summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/compat/py3k.py25
-rw-r--r--numpy/core/_add_newdocs.py69
-rw-r--r--numpy/core/_aliased_types.py0
-rw-r--r--numpy/core/memmap.py134
-rw-r--r--numpy/lib/npyio.py27
5 files changed, 171 insertions, 84 deletions
diff --git a/numpy/compat/py3k.py b/numpy/compat/py3k.py
index d5bb2e4c7..ce4543bc3 100644
--- a/numpy/compat/py3k.py
+++ b/numpy/compat/py3k.py
@@ -7,7 +7,8 @@ from __future__ import division, absolute_import, print_function
__all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested',
'asstr', 'open_latin1', 'long', 'basestring', 'sixu',
- 'integer_types', 'is_pathlib_path', 'npy_load_module', 'Path']
+ 'integer_types', 'is_pathlib_path', 'npy_load_module', 'Path',
+ 'contextlib_nullcontext']
import sys
try:
@@ -97,6 +98,28 @@ def is_pathlib_path(obj):
"""
return Path is not None and isinstance(obj, Path)
+# from Python 3.7
+class contextlib_nullcontext(object):
+ """Context manager that does no additional processing.
+
+ Used as a stand-in for a normal context manager, when a particular
+ block of code is only sometimes used with a normal context manager:
+
+ cm = optional_cm if condition else nullcontext()
+ with cm:
+ # Perform operation, using optional_cm if condition is True
+ """
+
+ def __init__(self, enter_result=None):
+ self.enter_result = enter_result
+
+ def __enter__(self):
+ return self.enter_result
+
+ def __exit__(self, *excinfo):
+ pass
+
+
if sys.version_info[0] >= 3 and sys.version_info[1] >= 4:
def npy_load_module(name, fn, info=None):
"""
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index d4b6765d0..1c82cfde4 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -7968,7 +7968,74 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('view',
##############################################################################
#
-# Documentation for other scalar classes
+# Documentation for scalar type abstract base classes in type hierarchy
+#
+##############################################################################
+
+
+add_newdoc('numpy.core.numerictypes', 'number',
+ """
+ Abstract base class of all numeric scalar types.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'integer',
+ """
+ Abstract base class of all integer scalar types.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'signedinteger',
+ """
+ Abstract base class of all signed integer scalar types.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'unsignedinteger',
+ """
+ Abstract base class of all unsigned integer scalar types.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'inexact',
+ """
+ Abstract base class of all numeric scalar types with a (potentially)
+ inexact representation of the values in its range, such as
+ floating-point numbers.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'floating',
+ """
+ Abstract base class of all floating-point scalar types.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'complexfloating',
+ """
+ Abstract base class of all complex number scalar types that are made up of
+ floating-point numbers.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'flexible',
+ """
+ Abstract base class of all scalar types without predefined length.
+ The actual size of these types depends on the specific `np.dtype`
+ instantiation.
+
+ """)
+
+add_newdoc('numpy.core.numerictypes', 'character',
+ """
+ Abstract base class of all character string scalar types.
+
+ """)
+
+
+##############################################################################
+#
+# Documentation for concrete scalar classes
#
##############################################################################
diff --git a/numpy/core/_aliased_types.py b/numpy/core/_aliased_types.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/numpy/core/_aliased_types.py
diff --git a/numpy/core/memmap.py b/numpy/core/memmap.py
index 536fa6094..8269f537f 100644
--- a/numpy/core/memmap.py
+++ b/numpy/core/memmap.py
@@ -2,7 +2,9 @@ from __future__ import division, absolute_import, print_function
import numpy as np
from .numeric import uint8, ndarray, dtype
-from numpy.compat import long, basestring, is_pathlib_path
+from numpy.compat import (
+ long, basestring, is_pathlib_path, contextlib_nullcontext
+)
__all__ = ['memmap']
@@ -211,78 +213,72 @@ class memmap(ndarray):
raise ValueError("mode must be one of %s" %
(valid_filemodes + list(mode_equivalents.keys())))
- if hasattr(filename, 'read'):
- fid = filename
- own_file = False
- elif is_pathlib_path(filename):
- fid = filename.open((mode == 'c' and 'r' or mode)+'b')
- own_file = True
- else:
- fid = open(filename, (mode == 'c' and 'r' or mode)+'b')
- own_file = True
-
- if (mode == 'w+') and shape is None:
+ if mode == 'w+' and shape is None:
raise ValueError("shape must be given")
- fid.seek(0, 2)
- flen = fid.tell()
- descr = dtypedescr(dtype)
- _dbytes = descr.itemsize
-
- if shape is None:
- bytes = flen - offset
- if (bytes % _dbytes):
- fid.close()
- raise ValueError("Size of available data is not a "
- "multiple of the data-type size.")
- size = bytes // _dbytes
- shape = (size,)
- else:
- if not isinstance(shape, tuple):
- shape = (shape,)
- size = np.intp(1) # avoid default choice of np.int_, which might overflow
- for k in shape:
- size *= k
-
- bytes = long(offset + size*_dbytes)
-
- if mode == 'w+' or (mode == 'r+' and flen < bytes):
- fid.seek(bytes - 1, 0)
- fid.write(b'\0')
- fid.flush()
-
- if mode == 'c':
- acc = mmap.ACCESS_COPY
- elif mode == 'r':
- acc = mmap.ACCESS_READ
- else:
- acc = mmap.ACCESS_WRITE
-
- start = offset - offset % mmap.ALLOCATIONGRANULARITY
- bytes -= start
- array_offset = offset - start
- mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
-
- self = ndarray.__new__(subtype, shape, dtype=descr, buffer=mm,
- offset=array_offset, order=order)
- self._mmap = mm
- self.offset = offset
- self.mode = mode
-
- if isinstance(filename, basestring):
- self.filename = os.path.abspath(filename)
+ if hasattr(filename, 'read'):
+ f_ctx = contextlib_nullcontext(filename)
elif is_pathlib_path(filename):
- self.filename = filename.resolve()
- # py3 returns int for TemporaryFile().name
- elif (hasattr(filename, "name") and
- isinstance(filename.name, basestring)):
- self.filename = os.path.abspath(filename.name)
- # same as memmap copies (e.g. memmap + 1)
+ f_ctx = filename.open(('r' if mode == 'c' else mode)+'b')
else:
- self.filename = None
-
- if own_file:
- fid.close()
+ f_ctx = open(filename, ('r' if mode == 'c' else mode)+'b')
+
+ with f_ctx as fid:
+ fid.seek(0, 2)
+ flen = fid.tell()
+ descr = dtypedescr(dtype)
+ _dbytes = descr.itemsize
+
+ if shape is None:
+ bytes = flen - offset
+ if bytes % _dbytes:
+ raise ValueError("Size of available data is not a "
+ "multiple of the data-type size.")
+ size = bytes // _dbytes
+ shape = (size,)
+ else:
+ if not isinstance(shape, tuple):
+ shape = (shape,)
+ size = np.intp(1) # avoid default choice of np.int_, which might overflow
+ for k in shape:
+ size *= k
+
+ bytes = long(offset + size*_dbytes)
+
+ if mode == 'w+' or (mode == 'r+' and flen < bytes):
+ fid.seek(bytes - 1, 0)
+ fid.write(b'\0')
+ fid.flush()
+
+ if mode == 'c':
+ acc = mmap.ACCESS_COPY
+ elif mode == 'r':
+ acc = mmap.ACCESS_READ
+ else:
+ acc = mmap.ACCESS_WRITE
+
+ start = offset - offset % mmap.ALLOCATIONGRANULARITY
+ bytes -= start
+ array_offset = offset - start
+ mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
+
+ self = ndarray.__new__(subtype, shape, dtype=descr, buffer=mm,
+ offset=array_offset, order=order)
+ self._mmap = mm
+ self.offset = offset
+ self.mode = mode
+
+ if isinstance(filename, basestring):
+ self.filename = os.path.abspath(filename)
+ elif is_pathlib_path(filename):
+ self.filename = filename.resolve()
+ # py3 returns int for TemporaryFile().name
+ elif (hasattr(filename, "name") and
+ isinstance(filename.name, basestring)):
+ self.filename = os.path.abspath(filename.name)
+ # same as memmap copies (e.g. memmap + 1)
+ else:
+ self.filename = None
return self
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index 9a7b244ac..73cf5554a 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -380,16 +380,6 @@ def load(file, mmap_mode=None, allow_pickle=True, fix_imports=True,
memmap([4, 5, 6])
"""
- own_fid = False
- if isinstance(file, basestring):
- fid = open(file, "rb")
- own_fid = True
- elif is_pathlib_path(file):
- fid = file.open("rb")
- own_fid = True
- else:
- fid = file
-
if encoding not in ('ASCII', 'latin1', 'bytes'):
# The 'encoding' value for pickle also affects what encoding
# the serialized binary data of NumPy arrays is loaded
@@ -410,6 +400,17 @@ def load(file, mmap_mode=None, allow_pickle=True, fix_imports=True,
# Nothing to do on Python 2
pickle_kwargs = {}
+ # TODO: Use contextlib.ExitStack once we drop Python 2
+ if isinstance(file, basestring):
+ fid = open(file, "rb")
+ own_fid = True
+ elif is_pathlib_path(file):
+ fid = file.open("rb")
+ own_fid = True
+ else:
+ fid = file
+ own_fid = False
+
try:
# Code to distinguish from NumPy binary files and pickles.
_ZIP_PREFIX = b'PK\x03\x04'
@@ -422,10 +423,10 @@ def load(file, mmap_mode=None, allow_pickle=True, fix_imports=True,
if magic.startswith(_ZIP_PREFIX) or magic.startswith(_ZIP_SUFFIX):
# zip-file (assume .npz)
# Transfer file ownership to NpzFile
- tmp = own_fid
+ ret = NpzFile(fid, own_fid=own_fid, allow_pickle=allow_pickle,
+ pickle_kwargs=pickle_kwargs)
own_fid = False
- return NpzFile(fid, own_fid=tmp, allow_pickle=allow_pickle,
- pickle_kwargs=pickle_kwargs)
+ return ret
elif magic == format.MAGIC_PREFIX:
# .npy file
if mmap_mode: