commit python-unyt for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-unyt for openSUSE:Factory checked in at 2024-07-11 20:32:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-unyt (Old) and /work/SRC/openSUSE:Factory/.python-unyt.new.17339 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-unyt" Thu Jul 11 20:32:53 2024 rev:7 rq:1186726 version:3.0.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-unyt/python-unyt.changes 2024-03-17 22:16:31.285526201 +0100 +++ /work/SRC/openSUSE:Factory/.python-unyt.new.17339/python-unyt.changes 2024-07-11 20:33:32.573663889 +0200 @@ -1,0 +2,8 @@ +Thu Jul 11 02:42:33 UTC 2024 - Steve Kowalik <steven.kowalik@suse.com> + +- Update to 3.0.3: + * BUG: fix signature incompatibilities in NEP 18 wrapped functions + * BUG: fix an incompatibility with sympy 1.13.0rc1 +- Restrict numpy to < 2. + +------------------------------------------------------------------- Old: ---- unyt-3.0.2.tar.gz New: ---- unyt-3.0.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-unyt.spec ++++++ --- /var/tmp/diff_new_pack.h4XyE8/_old 2024-07-11 20:33:33.141684645 +0200 +++ /var/tmp/diff_new_pack.h4XyE8/_new 2024-07-11 20:33:33.145684792 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-unyt -Version: 3.0.2 +Version: 3.0.3 Release: 0 Summary: A package for handling numpy arrays with units License: BSD-3-Clause @@ -33,12 +33,12 @@ # SECTION test BuildRequires: %{python_module dask-array} BuildRequires: %{python_module dask-diagnostics} -BuildRequires: %{python_module numpy >= 1.19.3} +BuildRequires: %{python_module numpy >= 1.19.3 with %python-numpy < 2} BuildRequires: %{python_module packaging >= 20.9} BuildRequires: %{python_module pytest} BuildRequires: %{python_module sympy >= 1.7} # /SECTION -Requires: python-numpy >= 1.19.3 +Requires: (python-numpy >= 1.19.3 with python-numpy < 2) Requires: python-packaging > 20.9 Requires: python-sympy >= 1.7 BuildArch: noarch ++++++ unyt-3.0.2.tar.gz -> unyt-3.0.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/.github/workflows/ci.yml new/unyt-3.0.3/.github/workflows/ci.yml --- old/unyt-3.0.2/.github/workflows/ci.yml 2024-01-28 09:32:56.000000000 +0100 +++ new/unyt-3.0.3/.github/workflows/ci.yml 2024-07-01 19:41:17.000000000 +0200 @@ -24,7 +24,8 @@ - '3.12' # Test all on ubuntu, test ends on macos and windows include: - - os: macos-latest + - os: macos-12 + # pin macos-12 (x86) because Python 3.9 is broken in the arm64 image python-version: '3.9' - os: windows-latest python-version: '3.9' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/.pre-commit-config.yaml new/unyt-3.0.3/.pre-commit-config.yaml --- old/unyt-3.0.2/.pre-commit-config.yaml 2024-02-24 15:11:41.000000000 +0100 +++ new/unyt-3.0.3/.pre-commit-config.yaml 2024-07-02 15:31:26.000000000 +0200 @@ -10,7 +10,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -21,18 +21,18 @@ - id: check-toml - repo: https://github.com/psf/black - rev: 24.1.1 + rev: 24.4.2 hooks: - id: black - repo: https://github.com/adamchainz/blacken-docs - rev: 1.16.0 + rev: 1.18.0 hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.0 + rev: v0.5.0 hooks: - id: ruff args: [--fix, --show-fixes] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/CONTRIBUTING.rst new/unyt-3.0.3/CONTRIBUTING.rst --- old/unyt-3.0.2/CONTRIBUTING.rst 2024-01-27 13:22:26.000000000 +0100 +++ new/unyt-3.0.3/CONTRIBUTING.rst 2024-07-01 19:41:17.000000000 +0200 @@ -106,7 +106,7 @@ $ cd unyt/ $ pyenv local 3.10 - $ python setup.py develop + $ python -m pip install -e 5. Create a branch for local development:: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/HISTORY.rst new/unyt-3.0.3/HISTORY.rst --- old/unyt-3.0.2/HISTORY.rst 2024-03-13 07:25:16.000000000 +0100 +++ new/unyt-3.0.3/HISTORY.rst 2024-07-02 15:38:31.000000000 +0200 @@ -2,6 +2,35 @@ History ======= +3.0.3 (2024-07-02) +------------------ + +This new bugfix release of ``unyt`` fixes bugs discovered since the v3.0.2 release. + +* Fix defects when running test suite in isolation from the project's pytest + configuration (`PR #495 <https://github.com/yt-project/unyt/pull/495>`_). Thank you + to Clément Robert (@neutrinoceros on GitHub) for the contribution. + +* Drop test case for unpickling old pickle files as too sensitive to upstream changes + (`PR #498 <https://github.com/yt-project/unyt/pull/498>`_). Thank you to Clément + Robert (@neutrinoceros on GitHub) for the contribution. + +* Fix signature incompatibilities in nep 18 wrapped functions (`PR #500 + <https://github.com/yt-project/unyt/pull/500>`_). Thank you to Clément Robert + (@neutrinoceros on GitHub) for the contribution. + +* Fix an incompatibility with sympy 1.13.0rc1 (`PR #504 + <https://github.com/yt-project/unyt/pull/504>`_). Thank you to Clément Robert + (@neutrinoceros on GitHub) for the contribution. + +* Adjust doctests to changes in array repr from numpy 2.0 (`PR #506 + <https://github.com/yt-project/unyt/pull/506>`_). Thank you to Clément Robert + (@neutrinoceros on GitHub) for the contribution. + +* TST: declare np.unstack as subclass-safe (fix incompatibility with Numpy 2.1) + (`PR #509 <https://github.com/yt-project/unyt/pull/509>`_). Thank you to + Clément Robert (@neutrinoceros on GitHub) for the contribution. + 3.0.2 (2024-03-13) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/PKG-INFO new/unyt-3.0.3/PKG-INFO --- old/unyt-3.0.2/PKG-INFO 2024-03-13 07:33:56.847813000 +0100 +++ new/unyt-3.0.3/PKG-INFO 2024-07-02 15:39:56.505619300 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: unyt -Version: 3.0.2 +Version: 3.0.3 Summary: A package for handling numpy arrays with units Author-email: The yt project <yt-dev@python.org> License: BSD-3-Clause diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/docs/extensions/show_all_units.py new/unyt-3.0.3/docs/extensions/show_all_units.py --- old/unyt-3.0.2/docs/extensions/show_all_units.py 2024-01-27 13:22:26.000000000 +0100 +++ new/unyt-3.0.3/docs/extensions/show_all_units.py 2024-06-26 16:21:25.000000000 +0200 @@ -175,22 +175,14 @@ start_of_line = start_of_line.translate(to_separator) vertical_separator = vertical_separator.translate(to_separator) end_of_line = end_of_line.translate(to_separator) - separator = "{}{}{}".format( - start_of_line, - vertical_separator.join([x * line_marker for x in sizes]), - end_of_line, - ) + separator = f"{start_of_line}{vertical_separator.join([x * line_marker for x in sizes])}{end_of_line}" # determine header separator th_separator_tr = maketrans("-", "=") start_of_line = start_of_line.translate(th_separator_tr) line_marker = line_marker.translate(th_separator_tr) vertical_separator = vertical_separator.translate(th_separator_tr) end_of_line = end_of_line.translate(th_separator_tr) - th_separator = "{}{}{}".format( - start_of_line, - vertical_separator.join([x * line_marker for x in sizes]), - end_of_line, - ) + th_separator = f"{start_of_line}{vertical_separator.join([x * line_marker for x in sizes])}{end_of_line}" # prepare result table.append(separator) # set table header diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/docs/usage.rst new/unyt-3.0.3/docs/usage.rst --- old/unyt-3.0.2/docs/usage.rst 2024-01-27 13:22:26.000000000 +0100 +++ new/unyt-3.0.3/docs/usage.rst 2024-07-01 19:41:17.000000000 +0200 @@ -1494,7 +1494,7 @@ One important caveat is that using Dask array functions may strip units: >>> da.sum(x_da).compute() - 49995000 + np.int64(49995000) For simple reductions, you can use the :mod:`reduce_with_units` function: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/pyproject.toml new/unyt-3.0.3/pyproject.toml --- old/unyt-3.0.2/pyproject.toml 2024-03-13 07:25:16.000000000 +0100 +++ new/unyt-3.0.3/pyproject.toml 2024-07-01 19:41:17.000000000 +0200 @@ -124,7 +124,6 @@ "error", "ignore:Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.:UserWarning", "ignore:FigureCanvasAgg is non-interactive, and thus cannot be shown:UserWarning", - "ignore:In accordance with NEP 32:DeprecationWarning", "ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning", 'ignore:datetime\.datetime\.utcfromtimestamp\(\) is deprecated:DeprecationWarning', # https://github.com/dateutil/dateutil/pull/1285 'ignore:mpnumeric is deprecated:DeprecationWarning', # sympy 1.12 VS mpmath 1.4, solution: https://github.com/sympy/sympy/pull/25290 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/tox.ini new/unyt-3.0.3/tox.ini --- old/unyt-3.0.2/tox.ini 2024-01-27 13:22:26.000000000 +0100 +++ new/unyt-3.0.3/tox.ini 2024-07-01 19:41:17.000000000 +0200 @@ -20,8 +20,8 @@ deps = pytest h5py - pint - astropy + !py39: pint + !py39: astropy!=6.1.1 coverage[toml]>=5.0 pytest-cov pytest-doctestplus @@ -32,6 +32,14 @@ pytest --cov=unyt --cov-append --doctest-modules --doctest-plus --doctest-rst --basetemp={envtmpdir} coverage report --omit='.tox/*' +[testenv:py39] +# skip doctest on py39 because doctests require numpy>=2.0 and all optional deps, +# but some of our optional deps (pint, astropy) don't have a version that support +# both numpy>=2.0 and Python 3.9 +commands= + pytest --cov=unyt --cov-append --basetemp={envtmpdir} + coverage report --omit='.tox/*' + [testenv:py39-versions] deps = docutils diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/_array_functions.py new/unyt-3.0.3/unyt/_array_functions.py --- old/unyt-3.0.2/unyt/_array_functions.py 2024-02-25 09:14:12.000000000 +0100 +++ new/unyt-3.0.3/unyt/_array_functions.py 2024-07-02 15:31:26.000000000 +0200 @@ -272,57 +272,57 @@ @implements(np.intersect1d) -def intersect1d(arr1, arr2, /, assume_unique=False, return_indices=False): - _validate_units_consistency((arr1, arr2)) +def intersect1d(ar1, ar2, assume_unique=False, return_indices=False): + _validate_units_consistency((ar1, ar2)) retv = np.intersect1d._implementation( - np.asarray(arr1), - np.asarray(arr2), + np.asarray(ar1), + np.asarray(ar2), assume_unique=assume_unique, return_indices=return_indices, ) if return_indices: return retv else: - return retv * arr1.units + return retv * ar1.units @implements(np.union1d) -def union1d(arr1, arr2, /): - _validate_units_consistency((arr1, arr2)) - return np.union1d._implementation(np.asarray(arr1), np.asarray(arr2)) * arr1.units +def union1d(ar1, ar2): + _validate_units_consistency((ar1, ar2)) + return np.union1d._implementation(np.asarray(ar1), np.asarray(ar2)) * ar1.units @implements(np.linalg.norm) -def norm(x, /, *args, **kwargs): +def norm(x, *args, **kwargs): return np.linalg.norm._implementation(np.asarray(x), *args, **kwargs) * x.units @implements(np.vstack) -def vstack(tup, /): +def vstack(tup, **kwargs): ret_units = _validate_units_consistency(tup) - return np.vstack._implementation([np.asarray(_) for _ in tup]) * ret_units + return np.vstack._implementation([np.asarray(_) for _ in tup], **kwargs) * ret_units @implements(np.hstack) -def hstack(tup, /): +def hstack(tup, **kwargs): ret_units = _validate_units_consistency(tup) - return np.vstack._implementation([np.asarray(_) for _ in tup]) * ret_units + return np.vstack._implementation([np.asarray(_) for _ in tup], **kwargs) * ret_units @implements(np.dstack) -def dstack(tup, /): +def dstack(tup): ret_units = _validate_units_consistency(tup) return np.dstack._implementation([np.asarray(_) for _ in tup]) * ret_units @implements(np.column_stack) -def column_stack(tup, /): +def column_stack(tup): ret_units = _validate_units_consistency(tup) return np.column_stack._implementation([np.asarray(_) for _ in tup]) * ret_units @implements(np.stack) -def stack(arrays, /, axis=0, out=None): +def stack(arrays, axis=0, out=None, **kwargs): ret_units = _validate_units_consistency(arrays) if out is None: return ( @@ -330,7 +330,7 @@ * ret_units ) res = np.stack._implementation( - [np.asarray(_) for _ in arrays], axis=axis, out=np.asarray(out) + [np.asarray(_) for _ in arrays], axis=axis, out=np.asarray(out), **kwargs ) if getattr(out, "units", None) is not None: out.units = ret_units @@ -678,8 +678,8 @@ @implements(np.ediff1d) -def ediff1d(a, *args, **kwargs): - return diff_helper(np.ediff1d, a, *args, **kwargs) +def ediff1d(ary, *args, **kwargs): + return diff_helper(np.ediff1d, ary, *args, **kwargs) @implements(np.ptp) @@ -874,7 +874,8 @@ @implements(np.einsum) -def einsum(subscripts, *operands, out=None, **kwargs): +def einsum(*operands, out=None, **kwargs): + subscripts, *operands = operands ret_units = _validate_units_consistency(operands) if out is not None: @@ -962,7 +963,7 @@ arr = np.asfarray._implementation(np.asarray(a), dtype=dtype) # noqa: NPY201 return arr * ret_units - _trapezoid_func = np.trapz + _trapezoid_func = np.trapz # noqa: NPY201 elif NUMPY_VERSION >= Version("2.0.0dev0"): # functions that were added in numpy 2.0.0 @@ -992,7 +993,7 @@ if hasattr(np, "in1d"): - @implements(np.in1d) + @implements(np.in1d) # noqa: NPY201 def in1d(ar1, ar2, *args, **kwargs): _validate_units_consistency((ar1, ar2)) return np.isin._implementation( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/_parsing.py new/unyt-3.0.3/unyt/_parsing.py --- old/unyt-3.0.2/unyt/_parsing.py 2024-02-24 15:11:41.000000000 +0100 +++ new/unyt-3.0.3/unyt/_parsing.py 2024-06-26 16:21:25.000000000 +0200 @@ -85,9 +85,6 @@ unit_expr, global_dict=global_dict, transformations=unit_text_transform ) except Exception as e: - msg = "Unit expression '{}' raised an error during parsing:\n{}".format( - unit_expr, - repr(e), - ) + msg = f"Unit expression '{unit_expr}' raised an error during parsing:\n{e!r}" raise UnitParseError(msg) return unit_expr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/_version.py new/unyt-3.0.3/unyt/_version.py --- old/unyt-3.0.2/unyt/_version.py 2024-03-13 07:33:56.000000000 +0100 +++ new/unyt-3.0.3/unyt/_version.py 2024-07-02 15:39:56.000000000 +0200 @@ -12,5 +12,5 @@ __version_tuple__: VERSION_TUPLE version_tuple: VERSION_TUPLE -__version__ = version = '3.0.2' -__version_tuple__ = version_tuple = (3, 0, 2) +__version__ = version = '3.0.3' +__version_tuple__ = version_tuple = (3, 0, 3) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/array.py new/unyt-3.0.3/unyt/array.py --- old/unyt-3.0.2/unyt/array.py 2024-03-12 16:09:51.000000000 +0100 +++ new/unyt-3.0.3/unyt/array.py 2024-07-01 19:41:17.000000000 +0200 @@ -1255,7 +1255,7 @@ >>> from unyt import km >>> data = [3, 8, 7]*km >>> print(np.argsort(data)) - [0 2 1] + [0 2 1] km >>> print(data.argsort()) [0 2 1] """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/exceptions.py new/unyt-3.0.3/unyt/exceptions.py --- old/unyt-3.0.2/unyt/exceptions.py 2024-01-27 13:22:26.000000000 +0100 +++ new/unyt-3.0.3/unyt/exceptions.py 2024-06-26 16:21:25.000000000 +0200 @@ -148,11 +148,10 @@ super().__init__() def __str__(self): - err = ( - "The %s unit system does not have a MKS current base unit" - % self.unit_system_name + return ( + f"The {self.unit_system_name} unit system does not have " + "a MKS current base unit" ) - return err class MKSCGSConversionError(UnytError): @@ -343,5 +342,5 @@ def __str__(self): return ( "Cannot create unit system with inconsistent mapping from " - "dimensions to units. Received:\n%s" % self.units_map + f"dimensions to units. Received:\n{self.units_map}" ) Binary files old/unyt-3.0.2/unyt/tests/data/unyt_array_sympy1.8.pickle and new/unyt-3.0.3/unyt/tests/data/unyt_array_sympy1.8.pickle differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/tests/test_array_functions.py new/unyt-3.0.3/unyt/tests/test_array_functions.py --- old/unyt-3.0.2/unyt/tests/test_array_functions.py 2024-02-25 09:14:12.000000000 +0100 +++ new/unyt-3.0.3/unyt/tests/test_array_functions.py 2024-07-02 15:31:26.000000000 +0200 @@ -1,5 +1,7 @@ # tests for NumPy __array_function__ support +import inspect import re +import warnings from importlib.metadata import version import numpy as np @@ -24,6 +26,13 @@ NUMPY_VERSION = Version(version("numpy")) + +VAR_POSITIONAL = inspect.Parameter.VAR_POSITIONAL +VAR_KEYWORD = inspect.Parameter.VAR_KEYWORD +POSITIONAL_ONLY = inspect.Parameter.POSITIONAL_ONLY +KEYWORD_ONLY = inspect.Parameter.KEYWORD_ONLY +POSITIONAL_OR_KEYWORD = inspect.Parameter.POSITIONAL_OR_KEYWORD + # this is a subset of NOT_HANDLED_FUNCTIONS for which there's nothing to do # because they don't apply to (real) numeric types # or they work as expected out of the box @@ -154,7 +163,7 @@ if NUMPY_VERSION >= Version("2.0.0dev0"): - # the followin all work out of the box (tested) + # the following all work out of the box (tested) NOOP_FUNCTIONS |= { np.linalg.cross, np.linalg.diagonal, @@ -175,6 +184,11 @@ np.vecdot, } +if NUMPY_VERSION >= Version("2.1.0dev0"): + NOOP_FUNCTIONS |= { + np.unstack, + } + # Functions for which behaviour is intentionally left to default IGNORED_FUNCTIONS = { np.i0, @@ -184,35 +198,47 @@ np.savez_compressed, } - +# map subsets of deprecated functions to the version they were removed +# so that we can drop the ones that are not present in any version we support DEPRECATED_FUNCTIONS = { - "alen", # deprecated in numpy 1.18, removed in 1.22 - "asscalar", # deprecated in numpy 1.18, removed in 1.22 - "fv", # deprecated in numpy 1.18, removed in 1.20 - "ipmt", # deprecated in numpy 1.18, removed in 1.20 - "irr", # deprecated in numpy 1.18, removed in 1.20 - "mirr", # deprecated in numpy 1.18, removed in 1.20 - "nper", # deprecated in numpy 1.18, removed in 1.20 - "npv", # deprecated in numpy 1.18, removed in 1.20 - "pmt", # deprecated in numpy 1.18, removed in 1.20 - "ppmt", # deprecated in numpy 1.18, removed in 1.20 - "pv", # deprecated in numpy 1.18, removed in 1.20 - "rank", # deprecated in numpy 1.10, removed in 1.18 - "rate", # deprecated in numpy 1.18, removed in 1.20 - "msort", # deprecated in numpy 1.24 - # numpy 1.25 deprecations - "product", - "cumproduct", - "round_", # removed in 2.0 - "sometrue", - "alltrue", + Version("1.20"): { + "fv", + "ipmt", + "irr", + "mirr", + "nper", + "npv", + "pmt", + "ppmt", + "pv", + "rate", + }, + Version("1.22"): { + "alen", + "asscalar", + }, + Version("2.0.0b1"): { + "msort", + "product", + "cumproduct", + "round_", + "sometrue", + "alltrue", + }, + # functions that are deprecated but not yet removed in any known version + # should be added here + Version("999.999.999"): set(), } NOT_HANDLED_FUNCTIONS = NOOP_FUNCTIONS | UNSUPPORTED_FUNCTIONS | IGNORED_FUNCTIONS -for func in DEPRECATED_FUNCTIONS: - if hasattr(np, func): - NOT_HANDLED_FUNCTIONS.add(getattr(np, func)) +with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + for removal_version, functions in DEPRECATED_FUNCTIONS.items(): + if NUMPY_VERSION >= removal_version: + continue + for func in functions: + NOT_HANDLED_FUNCTIONS.add(getattr(np, func)) def get_decorators(func): @@ -930,7 +956,7 @@ if NUMPY_VERSION >= Version("2.0.0dev0"): _trapezoid_func = np.trapezoid else: - _trapezoid_func = np.trapz + _trapezoid_func = np.trapz # noqa: NPY201 def test_trapezoid_no_x(): @@ -1202,16 +1228,25 @@ @pytest.mark.parametrize( - "func, args", + "func_name, args", [ - (np.split, (3, 2)), - (np.dsplit, (3,)), - (np.hsplit, (2,)), - (np.vsplit, (1,)), - (np.array_split, (3,)), + ("split", (3, 2)), + ("dsplit", (3,)), + ("hsplit", (2,)), + ("vsplit", (1,)), + ("array_split", (3,)), + pytest.param( + "unstack", + (), + marks=pytest.mark.skipif( + NUMPY_VERSION < Version("2.1.0dev0"), + reason="np.unstack is new in NumPy 2.1", + ), + ), ], ) -def test_xsplit(func, args): +def test_xsplit(func_name, args): + func = getattr(np, func_name) x = [ [ [ @@ -1404,7 +1439,7 @@ def test_savetxt(tmp_path): a = [1, 2, 3] * cm - with pytest.raises( + with pytest.warns( UserWarning, match=re.escape( "numpy.savetxt does not preserve units, " @@ -1685,14 +1720,14 @@ def test_in1d_mixed_units(): a = [1, 2, 3] * cm with pytest.raises(UnitInconsistencyError): - np.in1d([1, 2], a) + np.in1d([1, 2], a) # noqa: NPY201 @pytest.mark.filterwarnings("ignore:`in1d` is deprecated. Use `np.isin` instead.") def test_in1d(): a = [1, 2, 3] * cm b = [1, 2] * cm - assert np.all(np.in1d(b, a)) + assert np.all(np.in1d(b, a)) # noqa: NPY201 def test_place_mixed_units(): @@ -1965,3 +2000,146 @@ res = np.interp(_x * cm, _xp * cm, _fp * K) assert type(res) is unyt_array assert res.units == K + + +@pytest.mark.parametrize( + "target, helper", + sorted( + HANDLED_FUNCTIONS.items(), + key=lambda items: items[0].__name__, + ), + ids=lambda func: func.__name__, +) +class TestFunctionHelpersSignatureCompatibility: + """ + Check that a helper function's signature is *at least* as flexible + as the helped (target) function's. E.g., any argument that is allowed positionally, + or as keyword, by the target must be re-exposed *somehow* by the helper. + We explicitly allow helper's signature to be *more* flexible than the target signature + by allowing *args and **kwargs catch-all arguments, which we use to limit code + duplication, and also help with forward and backward compatibility. + See https://github.com/astropy/astropy/issues/15703 + """ + + # this test class is adapted from astropy.units + + @staticmethod + def have_catchall_argument(parameters, kind) -> bool: + return any(p.kind is kind for p in parameters.values()) + + @staticmethod + def get_param_group(parameters, kinds: list) -> list[str]: + return [name for name, p in parameters.items() if p.kind in kinds] + + def test_all_arguments_reexposed(self, target, helper): + try: + sig_target = inspect.signature(target) + except ValueError: + pytest.skip("Non Python function cannot be inspected at runtime") + + params_target = sig_target.parameters + sig_helper = inspect.signature(helper) + params_helper = sig_helper.parameters + + have_args_helper = self.have_catchall_argument(params_helper, VAR_POSITIONAL) + have_kwargs_helper = self.have_catchall_argument(params_helper, VAR_KEYWORD) + + args_helper = list(params_helper.items()) + + pos_helper = 0 + for nt, pt in params_target.items(): + kt = pt.kind + if kt in (POSITIONAL_ONLY, POSITIONAL_OR_KEYWORD): + assert pos_helper < len(args_helper), ( + "helper's signature is too short; " + "some arguments are not properly re-exposed" + ) + nh, ph = args_helper[pos_helper] + if (kh := ph.kind) is not VAR_POSITIONAL: + assert nh == nt, f"argument {nt!r} isn't re-exposed as positional" + assert kh is kt, ( + f"helper is not re-exposing argument {nt!r} properly:" + f"expected {kt}, got {kh}" + ) + pos_helper += 1 + continue + + if kt in (KEYWORD_ONLY, POSITIONAL_OR_KEYWORD): + if nt in params_helper: + kh = params_helper[nt].kind + assert kh is kt, ( + f"helper is not re-exposing argument {nt!r} properly: " + f"expected {kt}, got {kh}" + ) + elif kt is KEYWORD_ONLY: + assert ( + have_kwargs_helper + ), f"argument {nt!r} is not re-exposed as keyword" + elif kt is POSITIONAL_OR_KEYWORD: + assert ( + have_args_helper and have_kwargs_helper + ), f"argument {nt!r} is not re-exposed as positional-or-keyword" + elif kt is VAR_POSITIONAL: + assert have_args_helper, "helper is missing a catch-all *args argument" + elif kt is VAR_KEYWORD: + assert ( + have_kwargs_helper + ), "helper is missing a catch-all **kwargs argument" + + def test_known_arguments(self, target, helper): + # validate that all exposed arguments map to something in the target + try: + sig_target = inspect.signature(target) + except ValueError: + pytest.skip("Non Python function cannot be inspected at runtime") + + params_target = sig_target.parameters + sig_helper = inspect.signature(helper) + params_helper = sig_helper.parameters + + for kind in (POSITIONAL_ONLY, POSITIONAL_OR_KEYWORD): + args_target = self.get_param_group(params_helper, [kind]) + args_helper = self.get_param_group(params_helper, [kind]) + + if (nhelper := len(args_helper)) > (ntarget := len(args_target)): + unknown: list[str] = args_helper[ntarget:] + raise AssertionError( + f"Found unknown {kind} parameter(s) " + "in helper's signature: " + f"{unknown}, at position(s) {list(range(ntarget, nhelper))}" + ) + + # keyword-allowed + keyword_allowed_target = set( + self.get_param_group(params_target, [KEYWORD_ONLY, POSITIONAL_OR_KEYWORD]) + ) + keyword_allowed_helper = set( + self.get_param_group(params_helper, [KEYWORD_ONLY, POSITIONAL_OR_KEYWORD]) + ) + + # additional private keyword-only argument are allowed because + # they are only intended for testing purposes. + # For instance, quantile has such a parameter '_q_unit' + keyword_allowed_helper = { + name for name in keyword_allowed_helper if not name.startswith("_") + } + + diff = keyword_allowed_helper - keyword_allowed_target + assert not diff, ( + "Found some keyword-allowed parameters in helper " + f"that are unknown to target: {diff}" + ) + + # finally, check that default values are correctly replicated + for name, ph in params_helper.items(): + if name not in params_target: + # In a few cases, the helper defines names that are not in + # the target (e.g., a private name like _q_unit in quantile, + # or a *args, **kwargs that captures further arguments + # that do not matter. We let such cases slip by. + continue + pt = params_target[name] + assert ph.default == pt.default, ( + f"Default value mismatch for argument {name!r}. " + f"Helper has {ph.default!r}, target has {pt.default!r}" + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/tests/test_unyt_array.py new/unyt-3.0.3/unyt/tests/test_unyt_array.py --- old/unyt-3.0.2/unyt/tests/test_unyt_array.py 2024-03-12 16:09:51.000000000 +0100 +++ new/unyt-3.0.3/unyt/tests/test_unyt_array.py 2024-07-01 19:41:17.000000000 +0200 @@ -16,7 +16,6 @@ import shutil import tempfile from importlib.metadata import version -from pathlib import Path import numpy as np import pytest @@ -851,30 +850,6 @@ SYMPY_VERSION = Version(version("sympy")) -@pytest.mark.xfail( - condition=(SYMPY_VERSION == Version("1.12")), - reason="regression in sympy 1.12", - raises=AssertionError, - strict=True, -) -@pytest.mark.xfail( - condition=(SYMPY_VERSION in (Version("1.9"), Version("1.10"))), - reason="Not resolved upstream as of sympy 1.10", - raises=AttributeError, - strict=True, -) -def test_unpickling_old_array(): - # see https://github.com/sympy/sympy/issues/22241 - # the expected error is "AttributeError: 'One' object has no attribute '__dict__'" - PFILE = Path(__file__).parent / "data" / "unyt_array_sympy1.8.pickle" - with open(PFILE, "rb") as fh: - arr = pickle.load(fh) - - # this comparison fails with sympy==1.12 - # see https://github.com/sympy/sympy/issues/25134 - assert arr.units.dimensions == cm.dimensions - - def test_copy(): quan = unyt_quantity(1, "g") arr = unyt_array([1, 2, 3], "cm") @@ -1546,7 +1521,8 @@ reg.add("code_length", 10.0, dimensions.length) - warr = unyt_array(np.random.random((256, 256)), "code_length", registry=reg) + rng = np.random.default_rng() + warr = unyt_array(rng.random((256, 256)), "code_length", registry=reg) warr.write_hdf5("test.h5") @@ -1565,8 +1541,8 @@ # test code to overwrite existing dataset with data that has a different # shape - - warr = unyt_array(np.random.random((255, 255)), "code_length", registry=reg) + rng = np.random.default_rng() + warr = unyt_array(rng.random((255, 255)), "code_length", registry=reg) warr.write_hdf5("test.h5") @@ -2165,9 +2141,10 @@ curdir = os.getcwd() os.chdir(tmpdir) - a = unyt_array(np.random.random(10), "kpc") - b = unyt_array(np.random.random(10), "Msun") - c = unyt_array(np.random.random(10), "km/s") + rng = np.random.default_rng() + a = unyt_array(rng.random(10), "kpc") + b = unyt_array(rng.random(10), "Msun") + c = unyt_array(rng.random(10), "km/s") savetxt("arrays.dat", [a, b, c], delimiter=",") @@ -2221,8 +2198,9 @@ def test_trig_ufunc_degrees(): + rng = np.random.default_rng() for ufunc in (np.sin, np.cos, np.tan): - degree_values = np.random.random(10) * degree + degree_values = rng.random(10) * degree radian_values = degree_values.in_units("radian") assert_array_equal(ufunc(degree_values), ufunc(radian_values)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/unit_object.py new/unyt-3.0.3/unyt/unit_object.py --- old/unyt-3.0.2/unyt/unit_object.py 2024-02-24 15:11:41.000000000 +0100 +++ new/unyt-3.0.3/unyt/unit_object.py 2024-07-01 19:41:17.000000000 +0200 @@ -467,7 +467,7 @@ "Failed to cast it to a float." ) - if self.dimensions is logarithmic and p != 1.0: + if self.dimensions is logarithmic and p != 1: raise InvalidUnitOperation(f"Tried to raise '{self}' to power '{p}'") return Unit( @@ -988,9 +988,8 @@ return (float(base_value), dimensions) raise UnitParseError( - "Cannot parse for unit data from '%s'. Please supply" - " an expression of only Unit, Symbol, Pow, and Mul" - "objects." % str(unit_expr) + f"Cannot parse for unit data from {str(unit_expr)!r}. Please supply " + "an expression of only Unit, Symbol, Pow, and Mul objects." ) @@ -1006,15 +1005,15 @@ elif isinstance(dimensions, Pow): if not isinstance(dimensions.args[1], Number): raise UnitParseError( - "Dimensionality expression '%s' contains a " - "unit symbol as a power." % dimensions + f"Dimensionality expression '{dimensions}' contains a " + "unit symbol as a power." ) elif isinstance(dimensions, (Add, Number)): if not isinstance(dimensions, One): raise UnitParseError( "Only dimensions that are instances of Pow, " "Mul, or symbols in the base dimensions are " - "allowed. Got dimensions '%s'" % dimensions + f"allowed. Got dimensions '{dimensions}'" ) elif not isinstance(dimensions, Basic): raise UnitParseError(f"Bad dimensionality expression '{dimensions}'.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt/unit_registry.py new/unyt-3.0.3/unyt/unit_registry.py --- old/unyt-3.0.2/unyt/unit_registry.py 2024-02-24 15:11:41.000000000 +0100 +++ new/unyt-3.0.3/unyt/unit_registry.py 2024-06-26 16:21:25.000000000 +0200 @@ -179,8 +179,8 @@ if symbol not in self.lut: raise SymbolNotFoundError( - "Tried to remove the symbol '%s', but it does not exist " - "in this registry." % symbol + r"Tried to remove the symbol {symbol!r}, but it does not exist " + "in this registry." ) del self.lut[symbol] @@ -205,8 +205,8 @@ if symbol not in self.lut: raise SymbolNotFoundError( - "Tried to modify the symbol '%s', but it does not exist " - "in this registry." % symbol + f"Tried to modify the symbol {symbol!r}, but it does not exist " + "in this registry." ) if hasattr(base_value, "in_base"): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt.egg-info/PKG-INFO new/unyt-3.0.3/unyt.egg-info/PKG-INFO --- old/unyt-3.0.2/unyt.egg-info/PKG-INFO 2024-03-13 07:33:56.000000000 +0100 +++ new/unyt-3.0.3/unyt.egg-info/PKG-INFO 2024-07-02 15:39:56.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: unyt -Version: 3.0.2 +Version: 3.0.3 Summary: A package for handling numpy arrays with units Author-email: The yt project <yt-dev@python.org> License: BSD-3-Clause diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unyt-3.0.2/unyt.egg-info/SOURCES.txt new/unyt-3.0.3/unyt.egg-info/SOURCES.txt --- old/unyt-3.0.2/unyt.egg-info/SOURCES.txt 2024-03-13 07:33:56.000000000 +0100 +++ new/unyt-3.0.3/unyt.egg-info/SOURCES.txt 2024-07-02 15:39:56.000000000 +0200 @@ -91,5 +91,4 @@ unyt/tests/test_unyt_array.py unyt/tests/test_unyt_testing.py unyt/tests/data/__init__.py -unyt/tests/data/old_json_registry.txt -unyt/tests/data/unyt_array_sympy1.8.pickle \ No newline at end of file +unyt/tests/data/old_json_registry.txt \ No newline at end of file
participants (1)
-
Source-Sync