From e43f66cd41514d60210bdfa082ecae3c18ea01ac Mon Sep 17 00:00:00 2001 From: grayson-helmholz <107720976+grayson-helmholz@users.noreply.github.com> Date: Fri, 11 Oct 2024 19:47:09 +0200 Subject: [PATCH] MAINT: drop Python 3.8 support due to EOL (#143) --- .constraints/py3.8.txt | 245 --------------------- docs/conf.py | 15 +- pyproject.toml | 3 +- src/ampform_dpd/__init__.py | 6 +- src/ampform_dpd/_attrs.py | 4 +- src/ampform_dpd/_cache.py | 2 +- src/ampform_dpd/adapter/qrules.py | 5 +- src/ampform_dpd/decay.py | 6 +- src/ampform_dpd/io/__init__.py | 4 +- src/ampform_dpd/io/serialization/decay.py | 4 +- src/ampform_dpd/io/serialization/format.py | 6 +- src/ampform_dpd/spin.py | 5 +- 12 files changed, 35 insertions(+), 270 deletions(-) delete mode 100644 .constraints/py3.8.txt diff --git a/.constraints/py3.8.txt b/.constraints/py3.8.txt deleted file mode 100644 index dae167c3..00000000 --- a/.constraints/py3.8.txt +++ /dev/null @@ -1,245 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile pyproject.toml -o .constraints/py3.8.txt --all-extras --no-annotate --python-version=3.8 --no-emit-package setuptools -absl-py==2.1.0 -accessible-pygments==0.0.4 -alabaster==0.7.13 -ampform==0.15.4 -anyio==4.4.0 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==2.4.1 -astunparse==1.6.3 -async-lru==2.0.4 -attrs==24.2.0 -babel==2.16.0 -backcall==0.2.0 -beautifulsoup4==4.12.3 -bleach==6.1.0 -cachetools==5.5.0 -cattrs==24.1.0 -certifi==2024.8.30 -cffi==1.17.1 -cfgv==3.4.0 -chardet==5.2.0 -charset-normalizer==3.3.2 -click==8.1.7 -cloudpickle==3.0.0 -colorama==0.4.6 -comm==0.2.2 -contourpy==1.1.1 -coverage==7.6.1 -cycler==0.12.1 -debugpy==1.8.5 -decorator==5.1.1 -defusedxml==0.7.1 -distlib==0.3.8 -dm-tree==0.1.8 -docstring-to-markdown==0.15 -docutils==0.17.1 -exceptiongroup==1.2.2 -execnet==2.1.1 -executing==2.1.0 -fastjsonschema==2.20.0 -filelock==3.16.0 -flatbuffers==24.3.25 -fonttools==4.53.1 -fqdn==1.5.1 -gast==0.4.0 -gitdb==4.0.11 -gitpython==3.1.43 -google-auth==2.34.0 -google-auth-oauthlib==0.4.6 -google-pasta==0.2.0 -graphviz==0.20.3 -greenlet==3.1.0 -grpcio==1.66.1 -h11==0.14.0 -h5py==3.11.0 -hepunits==2.3.4 -httpcore==1.0.5 -httpx==0.27.2 -identify==2.6.0 -idna==3.8 -imagesize==1.4.1 -iminuit==2.27.0 -importlib-metadata==8.4.0 -importlib-resources==6.4.5 -iniconfig==2.0.0 -ipykernel==6.29.5 -ipympl==0.9.3 -ipython==8.12.3 -ipython-genutils==0.2.0 -ipywidgets==8.1.5 -isoduration==20.11.0 -jax==0.4.13 -jaxlib==0.4.13 -jedi==0.19.1 -jinja2==3.1.4 -json5==0.9.25 -jsonpointer==3.0.0 -jsonschema==4.23.0 -jsonschema-specifications==2023.12.1 -jupyter-cache==0.6.1 -jupyter-client==8.6.2 -jupyter-core==5.7.2 -jupyter-events==0.10.0 -jupyter-lsp==2.2.5 -jupyter-server==2.14.2 -jupyter-server-mathjax==0.2.6 -jupyter-server-terminals==0.5.3 -jupyterlab==4.2.5 -jupyterlab-code-formatter==3.0.2 -jupyterlab-git==0.50.1 -jupyterlab-lsp==5.1.0 -jupyterlab-myst==2.4.2 -jupyterlab-pygments==0.3.0 -jupyterlab-server==2.27.3 -jupyterlab-widgets==3.0.13 -keras==2.11.0 -kiwisolver==1.4.7 -latexcodec==3.0.0 -libclang==18.1.1 -livereload==2.7.0 -llvmlite==0.41.1 -lsprotocol==2023.0.1 -markdown==3.7 -markdown-it-py==2.2.0 -markupsafe==2.1.5 -matplotlib==3.7.5 -matplotlib-inline==0.1.7 -mdit-py-plugins==0.3.5 -mdurl==0.1.2 -mistune==3.0.2 -ml-dtypes==0.2.0 -mpmath==1.3.0 -mypy==1.11.2 -mypy-extensions==1.0.0 -myst-nb==0.17.2 -myst-parser==0.18.1 -nbclient==0.6.8 -nbconvert==7.16.4 -nbdime==4.0.2 -nbformat==5.10.4 -nbmake==1.5.4 -nest-asyncio==1.6.0 -nodeenv==1.9.1 -notebook-shim==0.2.4 -numba==0.58.1 -numpy==1.24.4 -oauthlib==3.2.2 -opt-einsum==3.3.0 -overrides==7.7.0 -packaging==24.1 -pandas==2.0.3 -pandocfilters==1.5.1 -parso==0.8.4 -particle==0.25.0 -pexpect==4.9.0 -phasespace==1.9.0 -pickleshare==0.7.5 -pillow==10.4.0 -pkgutil-resolve-name==1.3.10 -platformdirs==4.3.2 -pluggy==1.5.0 -pre-commit==3.5.0 -prometheus-client==0.20.0 -prompt-toolkit==3.0.47 -protobuf==3.19.6 -psutil==6.0.0 -ptyprocess==0.7.0 -pure-eval==0.2.3 -pyasn1==0.6.1 -pyasn1-modules==0.4.1 -pybtex==0.24.0 -pybtex-docutils==1.0.3 -pycparser==2.22 -pydata-sphinx-theme==0.14.4 -pygments==2.18.0 -pyparsing==3.1.4 -pyproject-api==1.7.1 -pytest==8.3.3 -pytest-cov==5.0.0 -pytest-xdist==3.6.1 -python-constraint2==2.0.0b5 -python-dateutil==2.9.0.post0 -python-json-logger==2.0.7 -python-lsp-jsonrpc==1.1.2 -python-lsp-ruff==2.2.2 -python-lsp-server==1.12.0 -pytoolconfig==1.3.1 -pytz==2024.1 -pyyaml==6.0.2 -pyzmq==26.2.0 -qrules==0.10.2 -referencing==0.35.1 -requests==2.32.3 -requests-oauthlib==2.0.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rope==1.13.0 -rpds-py==0.20.0 -rsa==4.9 -ruff==0.6.4 -scipy==1.10.1 -send2trash==1.8.3 -six==1.16.0 -smmap==5.0.1 -sniffio==1.3.1 -snowballstemmer==2.2.0 -soupsieve==2.6 -sphinx==5.3.0 -sphinx-api-relink==0.0.9 -sphinx-autobuild==2021.3.14 -sphinx-book-theme==1.0.1 -sphinx-codeautolink==0.15.2 -sphinx-copybutton==0.5.2 -sphinx-design==0.5.0 -sphinx-pybtex-etal-style==0.0.2 -sphinx-togglebutton==0.3.2 -sphinxcontrib-applehelp==1.0.4 -sphinxcontrib-bibtex==2.6.2 -sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==2.0.1 -sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.5 -sqlalchemy==2.0.34 -stack-data==0.6.3 -sympy==1.13.2 -tabulate==0.9.0 -tensorboard==2.11.2 -tensorboard-data-server==0.6.1 -tensorboard-plugin-wit==1.8.1 -tensorflow==2.11.1 -tensorflow-estimator==2.11.0 -tensorflow-io-gcs-filesystem==0.34.0 -tensorflow-probability==0.20.1 -tensorwaves==0.4.12 -termcolor==2.4.0 -terminado==0.18.1 -tinycss2==1.3.0 -tomli==2.0.1 -tornado==6.4.1 -tox==4.18.1 -tqdm==4.66.5 -traitlets==5.14.3 -types-python-dateutil==2.9.0.20240906 -typing-extensions==4.12.2 -tzdata==2024.1 -ujson==5.10.0 -uri-template==1.3.0 -urllib3==2.2.2 -virtualenv==20.26.4 -wcwidth==0.2.13 -webcolors==24.8.0 -webencodings==0.5.1 -websocket-client==1.8.0 -werkzeug==3.0.4 -wheel==0.44.0 -widgetsnbextension==4.0.13 -wrapt==1.16.0 -zipp==3.20.1 - -# The following packages were excluded from the output: -# setuptools diff --git a/docs/conf.py b/docs/conf.py index 5943a6ee..fb7ed7b4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,6 +40,7 @@ "ampform_dpd.decay.StateIDTemplate": ("obj", "ampform_dpd.decay.StateID"), "ampform_dpd.io.serialization.dynamics.T": "typing.TypeVar", "DecayNode": ("obj", "ampform_dpd.decay.DecayNode"), + "EdgeType": "typing.TypeVar", "FinalState": ("obj", "ampform_dpd.decay.FinalState"), "FinalStateID": ("obj", "ampform_dpd.decay.FinalStateID"), "FrozenTransition": "qrules.topology.FrozenTransition", @@ -47,6 +48,7 @@ "Literal[-1, 1]": "typing.Literal", "Literal[(-1, 1)]": "typing.Literal", "Node": ("obj", "ampform_dpd.io.serialization.format.Node"), + "NodeType": "typing.TypeVar", "ParameterValue": ("obj", "tensorwaves.interface.ParameterValue"), "ParametrizedBackendFunction": "tensorwaves.function.ParametrizedBackendFunction", "PoolSum": "ampform.sympy.PoolSum", @@ -172,7 +174,7 @@ html_title = REPO_TITLE intersphinx_mapping = { "IPython": (f"https://ipython.readthedocs.io/en/{pin('IPython')}", None), - "ampform": (f"https://ampform.readthedocs.io/en/{pin('ampform')}", None), + "ampform": (f"https://ampform.readthedocs.io/{pin('ampform')}", None), "attrs": (f"https://www.attrs.org/en/{pin('attrs')}", None), "compwa": ("https://compwa.github.io", None), "graphviz": ("https://graphviz.readthedocs.io/en/stable", None), @@ -181,17 +183,14 @@ "matplotlib": (f"https://matplotlib.org/{pin('matplotlib')}", None), "numpy": (f"https://numpy.org/doc/{pin_minor('numpy')}", None), "python": ("https://docs.python.org/3", None), - "qrules": (f"https://qrules.readthedocs.io/en/{pin('qrules')}", None), + "qrules": (f"https://qrules.readthedocs.io/{pin('qrules')}", None), "sympy": ("https://docs.sympy.org/latest", None), - "tensorwaves": ( - f"https://tensorwaves.readthedocs.io/en/{pin('tensorwaves')}", - None, - ), + "tensorwaves": (f"https://tensorwaves.readthedocs.io/{pin('tensorwaves')}", None), } linkcheck_anchors = False linkcheck_ignore = [ - "https://github.com/ComPWA/polarimetry", - "https://journals.aps.org/prd/pdf/10.1103/PhysRevD.101.034033#page=9", + "https://doi.org/10.1103", + "https://journals.aps.org/prd", ] myst_enable_extensions = [ "amsmath", diff --git a/pyproject.toml b/pyproject.toml index c07b5489..1354b9de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,6 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python", "Topic :: Scientific/Engineering :: Physics", @@ -38,7 +37,7 @@ description = "Symbolic expressions for Dalitz-Plot Decomposition" dynamic = ["version"] license = {file = "LICENSE"} name = "ampform-dpd" -requires-python = ">=3.8" +requires-python = ">=3.9" [project.optional-dependencies] dev = [ diff --git a/src/ampform_dpd/__init__.py b/src/ampform_dpd/__init__.py index 0f28efcd..6ea0adeb 100644 --- a/src/ampform_dpd/__init__.py +++ b/src/ampform_dpd/__init__.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections import abc -from functools import lru_cache +from functools import cache from itertools import product from typing import Any, Literal, Protocol from warnings import warn @@ -289,7 +289,7 @@ def _create_coupling_symbol( return H[resonance, interaction.L, interaction.S] -@lru_cache(maxsize=None) +@cache def _get_coupling_base( helicity_coupling: bool, typ: Literal["production", "decay"] ) -> sp.IndexedBase: @@ -331,7 +331,7 @@ def _formulate_clebsch_gordan_factors( return sqrt_factor * cg_ll * cg_ss -@lru_cache(maxsize=None) +@cache def _generate_amplitude_index_bases() -> dict[FinalStateID, sp.IndexedBase]: return dict(enumerate(sp.symbols(R"A^(1:4)", cls=sp.IndexedBase), 1)) # type:ignore[arg-type] diff --git a/src/ampform_dpd/_attrs.py b/src/ampform_dpd/_attrs.py index b85aaad3..d14e2a92 100644 --- a/src/ampform_dpd/_attrs.py +++ b/src/ampform_dpd/_attrs.py @@ -2,11 +2,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Iterable, SupportsFloat +from typing import TYPE_CHECKING, SupportsFloat import sympy as sp if TYPE_CHECKING: + from collections.abc import Iterable + from attrs import Attribute from ampform_dpd.decay import LSCoupling, ThreeBodyDecayChain diff --git a/src/ampform_dpd/_cache.py b/src/ampform_dpd/_cache.py index 39c00e44..d19552eb 100644 --- a/src/ampform_dpd/_cache.py +++ b/src/ampform_dpd/_cache.py @@ -80,7 +80,7 @@ def _get_python_hash_seed() -> int | None: return None -@functools.lru_cache(maxsize=None) # warn once +@functools.cache # warn once def _warn_about_unsafe_hash() -> None: message = """ PYTHONHASHSEED has not been set. For faster and safer hashing of SymPy expressions, diff --git a/src/ampform_dpd/adapter/qrules.py b/src/ampform_dpd/adapter/qrules.py index 9c1e504d..7d278c4d 100644 --- a/src/ampform_dpd/adapter/qrules.py +++ b/src/ampform_dpd/adapter/qrules.py @@ -5,7 +5,7 @@ from collections import abc, defaultdict from functools import singledispatch from pathlib import Path -from typing import Any, Iterable, NoReturn, TypeVar, overload +from typing import TYPE_CHECKING, Any, NoReturn, TypeVar, overload import attrs import qrules @@ -24,6 +24,9 @@ ThreeBodyDecayChain, ) +if TYPE_CHECKING: + from collections.abc import Iterable + _LOGGER = logging.getLogger(__name__) diff --git a/src/ampform_dpd/decay.py b/src/ampform_dpd/decay.py index 813097ce..57b4729d 100644 --- a/src/ampform_dpd/decay.py +++ b/src/ampform_dpd/decay.py @@ -2,7 +2,7 @@ from __future__ import annotations -from functools import lru_cache +from functools import cache from textwrap import dedent from typing import TYPE_CHECKING, Generic, Literal, TypeVar, overload from warnings import warn @@ -170,7 +170,7 @@ def initial_state(self) -> InitialState: return self.parent @property - @lru_cache(maxsize=None) # noqa: B019 + @cache # noqa: B019 def final_state(self) -> tuple[FinalState, FinalState, FinalState]: final_state = (*self.decay_products, self.spectator) return tuple(sorted(final_state, key=lambda x: x.index)) # type:ignore[return-value] @@ -202,7 +202,7 @@ def decay_products(self) -> tuple[FinalState, FinalState]: def spectator(self) -> FinalState: return self._get_child_of_type(State) - @lru_cache(maxsize=None) # noqa: B019 + @cache # noqa: B019 def _get_child_of_type(self, typ: type[T]) -> T: for child in self.decay.children: if isinstance(child, typ): diff --git a/src/ampform_dpd/io/__init__.py b/src/ampform_dpd/io/__init__.py index b5ed4481..d2a176dd 100644 --- a/src/ampform_dpd/io/__init__.py +++ b/src/ampform_dpd/io/__init__.py @@ -23,7 +23,7 @@ from collections import abc from importlib.metadata import version from pathlib import Path -from typing import TYPE_CHECKING, Any, Iterable, Mapping, Sequence, overload +from typing import TYPE_CHECKING, Any, overload import cloudpickle import sympy as sp @@ -41,6 +41,8 @@ ) if TYPE_CHECKING: + from collections.abc import Iterable, Mapping, Sequence + from tensorwaves.function import ( ParametrizedBackendFunction, PositionalArgumentFunction, diff --git a/src/ampform_dpd/io/serialization/decay.py b/src/ampform_dpd/io/serialization/decay.py index ae2bd893..bc54e3ae 100644 --- a/src/ampform_dpd/io/serialization/decay.py +++ b/src/ampform_dpd/io/serialization/decay.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Callable, Iterable +from typing import TYPE_CHECKING, Callable import sympy as sp @@ -20,6 +20,8 @@ ) if TYPE_CHECKING: + from collections.abc import Iterable + from ampform_dpd.io.serialization.format import ( DecayChain, ModelDefinition, diff --git a/src/ampform_dpd/io/serialization/format.py b/src/ampform_dpd/io/serialization/format.py index a09f779b..31504f3a 100644 --- a/src/ampform_dpd/io/serialization/format.py +++ b/src/ampform_dpd/io/serialization/format.py @@ -2,7 +2,7 @@ import difflib import sys -from typing import TYPE_CHECKING, List, Literal, Tuple, TypedDict, Union +from typing import TYPE_CHECKING, Literal, TypedDict, Union from warnings import warn from ampform_dpd.decay import FinalStateID @@ -39,7 +39,7 @@ class DecayDescription(TypedDict): appendix: dict -Topology = List[Union[FinalStateID, "Topology"]] +Topology = list[Union[FinalStateID, "Topology"]] """Topology definition as a list of final state IDs.""" @@ -77,7 +77,7 @@ class LSVertex(Vertex): s: str -Node = Tuple[Union[FinalStateID, "Node"], Union[FinalStateID, "Node"]] +Node = tuple[Union[FinalStateID, "Node"], Union[FinalStateID, "Node"]] """Node definition within a `.Topology`.""" ParityFactor = Literal["+", "-", ""] diff --git a/src/ampform_dpd/spin.py b/src/ampform_dpd/spin.py index b7bc8e19..8e1ba1e5 100644 --- a/src/ampform_dpd/spin.py +++ b/src/ampform_dpd/spin.py @@ -3,10 +3,13 @@ from __future__ import annotations from decimal import Decimal -from typing import Generator, SupportsFloat, SupportsInt +from typing import TYPE_CHECKING, SupportsFloat, SupportsInt import sympy as sp +if TYPE_CHECKING: + from collections.abc import Generator + def generate_ls_couplings( parent_spin: SupportsFloat,