From ef5656d842459a6c338ee03ee422d7bd4b8beb61 Mon Sep 17 00:00:00 2001 From: John Zwinck Date: Tue, 21 Jul 2020 15:50:05 +0800 Subject: MAINT: Avoid exception in NpzFile destructor if constructor raises BadZipFile (#15604) Previously if you gave an invalid zip file to NpzFile, zipfile_factory would raise BadZipFile and NpzFile.__exit__ would be called, which accessed members which had not yet been set, leading to a confusing second exception like this: zipfile.BadZipFile: File is not a zip file Exception ignored in: Traceback (most recent call last): File "numpy/lib/npyio.py", line 230, in __del__ self.close() File "numpy/lib/npyio.py", line 221, in close if self.zip is not None: AttributeError: 'NpzFile' object has no attribute 'zip' This change makes __exit__ safe even when __init__ did not complete. --- numpy/lib/npyio.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 520e9c9ec..58affc2fc 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -178,6 +178,9 @@ class NpzFile(Mapping): array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) """ + # Make __exit__ safe if zipfile_factory raises an exception + zip = None + fid = None def __init__(self, fid, own_fid=False, allow_pickle=False, pickle_kwargs=None): @@ -197,8 +200,6 @@ class NpzFile(Mapping): self.f = BagObj(self) if own_fid: self.fid = fid - else: - self.fid = None def __enter__(self): return self -- cgit v1.2.1 From 4cd6e4b336fbc68d88c0e9bc45a435ce7b721f1f Mon Sep 17 00:00:00 2001 From: Peter Andreas Entschev Date: Fri, 28 Aug 2020 20:05:18 +0200 Subject: ENH: implement NEP-35's `like=` argument (gh-16935) This PR adds the implementation of NEP-35's like= argument, allowing dispatch of array creation functions with __array_function__ based on a reference array. * ENH: Add like= kwarg via __array_function__ dispatcher to asarray * ENH: Add new function for __array_function__ dispatching from C This new function allows dispatching from C directly, while also implementing the new `like=` argument, requiring only minimal changes to existing array creation functions that need to add support for that argument. * ENH: Add like= support to numpy.array The implementation uses array_implement_c_array_function, thus introducing minimal complexity to the original _array_fromobject code. * BUG: Fix like= dispatcher for np.full * ENH: Remove np.asarray like= dispatcher via Python np.asarray can rely on np.array's C dispatcher instead. * TST: Add some tests for like= argument Tests comprise some of the functions that have been implemented already: * np.array (C dispatcher) * np.asarray (indirect C dispatcher via np.array) * np.full (Python dispatcher) * np.ones (Python dispatcher) * ENH: Remove like= argument during array_implement_array_function * ENH: Add like= kwarg to ones and full * BUG: prevent duplicate removal of `like=` argument * ENH: Make `like=` a keyword-only argument * ENH: Use PyUnicode_InternFromString in arrayfunction_override Replace PyUnicode_FromString by PyUnicode_InternFromString to cache "like" string. * ENH: Check for arrayfunction_override import errors Check and handle errors on importing NumPy's Python functions * BUG: Fix array_implement_c_array_function error handling * ENH: Handle exceptions with C implementation of `like=` * ENH: Add `like=` dispatch for all asarray functions Using Python dispatcher for all of them. Using the C dispatcher directly on the `np.array` call can result in incorrect behavior. Incorrect behavior may happen if the downstream library's implementation is different or if not all keyword arguments are supported. * ENH: Simplify handling of exceptions with `like=` * TST: Add test for exception handling with `like=` * ENH: Add support for `like=` to `np.empty` and `np.zeros` * TST: Add `like=` tests for `np.empty` and `np.zeros` * ENH: Add `like=` to remaining multiarraymodule.c functions Functions are: * np.arange * np.frombuffer * np.fromfile * np.fromiter * np.fromstring * TST: Add tests for multiarraymodule.c functions with like= Functions are: * np.arange * np.frombuffer * np.fromfile * np.fromiter * np.fromstring * ENH: Add `like=` support to more creation functions Support for the following functions is added: * np.eye * np.fromfunction * np.genfromtxt * np.identity * np.loadtxt * np.tri * TST: Add `like=` tests for multiple functions Tests for the following functions are added: * np.eye * np.fromfunction * np.genfromtxt * np.identity * np.loadtxt * np.tri * TST: Reduce code duplication in `like=` tests * DOC: Document `like=` in functions that support it Add documentations for the following functions: * np.array * np.arange * np.asarray * np.asanyarray * np.ascontiguousarray * np.asfortranarray * np.require * np.empty * np.full * np.ones * np.zeros * np.identity * np.eye * np.tri * np.frombuffer * np.fromfile * np.fromiter * np.fromstring * np.loadtxt * np.genfromtxt * ENH: Add `like=` to numpy/__init__.pyi stubs * BUG: Remove duplicate `like=` dispatching in as*array Functions `np.asanyarray`, `np.contiguousarray` and `np.fortranarray` were dispatching both via their definitions and `np.array` calls, the latter should be avoided. * BUG: Fix missing check in array_implement_array_function * BUG: Add missing keyword-only markers in stubs * BUG: Fix duplicate keyword-only marker in array stub * BUG: Fix syntax error in numpy/__init__.pyi * BUG: Fix more syntax errors in numpy/__init__.pyi * ENH: Intern arrayfunction_override strings in multiarraymodule * STY: Add missing brackets to arrayfunction_override.c * MAINT: Remove arrayfunction_override dict check for kwarg * TST: Assert that 'like' is not in TestArrayLike kwargs * MAINT: Rename array_implement_c_array_function(_creation) This is done to be more explicit as to its usage being intended for array creation functions only. * MAINT: Use NotImplemented to indicate fallback to default * TST: Test that results with `like=np.array` are correct * TST: Avoid duplicating MyArray code in TestArrayLike * TST: Don't delete temp file, it may cause issues with Windows * TST: Don't rely on eval in TestArrayLike * TST: Use lambda with StringIO in TestArrayLike * ENH: Avoid unnecessary Py_XDECREF in arrayfunction_override * TST: Make TestArrayLike more readable * ENH: Cleaner error handling in arrayfunction_override * ENH: Simplify array_implement_c_array_function_creation * STY: Add missing spaces to multiarraymodule.c * STY: C99 declaration style in arrayfunction_override.c * ENH: Simplify arrayfunction_override.c further Remove cleanup label from array_implementation_c_array_function, simplifying the code. Fix unitialized variable warning in array_implementation_array_function_internal. * DOC: Use string replacement for `like=` documentation Avoid repeating the full text for the `like=` argument by storing it as a variable and using `replace` on each docstring. * DOC: Update `like=` docstring * TST: Test like= with array not implementing __array_function__ * TST: Add missing asanyarray to TestArrayLike * ENH: Use helper function for like= dispatching Avoid dispatching like= from Python implementation functions to improve their performance. This is achieved by only calling a dispatcher function when like is passed by the users. * ENH: Rename array_function_dispatch kwarg to public_api * BUG: Add accidentally removed decorator for np.eye back * DOC: Add set_array_function_like_doc function The function keeps Python files cleaner and resolve errors when __doc__ is not defined due to PYTHONOPTIMIZE or -OO . * DOC: Add mention to like= kwarg being experimental * TST: Test like= with not implemented downstream function * DOC: Fix like= docstring reference to NEP 35. * ENH: Prevent silent errors if public_api is not callable * ENH: Make set_array_function_like_doc a decorator * ENH: Simplify `_*_with_like` functions * BUG: Fix multiple `like=` dispatching in `require` * MAINT: Remove now unused public_api from array_function_dispatch Co-authored-by: Sebastian Berg --- numpy/lib/npyio.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 58affc2fc..cc3465cc6 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -14,7 +14,7 @@ from . import format from ._datasource import DataSource from numpy.core import overrides from numpy.core.multiarray import packbits, unpackbits -from numpy.core.overrides import set_module +from numpy.core.overrides import set_array_function_like_doc, set_module from numpy.core._internal import recursive from ._iotools import ( LineSplitter, NameValidator, StringConverter, ConverterError, @@ -790,10 +790,17 @@ def _getconv(dtype): _loadtxt_chunksize = 50000 +def _loadtxt_dispatcher(fname, dtype=None, comments=None, delimiter=None, + converters=None, skiprows=None, usecols=None, unpack=None, + ndmin=None, encoding=None, max_rows=None, *, like=None): + return (like,) + + +@set_array_function_like_doc @set_module('numpy') def loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, - ndmin=0, encoding='bytes', max_rows=None): + ndmin=0, encoding='bytes', max_rows=None, *, like=None): r""" Load data from a text file. @@ -860,6 +867,9 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, is to read all the lines. .. versionadded:: 1.16.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 Returns ------- @@ -917,6 +927,14 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, [-17.57, 63.94]]) """ + if like is not None: + return _loadtxt_with_like( + fname, dtype=dtype, comments=comments, delimiter=delimiter, + converters=converters, skiprows=skiprows, usecols=usecols, + unpack=unpack, ndmin=ndmin, encoding=encoding, + max_rows=max_rows, like=like + ) + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Nested functions used by loadtxt. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1201,6 +1219,11 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, return X +_loadtxt_with_like = array_function_dispatch( + _loadtxt_dispatcher +)(loadtxt) + + def _savetxt_dispatcher(fname, X, fmt=None, delimiter=None, newline=None, header=None, footer=None, comments=None, encoding=None): @@ -1554,6 +1577,18 @@ def fromregex(file, regexp, dtype, encoding=None): #####-------------------------------------------------------------------------- +def _genfromtxt_dispatcher(fname, dtype=None, comments=None, delimiter=None, + skip_header=None, skip_footer=None, converters=None, + missing_values=None, filling_values=None, usecols=None, + names=None, excludelist=None, deletechars=None, + replace_space=None, autostrip=None, case_sensitive=None, + defaultfmt=None, unpack=None, usemask=None, loose=None, + invalid_raise=None, max_rows=None, encoding=None, *, + like=None): + return (like,) + + +@set_array_function_like_doc @set_module('numpy') def genfromtxt(fname, dtype=float, comments='#', delimiter=None, skip_header=0, skip_footer=0, converters=None, @@ -1562,7 +1597,8 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, deletechars=''.join(sorted(NameValidator.defaultdeletechars)), replace_space='_', autostrip=False, case_sensitive=True, defaultfmt="f%i", unpack=None, usemask=False, loose=True, - invalid_raise=True, max_rows=None, encoding='bytes'): + invalid_raise=True, max_rows=None, encoding='bytes', *, + like=None): """ Load data from a text file, with missing values handled as specified. @@ -1659,6 +1695,9 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, to None the system default is used. The default value is 'bytes'. .. versionadded:: 1.14.0 + ${ARRAY_FUNCTION_LIKE} + + .. versionadded:: 1.20.0 Returns ------- @@ -1737,6 +1776,21 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, dtype=[('f0', 'S12'), ('f1', 'S12')]) """ + + if like is not None: + return _genfromtxt_with_like( + fname, dtype=dtype, comments=comments, delimiter=delimiter, + skip_header=skip_header, skip_footer=skip_footer, + converters=converters, missing_values=missing_values, + filling_values=filling_values, usecols=usecols, names=names, + excludelist=excludelist, deletechars=deletechars, + replace_space=replace_space, autostrip=autostrip, + case_sensitive=case_sensitive, defaultfmt=defaultfmt, + unpack=unpack, usemask=usemask, loose=loose, + invalid_raise=invalid_raise, max_rows=max_rows, encoding=encoding, + like=like + ) + if max_rows is not None: if skip_footer: raise ValueError( @@ -2250,6 +2304,11 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, return output.squeeze() +_genfromtxt_with_like = array_function_dispatch( + _genfromtxt_dispatcher +)(genfromtxt) + + def ndfromtxt(fname, **kwargs): """ Load ASCII data stored in a file and return it as a single array. -- cgit v1.2.1 From 8a4fafa5278c2d894cf4efd40a342b33e941e373 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 31 Aug 2020 10:23:54 +0100 Subject: MAINT: Remove users of `numpy.compat.bytes` Some more Python 2 cleanup. --- numpy/lib/npyio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index cc3465cc6..d1a29ffad 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -23,7 +23,7 @@ from ._iotools import ( ) from numpy.compat import ( - asbytes, asstr, asunicode, bytes, os_fspath, os_PathLike, + asbytes, asstr, asunicode, os_fspath, os_PathLike, pickle, contextlib_nullcontext ) -- cgit v1.2.1 From 1f8ce6341159ebb0731c2c262f4576609210d2c8 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Wed, 2 Sep 2020 21:01:35 +0300 Subject: MAINT, DOC: move informational files from numpy.doc.*.py to their *.rst counterparts (#17222) * DOC: redistribute docstring-only content from numpy/doc * DOC: post-transition clean-up * DOC, MAINT: reskip doctests, fix a few easy ones --- numpy/lib/npyio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index cc3465cc6..da0b0b114 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -1520,7 +1520,7 @@ def fromregex(file, regexp, dtype, encoding=None): ----- Dtypes for structured arrays can be specified in several forms, but all forms specify at least the data type and field name. For details see - `doc.structured_arrays`. + `basics.rec`. Examples -------- -- cgit v1.2.1 From d09e192f05fae7d2e13735c82714b0bc140a0d9f Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 2 Sep 2020 16:43:40 +0300 Subject: MAINT: Remove old sys.version_info code --- numpy/lib/npyio.py | 46 ++++++++-------------------------------------- 1 file changed, 8 insertions(+), 38 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index cc3465cc6..e0a288980 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -712,44 +712,14 @@ def _savez(file, args, kwds, compress, allow_pickle=True, pickle_kwargs=None): zipf = zipfile_factory(file, mode="w", compression=compression) - if sys.version_info >= (3, 6): - # Since Python 3.6 it is possible to write directly to a ZIP file. - for key, val in namedict.items(): - fname = key + '.npy' - val = np.asanyarray(val) - # always force zip64, gh-10776 - with zipf.open(fname, 'w', force_zip64=True) as fid: - format.write_array(fid, val, - allow_pickle=allow_pickle, - pickle_kwargs=pickle_kwargs) - else: - # Stage arrays in a temporary file on disk, before writing to zip. - - # Import deferred for startup time improvement - import tempfile - # Since target file might be big enough to exceed capacity of a global - # temporary directory, create temp file side-by-side with the target file. - file_dir, file_prefix = os.path.split(file) if _is_string_like(file) else (None, 'tmp') - fd, tmpfile = tempfile.mkstemp(prefix=file_prefix, dir=file_dir, suffix='-numpy.npy') - os.close(fd) - try: - for key, val in namedict.items(): - fname = key + '.npy' - fid = open(tmpfile, 'wb') - try: - format.write_array(fid, np.asanyarray(val), - allow_pickle=allow_pickle, - pickle_kwargs=pickle_kwargs) - fid.close() - fid = None - zipf.write(tmpfile, arcname=fname) - except IOError as exc: - raise IOError("Failed to write to %s: %s" % (tmpfile, exc)) - finally: - if fid: - fid.close() - finally: - os.remove(tmpfile) + for key, val in namedict.items(): + fname = key + '.npy' + val = np.asanyarray(val) + # always force zip64, gh-10776 + with zipf.open(fname, 'w', force_zip64=True) as fid: + format.write_array(fid, val, + allow_pickle=allow_pickle, + pickle_kwargs=pickle_kwargs) zipf.close() -- cgit v1.2.1 From 3329d26c5d1d53f7fca1dfe253fdc43e93f0f6aa Mon Sep 17 00:00:00 2001 From: Andrew Eckart Date: Fri, 11 Sep 2020 11:31:03 -0500 Subject: ENH: Allow genfromtxt to unpack structured arrays (#16650) * ENH: Allow genfromtxt to unpack structured arrays genfromtxt failed to transpose output when unpack=True and `dtype` was structured (or None). This patch resolves the issue by returning a list of arrays, as in `loadtxt`. Co-authored-by: Matti Picus Co-authored-by: Eric Wieser Co-authored-by: Sebastian Berg Co-authored-by: Ross Barnowski --- numpy/lib/npyio.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index c6a19fda9..90e16643c 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -815,8 +815,9 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, fourth column the same way as ``usecols = (3,)`` would. unpack : bool, optional If True, the returned array is transposed, so that arguments may be - unpacked using ``x, y, z = loadtxt(...)``. When used with a structured - data-type, arrays are returned for each field. Default is False. + unpacked using ``x, y, z = loadtxt(...)``. When used with a + structured data-type, arrays are returned for each field. + Default is False. ndmin : int, optional The returned array will have at least `ndmin` dimensions. Otherwise mono-dimensional axes will be squeezed. @@ -1640,7 +1641,9 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, If 'lower', field names are converted to lower case. unpack : bool, optional If True, the returned array is transposed, so that arguments may be - unpacked using ``x, y, z = loadtxt(...)`` + unpacked using ``x, y, z = genfromtxt(...)``. When used with a + structured data-type, arrays are returned for each field. + Default is False. usemask : bool, optional If True, return a masked array. If False, return a regular array. @@ -2269,9 +2272,18 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, if usemask: output = output.view(MaskedArray) output._mask = outputmask + output = np.squeeze(output) if unpack: - return output.squeeze().T - return output.squeeze() + if names is None: + return output.T + elif len(names) == 1: + # squeeze single-name dtypes too + return output[names[0]] + else: + # For structured arrays with multiple fields, + # return an array for each field. + return [output[field] for field in names] + return output _genfromtxt_with_like = array_function_dispatch( -- cgit v1.2.1 From 260f2f144018f1c4c3de171160dc53b5c642b205 Mon Sep 17 00:00:00 2001 From: Bijesh Mohan Date: Wed, 16 Sep 2020 20:04:09 +0530 Subject: MAINT: Chaining exceptions in npyio.py --- numpy/lib/npyio.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 90e16643c..805e59bc1 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -86,7 +86,7 @@ class BagObj: try: return object.__getattribute__(self, '_obj')[key] except KeyError: - raise AttributeError(key) + raise AttributeError(key) from None def __dir__(self): """ @@ -446,9 +446,9 @@ def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, "when allow_pickle=False") try: return pickle.load(fid, **pickle_kwargs) - except Exception: + except Exception as e: raise IOError( - "Failed to interpret file %s as a pickle" % repr(file)) + "Failed to interpret file %s as a pickle" % repr(file)) from e def _save_dispatcher(file, arr, allow_pickle=None, fix_imports=None): @@ -1435,10 +1435,10 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', for row in X: try: v = format % tuple(row) + newline - except TypeError: + except TypeError as e: raise TypeError("Mismatch between array dtype ('%s') and " "format specifier ('%s')" - % (str(X.dtype), format)) + % (str(X.dtype), format)) from e fh.write(v) if len(footer) > 0: -- cgit v1.2.1 From b88b2c0c19851810d4ee07f03a7734b6e19dbdaa Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Wed, 18 Nov 2020 22:56:16 -0800 Subject: MAINT: Minor touchups in npyio (#17796) * Simplify logic for encoding kwarg in _decode_line. * Remove unnecessary else branch from split_line. * MAINT: rm else branch from loadtxt. * MAINT: re-nest encoding parsing. Co-Authored-By: mattip * condense return statement. Co-authored-by: mattip --- numpy/lib/npyio.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 805e59bc1..3b2de3e61 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -965,10 +965,7 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, if comments is not None: line = regex_comments.split(line, maxsplit=1)[0] line = line.strip('\r\n') - if line: - return line.split(delimiter) - else: - return [] + return line.split(delimiter) if line else [] def read_data(chunk_size): """Parse each line, including the first. @@ -1030,11 +1027,10 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, user_converters = converters + byte_converters = False if encoding == 'bytes': encoding = None byte_converters = True - else: - byte_converters = False if usecols is not None: # Allow usecols to be a single int or a sequence of ints -- cgit v1.2.1 From b2778a8a6d99dfbfee8f09daf6c069d1acf1aa8d Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Sat, 5 Dec 2020 13:22:39 +0100 Subject: MAINT: Replace `contextlib_nullcontext` with `contextlib.nullcontext` --- numpy/lib/npyio.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'numpy/lib/npyio.py') diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 3b2de3e61..af8e28e42 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -24,7 +24,7 @@ from ._iotools import ( from numpy.compat import ( asbytes, asstr, asunicode, os_fspath, os_PathLike, - pickle, contextlib_nullcontext + pickle ) @@ -517,7 +517,7 @@ def save(file, arr, allow_pickle=True, fix_imports=True): # [1 2] [1 3] """ if hasattr(file, 'write'): - file_ctx = contextlib_nullcontext(file) + file_ctx = contextlib.nullcontext(file) else: file = os_fspath(file) if not file.endswith('.npy'): @@ -1792,7 +1792,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, fid_ctx = contextlib.closing(fid) else: fid = fname - fid_ctx = contextlib_nullcontext(fid) + fid_ctx = contextlib.nullcontext(fid) fhd = iter(fid) except TypeError as e: raise TypeError( -- cgit v1.2.1