From 8b82d945dfdf00bc7e04bccf13b070ad3d57a662 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 03:18:19 +0200 Subject: [PATCH] DX!: switch to Ruff as linter (#76) * MAINT: implement updates from pre-commit hooks * MAINT: update pip constraints and pre-commit * MAINT: upgrade to Jupyter Lab v4 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: Remco de Boer <29308176+redeboer@users.noreply.github.com> --- .constraints/py3.10.txt | 98 ++++++++++---------- .constraints/py3.11.txt | 96 +++++++++---------- .constraints/py3.7.txt | 47 +++++----- .constraints/py3.8.txt | 96 +++++++++---------- .constraints/py3.9.txt | 98 ++++++++++---------- .cspell.json | 3 - .gitpod.yml | 2 + .pre-commit-config.yaml | 25 ++--- .vscode/extensions.json | 10 ++ .vscode/settings.json | 7 +- README.md | 1 + docs/_relink_references.py | 13 ++- docs/_unsrt_et_al.py | 14 ++- docs/comparison/d2kkk.ipynb | 30 +++--- docs/comparison/jpsi2phipipi.ipynb | 30 +++--- docs/comparison/jpsi2pipipi.ipynb | 30 +++--- docs/conf.py | 14 +-- docs/jpsi2ksp.ipynb | 13 +-- docs/lc2pkpi.ipynb | 7 +- pyproject.toml | 143 +++++++++++++++++++++++++---- pyrightconfig.json | 30 ------ setup.cfg | 10 +- src/ampform_dpd/__init__.py | 31 +++---- src/ampform_dpd/_attrs.py | 11 ++- src/ampform_dpd/angles.py | 32 ++++--- src/ampform_dpd/decay.py | 45 ++++++--- src/ampform_dpd/dynamics.py | 2 +- src/ampform_dpd/io.py | 33 ++++--- src/ampform_dpd/spin.py | 2 +- tests/test_angles.py | 2 +- tests/test_io.py | 2 +- 31 files changed, 547 insertions(+), 430 deletions(-) delete mode 100644 pyrightconfig.json diff --git a/.constraints/py3.10.txt b/.constraints/py3.10.txt index 4af214ee..c45f29a1 100644 --- a/.constraints/py3.10.txt +++ b/.constraints/py3.10.txt @@ -6,17 +6,15 @@ # absl-py==1.4.0 accessible-pygments==0.0.4 -aiofiles==22.1.0 -aiosqlite==0.19.0 alabaster==0.7.13 ampform==0.14.6 -anyio==3.7.0 -aquirdturtle-collapsible-headings==3.1.0 +anyio==3.7.1 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 arrow==1.2.3 asttokens==2.2.1 astunparse==1.6.3 +async-lru==2.0.2 attrs==23.1.0 babel==2.12.1 backcall==0.2.0 @@ -29,7 +27,7 @@ cffi==1.15.1 cfgv==3.3.1 chardet==5.1.0 charset-normalizer==3.1.0 -click==8.1.3 +click==8.1.4 cloudpickle==2.2.1 colorama==0.4.6 comm==0.1.3 @@ -43,7 +41,7 @@ deprecated==1.2.14 distlib==0.3.6 dm-tree==0.1.8 docutils==0.19 -exceptiongroup==1.1.1 +exceptiongroup==1.1.2 execnet==1.9.0 executing==1.2.0 fastjsonschema==2.17.1 @@ -52,50 +50,48 @@ flatbuffers==23.5.26 fonttools==4.40.0 fqdn==1.5.1 gast==0.4.0 -google-auth==2.20.0 +google-auth==2.21.0 google-auth-oauthlib==1.0.0 google-pasta==0.2.0 graphviz==0.20.1 greenlet==2.0.2 -grpcio==1.54.2 +grpcio==1.56.0 h5py==3.9.0 hepunits==2.3.2 identify==2.5.24 idna==3.4 imagesize==1.4.1 -iminuit==2.21.3 +iminuit==2.22.0 importlib-metadata==6.7.0 iniconfig==2.0.0 -ipykernel==6.23.2 +ipykernel==6.24.0 ipympl==0.9.3 ipython==8.14.0 ipython-genutils==0.2.0 -ipywidgets==8.0.6 +ipywidgets==8.0.7 isoduration==20.11.0 -isort==5.12.0 -jax==0.4.12 -jaxlib==0.4.12 +jax==0.4.13 +jaxlib==0.4.13 jedi==0.18.2 jinja2==3.1.2 json5==0.9.14 jsonpointer==2.4 -jsonschema==4.17.3 +jsonschema==4.18.0 +jsonschema-specifications==2023.6.1 jupyter-cache==0.6.1 -jupyter-client==8.2.0 +jupyter-client==8.3.0 jupyter-core==5.3.1 jupyter-events==0.6.3 -jupyter-server==2.6.0 -jupyter-server-fileid==0.9.0 +jupyter-lsp==2.2.0 +jupyter-server==2.7.0 jupyter-server-terminals==0.4.4 -jupyter-server-ydoc==0.8.0 -jupyter-ydoc==0.2.4 -jupyterlab==3.6.4 +jupyterlab==4.0.2 jupyterlab-code-formatter==2.2.1 -jupyterlab-myst==1.2.0 +jupyterlab-myst==2.0.1 jupyterlab-pygments==0.2.2 jupyterlab-server==2.23.0 -jupyterlab-widgets==3.0.7 -keras==2.12.0 +jupyterlab-widgets==3.0.8 +keras==2.13.1 kiwisolver==1.4.4 latexcodec==2.0.1 libclang==16.0.0 @@ -103,7 +99,7 @@ livereload==2.6.3 markdown==3.4.3 markdown-it-py==2.2.0 markupsafe==2.1.3 -matplotlib==3.7.1 +matplotlib==3.7.2 matplotlib-inline==0.1.6 mdit-py-plugins==0.3.5 mdurl==0.1.2 @@ -113,34 +109,32 @@ mpmath==1.3.0 mypy-extensions==1.0.0 myst-nb==0.17.2 myst-parser==0.18.1 -nbclassic==1.0.0 -nbclient==0.5.13 +nbclient==0.6.8 nbconvert==7.6.0 nbformat==5.9.0 -nbmake==1.3.0 +nbmake==1.4.1 nest-asyncio==1.5.6 nodeenv==1.8.0 -notebook==6.5.4 notebook-shim==0.2.3 -numpy==1.23.5 +numpy==1.24.3 oauthlib==3.2.2 opt-einsum==3.3.0 overrides==7.3.1 packaging==23.1 pandocfilters==1.5.0 parso==0.8.3 -particle==0.22.1 +particle==0.23.0 pathspec==0.11.1 pexpect==4.8.0 phasespace==1.8.0 pickleshare==0.7.5 -pillow==9.5.0 -platformdirs==3.7.0 +pillow==10.0.0 +platformdirs==3.8.1 pluggy==1.2.0 pre-commit==3.3.3 prometheus-client==0.17.0 -prompt-toolkit==3.0.38 -protobuf==4.23.3 +prompt-toolkit==3.0.39 +protobuf==4.23.4 psutil==5.9.5 ptyprocess==0.7.0 pure-eval==0.2.2 @@ -149,13 +143,12 @@ pyasn1-modules==0.3.0 pybtex==0.24.0 pybtex-docutils==1.0.2 pycparser==2.21 -pydantic==1.10.9 +pydantic==1.10.11 pydata-sphinx-theme==0.13.3 pygments==2.15.1 -pyparsing==3.1.0 -pyproject-api==1.5.2 -pyrsistent==0.19.3 -pytest==7.3.2 +pyparsing==3.0.9 +pyproject-api==1.5.3 +pytest==7.4.0 pytest-cov==4.1.0 pytest-xdist==3.3.1 python-constraint==1.4.0 @@ -164,12 +157,15 @@ python-json-logger==2.0.7 pyyaml==6.0 pyzmq==25.1.0 qrules==0.9.8 +referencing==0.29.1 requests==2.31.0 requests-oauthlib==1.3.1 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 +rpds-py==0.8.8 rsa==4.9 -scipy==1.10.1 +ruff==0.0.277 +scipy==1.11.1 send2trash==1.8.2 six==1.16.0 sniffio==1.3.0 @@ -189,14 +185,14 @@ sphinxcontrib-htmlhelp==2.0.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 -sqlalchemy==2.0.16 +sqlalchemy==2.0.18 stack-data==0.6.2 sympy==1.12 tabulate==0.9.0 -tensorboard==2.12.3 +tensorboard==2.13.0 tensorboard-data-server==0.7.1 -tensorflow==2.12.0 -tensorflow-estimator==2.12.0 +tensorflow==2.13.0 +tensorflow-estimator==2.13.0 tensorflow-io-gcs-filesystem==0.32.0 tensorflow-probability==0.18.0 tensorwaves==0.4.10 @@ -205,23 +201,21 @@ terminado==0.17.1 tinycss2==1.2.1 tomli==2.0.1 tornado==6.3.2 -tox==4.6.3 +tox==4.6.4 tqdm==4.65.0 traitlets==5.9.0 -typing-extensions==4.6.3 +typing-extensions==4.5.0 uri-template==1.3.0 urllib3==1.26.16 virtualenv==20.23.1 wcwidth==0.2.6 webcolors==1.13 webencodings==0.5.1 -websocket-client==1.6.0 +websocket-client==1.6.1 werkzeug==2.3.6 wheel==0.40.0 -widgetsnbextension==4.0.7 -wrapt==1.14.1 -y-py==0.5.9 -ypy-websocket==0.8.2 +widgetsnbextension==4.0.8 +wrapt==1.15.0 zipp==3.15.0 # The following packages are considered to be unsafe in a requirements file: diff --git a/.constraints/py3.11.txt b/.constraints/py3.11.txt index c36e45ca..6fbcf73f 100644 --- a/.constraints/py3.11.txt +++ b/.constraints/py3.11.txt @@ -6,17 +6,15 @@ # absl-py==1.4.0 accessible-pygments==0.0.4 -aiofiles==22.1.0 -aiosqlite==0.19.0 alabaster==0.7.13 ampform==0.14.6 -anyio==3.7.0 -aquirdturtle-collapsible-headings==3.1.0 +anyio==3.7.1 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 arrow==1.2.3 asttokens==2.2.1 astunparse==1.6.3 +async-lru==2.0.2 attrs==23.1.0 babel==2.12.1 backcall==0.2.0 @@ -29,7 +27,7 @@ cffi==1.15.1 cfgv==3.3.1 chardet==5.1.0 charset-normalizer==3.1.0 -click==8.1.3 +click==8.1.4 cloudpickle==2.2.1 colorama==0.4.6 comm==0.1.3 @@ -51,50 +49,48 @@ flatbuffers==23.5.26 fonttools==4.40.0 fqdn==1.5.1 gast==0.4.0 -google-auth==2.20.0 +google-auth==2.21.0 google-auth-oauthlib==1.0.0 google-pasta==0.2.0 graphviz==0.20.1 greenlet==2.0.2 -grpcio==1.54.2 +grpcio==1.56.0 h5py==3.9.0 hepunits==2.3.2 identify==2.5.24 idna==3.4 imagesize==1.4.1 -iminuit==2.21.3 +iminuit==2.22.0 importlib-metadata==6.7.0 iniconfig==2.0.0 -ipykernel==6.23.2 +ipykernel==6.24.0 ipympl==0.9.3 ipython==8.14.0 ipython-genutils==0.2.0 -ipywidgets==8.0.6 +ipywidgets==8.0.7 isoduration==20.11.0 -isort==5.12.0 -jax==0.4.12 -jaxlib==0.4.12 +jax==0.4.13 +jaxlib==0.4.13 jedi==0.18.2 jinja2==3.1.2 json5==0.9.14 jsonpointer==2.4 -jsonschema==4.17.3 +jsonschema==4.18.0 +jsonschema-specifications==2023.6.1 jupyter-cache==0.6.1 -jupyter-client==8.2.0 +jupyter-client==8.3.0 jupyter-core==5.3.1 jupyter-events==0.6.3 -jupyter-server==2.6.0 -jupyter-server-fileid==0.9.0 +jupyter-lsp==2.2.0 +jupyter-server==2.7.0 jupyter-server-terminals==0.4.4 -jupyter-server-ydoc==0.8.0 -jupyter-ydoc==0.2.4 -jupyterlab==3.6.4 +jupyterlab==4.0.2 jupyterlab-code-formatter==2.2.1 -jupyterlab-myst==1.2.0 +jupyterlab-myst==2.0.1 jupyterlab-pygments==0.2.2 jupyterlab-server==2.23.0 -jupyterlab-widgets==3.0.7 -keras==2.12.0 +jupyterlab-widgets==3.0.8 +keras==2.13.1 kiwisolver==1.4.4 latexcodec==2.0.1 libclang==16.0.0 @@ -102,7 +98,7 @@ livereload==2.6.3 markdown==3.4.3 markdown-it-py==2.2.0 markupsafe==2.1.3 -matplotlib==3.7.1 +matplotlib==3.7.2 matplotlib-inline==0.1.6 mdit-py-plugins==0.3.5 mdurl==0.1.2 @@ -112,34 +108,32 @@ mpmath==1.3.0 mypy-extensions==1.0.0 myst-nb==0.17.2 myst-parser==0.18.1 -nbclassic==1.0.0 -nbclient==0.5.13 +nbclient==0.6.8 nbconvert==7.6.0 nbformat==5.9.0 -nbmake==1.3.0 +nbmake==1.4.1 nest-asyncio==1.5.6 nodeenv==1.8.0 -notebook==6.5.4 notebook-shim==0.2.3 -numpy==1.23.5 +numpy==1.24.3 oauthlib==3.2.2 opt-einsum==3.3.0 overrides==7.3.1 packaging==23.1 pandocfilters==1.5.0 parso==0.8.3 -particle==0.22.1 +particle==0.23.0 pathspec==0.11.1 pexpect==4.8.0 phasespace==1.8.0 pickleshare==0.7.5 -pillow==9.5.0 -platformdirs==3.7.0 +pillow==10.0.0 +platformdirs==3.8.1 pluggy==1.2.0 pre-commit==3.3.3 prometheus-client==0.17.0 -prompt-toolkit==3.0.38 -protobuf==4.23.3 +prompt-toolkit==3.0.39 +protobuf==4.23.4 psutil==5.9.5 ptyprocess==0.7.0 pure-eval==0.2.2 @@ -148,13 +142,12 @@ pyasn1-modules==0.3.0 pybtex==0.24.0 pybtex-docutils==1.0.2 pycparser==2.21 -pydantic==1.10.9 +pydantic==1.10.11 pydata-sphinx-theme==0.13.3 pygments==2.15.1 -pyparsing==3.1.0 -pyproject-api==1.5.2 -pyrsistent==0.19.3 -pytest==7.3.2 +pyparsing==3.0.9 +pyproject-api==1.5.3 +pytest==7.4.0 pytest-cov==4.1.0 pytest-xdist==3.3.1 python-constraint==1.4.0 @@ -163,12 +156,15 @@ python-json-logger==2.0.7 pyyaml==6.0 pyzmq==25.1.0 qrules==0.9.8 +referencing==0.29.1 requests==2.31.0 requests-oauthlib==1.3.1 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 +rpds-py==0.8.8 rsa==4.9 -scipy==1.10.1 +ruff==0.0.277 +scipy==1.11.1 send2trash==1.8.2 six==1.16.0 sniffio==1.3.0 @@ -188,14 +184,14 @@ sphinxcontrib-htmlhelp==2.0.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 -sqlalchemy==2.0.16 +sqlalchemy==2.0.18 stack-data==0.6.2 sympy==1.12 tabulate==0.9.0 -tensorboard==2.12.3 +tensorboard==2.13.0 tensorboard-data-server==0.7.1 -tensorflow==2.12.0 -tensorflow-estimator==2.12.0 +tensorflow==2.13.0 +tensorflow-estimator==2.13.0 tensorflow-io-gcs-filesystem==0.32.0 tensorflow-probability==0.18.0 tensorwaves==0.4.10 @@ -203,23 +199,21 @@ termcolor==2.3.0 terminado==0.17.1 tinycss2==1.2.1 tornado==6.3.2 -tox==4.6.3 +tox==4.6.4 tqdm==4.65.0 traitlets==5.9.0 -typing-extensions==4.6.3 +typing-extensions==4.5.0 uri-template==1.3.0 urllib3==1.26.16 virtualenv==20.23.1 wcwidth==0.2.6 webcolors==1.13 webencodings==0.5.1 -websocket-client==1.6.0 +websocket-client==1.6.1 werkzeug==2.3.6 wheel==0.40.0 -widgetsnbextension==4.0.7 -wrapt==1.14.1 -y-py==0.5.9 -ypy-websocket==0.8.2 +widgetsnbextension==4.0.8 +wrapt==1.15.0 zipp==3.15.0 # The following packages are considered to be unsafe in a requirements file: diff --git a/.constraints/py3.7.txt b/.constraints/py3.7.txt index 0840293d..635ef188 100644 --- a/.constraints/py3.7.txt +++ b/.constraints/py3.7.txt @@ -10,8 +10,7 @@ aiofiles==22.1.0 aiosqlite==0.19.0 alabaster==0.7.13 ampform==0.14.6 -anyio==3.7.0 -aquirdturtle-collapsible-headings==3.1.0 +anyio==3.7.1 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 arrow==1.2.3 @@ -29,7 +28,7 @@ cffi==1.15.1 cfgv==3.3.1 chardet==5.1.0 charset-normalizer==3.1.0 -click==8.1.3 +click==8.1.4 cloudpickle==2.2.1 colorama==0.4.6 coverage==7.2.7 @@ -42,7 +41,7 @@ distlib==0.3.6 dm-tree==0.1.8 docutils==0.19 entrypoints==0.4 -exceptiongroup==1.1.1 +exceptiongroup==1.1.2 execnet==1.9.0 fastjsonschema==2.17.1 filelock==3.12.2 @@ -50,12 +49,12 @@ flatbuffers==23.5.26 fonttools==4.38.0 fqdn==1.5.1 gast==0.4.0 -google-auth==2.20.0 +google-auth==2.21.0 google-auth-oauthlib==0.4.6 google-pasta==0.2.0 graphviz==0.20.1 greenlet==2.0.2 -grpcio==1.54.2 +grpcio==1.56.0 h5py==3.8.0 hepunits==2.3.2 identify==2.5.24 @@ -69,9 +68,8 @@ ipykernel==6.16.2 ipympl==0.9.3 ipython==7.34.0 ipython-genutils==0.2.0 -ipywidgets==8.0.6 +ipywidgets==8.0.7 isoduration==20.11.0 -isort==5.11.5 jax==0.3.25 jaxlib==0.3.25 jedi==0.18.2 @@ -87,12 +85,12 @@ jupyter-server==1.24.0 jupyter-server-fileid==0.9.0 jupyter-server-ydoc==0.8.0 jupyter-ydoc==0.2.4 -jupyterlab==3.6.4 +jupyterlab==3.6.5 jupyterlab-code-formatter==2.2.1 jupyterlab-myst==1.2.0 jupyterlab-pygments==0.2.2 jupyterlab-server==2.23.0 -jupyterlab-widgets==3.0.7 +jupyterlab-widgets==3.0.8 keras==2.11.0 kiwisolver==1.4.4 latexcodec==2.0.1 @@ -114,7 +112,7 @@ nbclassic==1.0.0 nbclient==0.5.13 nbconvert==7.6.0 nbformat==5.8.0 -nbmake==1.3.0 +nbmake==1.2.1 ; python_version < "3.8.0" nest-asyncio==1.5.6 nodeenv==1.8.0 notebook==6.5.4 @@ -125,18 +123,18 @@ opt-einsum==3.3.0 packaging==23.1 pandocfilters==1.5.0 parso==0.8.3 -particle==0.22.1 +particle==0.23.0 pathspec==0.11.1 pexpect==4.8.0 phasespace==1.8.0 pickleshare==0.7.5 pillow==9.5.0 pkgutil-resolve-name==1.3.10 -platformdirs==3.7.0 +platformdirs==3.8.1 pluggy==1.2.0 pre-commit==2.21.0 prometheus-client==0.17.0 -prompt-toolkit==3.0.38 +prompt-toolkit==3.0.39 protobuf==3.19.6 psutil==5.9.5 ptyprocess==0.7.0 @@ -145,13 +143,13 @@ pyasn1-modules==0.3.0 pybtex==0.24.0 pybtex-docutils==1.0.2 pycparser==2.21 -pydantic==1.10.9 +pydantic==1.10.11 pydata-sphinx-theme==0.13.3 pygments==2.15.1 pyparsing==3.1.0 -pyproject-api==1.5.2 +pyproject-api==1.5.3 pyrsistent==0.19.3 -pytest==7.3.2 +pytest==7.4.0 pytest-cov==4.1.0 pytest-xdist==3.3.1 python-constraint==1.4.0 @@ -166,6 +164,7 @@ requests-oauthlib==1.3.1 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 rsa==4.9 +ruff==0.0.277 scipy==1.7.3 send2trash==1.8.2 singledispatchmethod==1.0 @@ -187,7 +186,7 @@ sphinxcontrib-htmlhelp==2.0.0 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 -sqlalchemy==1.4.48 +sqlalchemy==1.4.49 sympy==1.10.1 tabulate==0.9.0 tensorboard==2.11.2 @@ -203,24 +202,24 @@ terminado==0.17.1 tinycss2==1.2.1 tomli==2.0.1 tornado==6.2 -tox==4.6.3 +tox==4.6.4 tqdm==4.65.0 traitlets==5.9.0 -typed-ast==1.5.4 -typing-extensions==4.6.3 ; python_version < "3.8.0" +typed-ast==1.5.5 +typing-extensions==4.7.1 ; python_version < "3.8.0" uri-template==1.3.0 urllib3==1.26.16 virtualenv==20.23.1 wcwidth==0.2.6 webcolors==1.13 webencodings==0.5.1 -websocket-client==1.6.0 +websocket-client==1.6.1 werkzeug==2.2.3 wheel==0.40.0 -widgetsnbextension==4.0.7 +widgetsnbextension==4.0.8 wrapt==1.15.0 y-py==0.5.9 -ypy-websocket==0.8.2 +ypy-websocket==0.8.2 ; python_version < "3.8.0" zipp==3.15.0 # The following packages are considered to be unsafe in a requirements file: diff --git a/.constraints/py3.8.txt b/.constraints/py3.8.txt index e4ff6227..0573be3c 100644 --- a/.constraints/py3.8.txt +++ b/.constraints/py3.8.txt @@ -6,17 +6,15 @@ # absl-py==1.4.0 accessible-pygments==0.0.4 -aiofiles==22.1.0 -aiosqlite==0.19.0 alabaster==0.7.13 ampform==0.14.6 -anyio==3.7.0 -aquirdturtle-collapsible-headings==3.1.0 +anyio==3.7.1 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 arrow==1.2.3 asttokens==2.2.1 astunparse==1.6.3 +async-lru==2.0.2 attrs==23.1.0 babel==2.12.1 backcall==0.2.0 @@ -29,7 +27,7 @@ cffi==1.15.1 cfgv==3.3.1 chardet==5.1.0 charset-normalizer==3.1.0 -click==8.1.3 +click==8.1.4 cloudpickle==2.2.1 colorama==0.4.6 comm==0.1.3 @@ -43,7 +41,7 @@ deprecated==1.2.14 distlib==0.3.6 dm-tree==0.1.8 docutils==0.19 -exceptiongroup==1.1.1 +exceptiongroup==1.1.2 execnet==1.9.0 executing==1.2.0 fastjsonschema==2.17.1 @@ -52,51 +50,49 @@ flatbuffers==23.5.26 fonttools==4.40.0 fqdn==1.5.1 gast==0.4.0 -google-auth==2.20.0 +google-auth==2.21.0 google-auth-oauthlib==1.0.0 google-pasta==0.2.0 graphviz==0.20.1 greenlet==2.0.2 -grpcio==1.54.2 +grpcio==1.56.0 h5py==3.9.0 hepunits==2.3.2 identify==2.5.24 idna==3.4 imagesize==1.4.1 -iminuit==2.21.3 +iminuit==2.22.0 importlib-metadata==6.7.0 importlib-resources==5.12.0 iniconfig==2.0.0 -ipykernel==6.23.2 +ipykernel==6.24.0 ipympl==0.9.3 ipython==8.12.2 ipython-genutils==0.2.0 -ipywidgets==8.0.6 +ipywidgets==8.0.7 isoduration==20.11.0 -isort==5.12.0 -jax==0.4.12 -jaxlib==0.4.12 +jax==0.4.13 +jaxlib==0.4.13 jedi==0.18.2 jinja2==3.1.2 json5==0.9.14 jsonpointer==2.4 -jsonschema==4.17.3 +jsonschema==4.18.0 +jsonschema-specifications==2023.6.1 jupyter-cache==0.6.1 -jupyter-client==8.2.0 +jupyter-client==8.3.0 jupyter-core==5.3.1 jupyter-events==0.6.3 -jupyter-server==2.6.0 -jupyter-server-fileid==0.9.0 +jupyter-lsp==2.2.0 +jupyter-server==2.7.0 jupyter-server-terminals==0.4.4 -jupyter-server-ydoc==0.8.0 -jupyter-ydoc==0.2.4 -jupyterlab==3.6.4 +jupyterlab==4.0.2 jupyterlab-code-formatter==2.2.1 -jupyterlab-myst==1.2.0 +jupyterlab-myst==2.0.1 jupyterlab-pygments==0.2.2 jupyterlab-server==2.23.0 -jupyterlab-widgets==3.0.7 -keras==2.12.0 +jupyterlab-widgets==3.0.8 +keras==2.13.1 kiwisolver==1.4.4 latexcodec==2.0.1 libclang==16.0.0 @@ -104,7 +100,7 @@ livereload==2.6.3 markdown==3.4.3 markdown-it-py==2.2.0 markupsafe==2.1.3 -matplotlib==3.7.1 +matplotlib==3.7.2 matplotlib-inline==0.1.6 mdit-py-plugins==0.3.5 mdurl==0.1.2 @@ -114,35 +110,33 @@ mpmath==1.3.0 mypy-extensions==1.0.0 myst-nb==0.17.2 myst-parser==0.18.1 -nbclassic==1.0.0 -nbclient==0.5.13 +nbclient==0.6.8 nbconvert==7.6.0 nbformat==5.9.0 -nbmake==1.3.0 +nbmake==1.4.1 nest-asyncio==1.5.6 nodeenv==1.8.0 -notebook==6.5.4 notebook-shim==0.2.3 -numpy==1.23.5 +numpy==1.24.3 oauthlib==3.2.2 opt-einsum==3.3.0 overrides==7.3.1 packaging==23.1 pandocfilters==1.5.0 parso==0.8.3 -particle==0.22.1 +particle==0.23.0 pathspec==0.11.1 pexpect==4.8.0 phasespace==1.8.0 pickleshare==0.7.5 -pillow==9.5.0 +pillow==10.0.0 pkgutil-resolve-name==1.3.10 -platformdirs==3.7.0 +platformdirs==3.8.1 pluggy==1.2.0 pre-commit==3.3.3 prometheus-client==0.17.0 -prompt-toolkit==3.0.38 -protobuf==4.23.3 +prompt-toolkit==3.0.39 +protobuf==4.23.4 psutil==5.9.5 ptyprocess==0.7.0 pure-eval==0.2.2 @@ -151,13 +145,12 @@ pyasn1-modules==0.3.0 pybtex==0.24.0 pybtex-docutils==1.0.2 pycparser==2.21 -pydantic==1.10.9 +pydantic==1.10.11 pydata-sphinx-theme==0.13.3 pygments==2.15.1 -pyparsing==3.1.0 -pyproject-api==1.5.2 -pyrsistent==0.19.3 -pytest==7.3.2 +pyparsing==3.0.9 +pyproject-api==1.5.3 +pytest==7.4.0 pytest-cov==4.1.0 pytest-xdist==3.3.1 python-constraint==1.4.0 @@ -167,11 +160,14 @@ pytz==2023.3 pyyaml==6.0 pyzmq==25.1.0 qrules==0.9.8 +referencing==0.29.1 requests==2.31.0 requests-oauthlib==1.3.1 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 +rpds-py==0.8.8 rsa==4.9 +ruff==0.0.277 scipy==1.10.1 send2trash==1.8.2 six==1.16.0 @@ -192,14 +188,14 @@ sphinxcontrib-htmlhelp==2.0.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 -sqlalchemy==2.0.16 +sqlalchemy==2.0.18 stack-data==0.6.2 sympy==1.12 tabulate==0.9.0 -tensorboard==2.12.3 +tensorboard==2.13.0 tensorboard-data-server==0.7.1 -tensorflow==2.12.0 -tensorflow-estimator==2.12.0 +tensorflow==2.13.0 +tensorflow-estimator==2.13.0 tensorflow-io-gcs-filesystem==0.32.0 tensorflow-probability==0.18.0 tensorwaves==0.4.10 @@ -208,23 +204,21 @@ terminado==0.17.1 tinycss2==1.2.1 tomli==2.0.1 tornado==6.3.2 -tox==4.6.3 +tox==4.6.4 tqdm==4.65.0 traitlets==5.9.0 -typing-extensions==4.6.3 +typing-extensions==4.5.0 uri-template==1.3.0 urllib3==1.26.16 virtualenv==20.23.1 wcwidth==0.2.6 webcolors==1.13 webencodings==0.5.1 -websocket-client==1.6.0 +websocket-client==1.6.1 werkzeug==2.3.6 wheel==0.40.0 -widgetsnbextension==4.0.7 -wrapt==1.14.1 -y-py==0.5.9 -ypy-websocket==0.8.2 +widgetsnbextension==4.0.8 +wrapt==1.15.0 zipp==3.15.0 # The following packages are considered to be unsafe in a requirements file: diff --git a/.constraints/py3.9.txt b/.constraints/py3.9.txt index a9786755..592d9108 100644 --- a/.constraints/py3.9.txt +++ b/.constraints/py3.9.txt @@ -6,17 +6,15 @@ # absl-py==1.4.0 accessible-pygments==0.0.4 -aiofiles==22.1.0 -aiosqlite==0.19.0 alabaster==0.7.13 ampform==0.14.6 -anyio==3.7.0 -aquirdturtle-collapsible-headings==3.1.0 +anyio==3.7.1 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 arrow==1.2.3 asttokens==2.2.1 astunparse==1.6.3 +async-lru==2.0.2 attrs==23.1.0 babel==2.12.1 backcall==0.2.0 @@ -29,7 +27,7 @@ cffi==1.15.1 cfgv==3.3.1 chardet==5.1.0 charset-normalizer==3.1.0 -click==8.1.3 +click==8.1.4 cloudpickle==2.2.1 colorama==0.4.6 comm==0.1.3 @@ -43,7 +41,7 @@ deprecated==1.2.14 distlib==0.3.6 dm-tree==0.1.8 docutils==0.19 -exceptiongroup==1.1.1 +exceptiongroup==1.1.2 execnet==1.9.0 executing==1.2.0 fastjsonschema==2.17.1 @@ -52,51 +50,49 @@ flatbuffers==23.5.26 fonttools==4.40.0 fqdn==1.5.1 gast==0.4.0 -google-auth==2.20.0 +google-auth==2.21.0 google-auth-oauthlib==1.0.0 google-pasta==0.2.0 graphviz==0.20.1 greenlet==2.0.2 -grpcio==1.54.2 +grpcio==1.56.0 h5py==3.9.0 hepunits==2.3.2 identify==2.5.24 idna==3.4 imagesize==1.4.1 -iminuit==2.21.3 +iminuit==2.22.0 importlib-metadata==6.7.0 importlib-resources==5.12.0 iniconfig==2.0.0 -ipykernel==6.23.2 +ipykernel==6.24.0 ipympl==0.9.3 ipython==8.14.0 ipython-genutils==0.2.0 -ipywidgets==8.0.6 +ipywidgets==8.0.7 isoduration==20.11.0 -isort==5.12.0 -jax==0.4.12 -jaxlib==0.4.12 +jax==0.4.13 +jaxlib==0.4.13 jedi==0.18.2 jinja2==3.1.2 json5==0.9.14 jsonpointer==2.4 -jsonschema==4.17.3 +jsonschema==4.18.0 +jsonschema-specifications==2023.6.1 jupyter-cache==0.6.1 -jupyter-client==8.2.0 +jupyter-client==8.3.0 jupyter-core==5.3.1 jupyter-events==0.6.3 -jupyter-server==2.6.0 -jupyter-server-fileid==0.9.0 +jupyter-lsp==2.2.0 +jupyter-server==2.7.0 jupyter-server-terminals==0.4.4 -jupyter-server-ydoc==0.8.0 -jupyter-ydoc==0.2.4 -jupyterlab==3.6.4 +jupyterlab==4.0.2 jupyterlab-code-formatter==2.2.1 -jupyterlab-myst==1.2.0 +jupyterlab-myst==2.0.1 jupyterlab-pygments==0.2.2 jupyterlab-server==2.23.0 -jupyterlab-widgets==3.0.7 -keras==2.12.0 +jupyterlab-widgets==3.0.8 +keras==2.13.1 kiwisolver==1.4.4 latexcodec==2.0.1 libclang==16.0.0 @@ -104,7 +100,7 @@ livereload==2.6.3 markdown==3.4.3 markdown-it-py==2.2.0 markupsafe==2.1.3 -matplotlib==3.7.1 +matplotlib==3.7.2 matplotlib-inline==0.1.6 mdit-py-plugins==0.3.5 mdurl==0.1.2 @@ -114,34 +110,32 @@ mpmath==1.3.0 mypy-extensions==1.0.0 myst-nb==0.17.2 myst-parser==0.18.1 -nbclassic==1.0.0 -nbclient==0.5.13 +nbclient==0.6.8 nbconvert==7.6.0 nbformat==5.9.0 -nbmake==1.3.0 +nbmake==1.4.1 nest-asyncio==1.5.6 nodeenv==1.8.0 -notebook==6.5.4 notebook-shim==0.2.3 -numpy==1.23.5 +numpy==1.24.3 oauthlib==3.2.2 opt-einsum==3.3.0 overrides==7.3.1 packaging==23.1 pandocfilters==1.5.0 parso==0.8.3 -particle==0.22.1 +particle==0.23.0 pathspec==0.11.1 pexpect==4.8.0 phasespace==1.8.0 pickleshare==0.7.5 -pillow==9.5.0 -platformdirs==3.7.0 +pillow==10.0.0 +platformdirs==3.8.1 pluggy==1.2.0 pre-commit==3.3.3 prometheus-client==0.17.0 -prompt-toolkit==3.0.38 -protobuf==4.23.3 +prompt-toolkit==3.0.39 +protobuf==4.23.4 psutil==5.9.5 ptyprocess==0.7.0 pure-eval==0.2.2 @@ -150,13 +144,12 @@ pyasn1-modules==0.3.0 pybtex==0.24.0 pybtex-docutils==1.0.2 pycparser==2.21 -pydantic==1.10.9 +pydantic==1.10.11 pydata-sphinx-theme==0.13.3 pygments==2.15.1 -pyparsing==3.1.0 -pyproject-api==1.5.2 -pyrsistent==0.19.3 -pytest==7.3.2 +pyparsing==3.0.9 +pyproject-api==1.5.3 +pytest==7.4.0 pytest-cov==4.1.0 pytest-xdist==3.3.1 python-constraint==1.4.0 @@ -165,12 +158,15 @@ python-json-logger==2.0.7 pyyaml==6.0 pyzmq==25.1.0 qrules==0.9.8 +referencing==0.29.1 requests==2.31.0 requests-oauthlib==1.3.1 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 +rpds-py==0.8.8 rsa==4.9 -scipy==1.10.1 +ruff==0.0.277 +scipy==1.11.1 send2trash==1.8.2 six==1.16.0 sniffio==1.3.0 @@ -190,14 +186,14 @@ sphinxcontrib-htmlhelp==2.0.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 -sqlalchemy==2.0.16 +sqlalchemy==2.0.18 stack-data==0.6.2 sympy==1.12 tabulate==0.9.0 -tensorboard==2.12.3 +tensorboard==2.13.0 tensorboard-data-server==0.7.1 -tensorflow==2.12.0 -tensorflow-estimator==2.12.0 +tensorflow==2.13.0 +tensorflow-estimator==2.13.0 tensorflow-io-gcs-filesystem==0.32.0 tensorflow-probability==0.18.0 tensorwaves==0.4.10 @@ -206,23 +202,21 @@ terminado==0.17.1 tinycss2==1.2.1 tomli==2.0.1 tornado==6.3.2 -tox==4.6.3 +tox==4.6.4 tqdm==4.65.0 traitlets==5.9.0 -typing-extensions==4.6.3 +typing-extensions==4.5.0 uri-template==1.3.0 urllib3==1.26.16 virtualenv==20.23.1 wcwidth==0.2.6 webcolors==1.13 webencodings==0.5.1 -websocket-client==1.6.0 +websocket-client==1.6.1 werkzeug==2.3.6 wheel==0.40.0 -widgetsnbextension==4.0.7 -wrapt==1.14.1 -y-py==0.5.9 -ypy-websocket==0.8.2 +widgetsnbextension==4.0.8 +wrapt==1.15.0 zipp==3.15.0 # The following packages are considered to be unsafe in a requirements file: diff --git a/.cspell.json b/.cspell.json index 2e00672a..fd41364f 100644 --- a/.cspell.json +++ b/.cspell.json @@ -22,14 +22,11 @@ "*particle*.*ml", ".constraints/*.txt", ".editorconfig", - ".flake8*", ".gitignore", ".gitpod.*", ".mypy.ini", ".pre-commit-config.yaml", ".prettierignore", - ".pydocstyle*", - ".pylintrc", ".readthedocs.yml", ".vscode/*", ".vscode/.gitignore", diff --git a/.gitpod.yml b/.gitpod.yml index 1c6a7656..1eca252d 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -13,9 +13,11 @@ github: vscode: extensions: + - charliermarsh.ruff - eamodio.gitlens - editorconfig.editorconfig - esbenp.prettier-vscode + - garaioag.garaio-vscode-unwanted-recommendations - github.vscode-github-actions - github.vscode-pull-request-github - ms-python.python diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21578067..2b3c2c43 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/ComPWA/repo-maintenance - rev: 0.0.182 + rev: 0.0.189 hooks: - id: check-dev-files args: @@ -44,11 +44,12 @@ repos: - id: nbqa-black additional_dependencies: - black>=22.1.0 - - id: nbqa-flake8 - - id: nbqa-isort - id: nbqa-pyupgrade args: - --py37-plus + - id: nbqa-ruff + args: + - --fix - repo: https://github.com/psf/black rev: 23.3.0 @@ -71,11 +72,6 @@ repos: .*\.py )$ - - repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - - repo: https://github.com/kynan/nbstripout rev: 0.6.1 hooks: @@ -101,22 +97,29 @@ repos: metadata.vscode - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.9-for-vscode + rev: v3.0.0 hooks: - id: prettier - repo: https://github.com/ComPWA/mirrors-pyright - rev: v1.1.315 + rev: v1.1.316 hooks: - id: pyright - repo: https://github.com/asottile/pyupgrade - rev: v3.7.0 + rev: v3.8.0 hooks: - id: pyupgrade args: - --py37-plus + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.277 + hooks: + - id: ruff + args: + - --fix + - repo: https://github.com/ComPWA/mirrors-taplo rev: v0.8.0 hooks: diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e9ae2c93..979ce482 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,8 +1,10 @@ { "recommendations": [ + "charliermarsh.ruff", "eamodio.gitlens", "editorconfig.editorconfig", "esbenp.prettier-vscode", + "garaioag.garaio-vscode-unwanted-recommendations", "github.vscode-github-actions", "github.vscode-pull-request-github", "ms-python.python", @@ -17,5 +19,13 @@ "tamasfe.even-better-toml", "tyriar.sort-lines", "yzhang.markdown-all-in-one" + ], + "unwantedRecommendations": [ + "bungcip.better-toml", + "ms-python.flake8", + "ms-python.isort", + "ms-python.mypy-type-checker", + "ms-python.pylint", + "travisillig.vscode-json-stable-stringify" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 6ed525f6..f1549816 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,15 +34,20 @@ "github-actions.workflows.pinned.workflows": [".github/workflows/ci.yml"], "livePreview.defaultPreviewPath": "docs/_build/html", "python.analysis.autoImportCompletions": false, - "python.analysis.diagnosticMode": "workspace", "python.analysis.inlayHints.pytestParameters": true, "python.analysis.typeCheckingMode": "strict", "python.formatting.provider": "black", "python.linting.enabled": true, + "python.linting.flake8Enabled": false, + "python.linting.mypyEnabled": false, + "python.linting.pydocstyleEnabled": false, + "python.linting.pylintEnabled": false, "python.testing.pytestArgs": ["--color=no"], "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, "rewrap.wrappingColumn": 88, + "ruff.enable": true, + "ruff.organizeImports": true, "yaml.schemas": { "https://json.schemastore.org/github-workflow.json": ".github/workflows/requirements.yml" } diff --git a/README.md b/README.md index ebd935fd..7f496f47 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ [![GitPod](https://img.shields.io/badge/gitpod-open-blue?logo=gitpod)](https://gitpod.io/#https://github.com/ComPWA/ampform-dpd) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![Spelling checked](https://img.shields.io/badge/cspell-checked-brightgreen.svg)](https://github.com/streetsidesoftware/cspell/tree/master/packages/cspell) +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) This repository is a (temporary) extension of [AmpForm](https://ampform.rtfd.io) and provides a symbolic implementation of Dalitz-plot decomposition ([10.1103/PhysRevD.101.034033](https://journals.aps.org/prd/abstract/10.1103/PhysRevD.101.034033)) with [SymPy](https://www.sympy.org/en/index.html). It has been extracted from the [ComPWA/polarimetry](https://github.com/ComPWA/polarimetry) repository, which is not yet public. diff --git a/docs/_relink_references.py b/docs/_relink_references.py index 73a591d3..98fe0dc3 100644 --- a/docs/_relink_references.py +++ b/docs/_relink_references.py @@ -8,17 +8,25 @@ """ from __future__ import annotations +from typing import TYPE_CHECKING + import sphinx.domains.python from docutils import nodes from sphinx.addnodes import pending_xref, pending_xref_condition from sphinx.domains.python import parse_reftarget -from sphinx.environment import BuildEnvironment + +if TYPE_CHECKING: + from sphinx.environment import BuildEnvironment __TARGET_SUBSTITUTIONS = { + "Literal[(-1, 1)]": "typing.Literal", "Literal[- 1, 1]": "typing.Literal", "Literal[-1, 1]": "typing.Literal", "OuterStates": "ampform_dpd.decay.OuterStates", + "ParameterValue": "tensorwaves.interface.ParameterValue", + "ParametrizedBackendFunction": "tensorwaves.function.ParametrizedBackendFunction", "PoolSum": "ampform.sympy.PoolSum", + "PositionalArgumentFunction": "tensorwaves.function.PositionalArgumentFunction", "sp.Expr": "sympy.core.expr.Expr", "sp.Indexed": "sympy.tensor.indexed.Indexed", "sp.Rational": "sympy.core.numbers.Rational", @@ -28,12 +36,13 @@ } __REF_TYPE_SUBSTITUTIONS = { "ampform_dpd.decay.OuterStates": "obj", + "tensorwaves.interface.ParameterValue": "obj", } def _new_type_to_xref( target: str, - env: BuildEnvironment = None, + env: BuildEnvironment | None = None, suppress_prefix: bool = False, ) -> pending_xref: reftype, target, title, refspecific = parse_reftarget(target, suppress_prefix) diff --git a/docs/_unsrt_et_al.py b/docs/_unsrt_et_al.py index fe01a836..6ccfce50 100644 --- a/docs/_unsrt_et_al.py +++ b/docs/_unsrt_et_al.py @@ -1,10 +1,10 @@ from pybtex.database import Entry from pybtex.richtext import Tag, Text from pybtex.style.formatting.unsrt import Style as UnsrtStyle -from pybtex.style.template import _format_list # pyright: ignore[reportPrivateUsage] from pybtex.style.template import ( FieldIsMissing, Node, + _format_list, # pyright: ignore[reportPrivateUsage] field, href, join, @@ -22,8 +22,7 @@ def format_names(self, role: Entry, as_sentence: bool = True) -> Node: formatted_names = names(role, sep=", ", sep2=" and ", last_sep=", and ") if as_sentence: return sentence[formatted_names] - else: - return formatted_names + return formatted_names def format_eprint(self, e: Entry) -> Node: if "doi" in e.fields: @@ -62,12 +61,11 @@ def et_al(children, data, sep="", sep2=None, last_sep=None): parts = [part for part in _format_list(children, data) if part] if len(parts) <= 1: return Text(*parts) - elif len(parts) == 2: + if len(parts) == 2: return Text(sep2).join(parts) - elif len(parts) == 3: + if len(parts) == 3: return Text(last_sep).join([Text(sep).join(parts[:-1]), parts[-1]]) - else: - return Text(parts[0], Tag("em", " et al")) + return Text(parts[0], Tag("em", " et al")) @node # pyright: ignore[reportUntypedFunctionDecorator] @@ -77,7 +75,7 @@ def names(children, context, role, **kwargs): try: persons = context["entry"].persons[role] except KeyError: - raise FieldIsMissing(role, context["entry"]) + raise FieldIsMissing(role, context["entry"]) from None style = context["style"] formatted_names = [ diff --git a/docs/comparison/d2kkk.ipynb b/docs/comparison/d2kkk.ipynb index 68b99e15..dcec4204 100644 --- a/docs/comparison/d2kkk.ipynb +++ b/docs/comparison/d2kkk.ipynb @@ -35,7 +35,7 @@ "import logging\n", "import os\n", "from textwrap import dedent\n", - "from typing import Iterable\n", + "from typing import TYPE_CHECKING, Iterable\n", "\n", "import ampform\n", "import graphviz\n", @@ -44,7 +44,6 @@ "import matplotlib.pyplot as plt\n", "import qrules\n", "import sympy as sp\n", - "from ampform.helicity import HelicityModel\n", "from ampform.kinematics import FourMomentumSymbol, InvariantMass\n", "from ampform.sympy import perform_cached_doit\n", "from IPython.display import SVG, Latex, Markdown, clear_output, display\n", @@ -60,11 +59,9 @@ " VBox,\n", " interactive_output,\n", ")\n", - "from qrules.transition import ReactionInfo\n", "from tensorwaves.data.phasespace import TFPhaseSpaceGenerator\n", "from tensorwaves.data.rng import TFUniformRealNumberGenerator\n", "from tensorwaves.data.transform import SympyDataTransformer\n", - "from tensorwaves.interface import DataSample, ParameterValue, ParametrizedFunction\n", "\n", "from ampform_dpd import DalitzPlotDecompositionBuilder, simplify_latex_rendering\n", "from ampform_dpd.decay import (\n", @@ -81,6 +78,15 @@ ")\n", "from ampform_dpd.spin import filter_parity_violating_ls, generate_ls_couplings\n", "\n", + "if TYPE_CHECKING:\n", + " from ampform.helicity import HelicityModel\n", + " from qrules.transition import ReactionInfo\n", + " from tensorwaves.interface import (\n", + " DataSample,\n", + " ParameterValue,\n", + " ParametrizedFunction,\n", + " )\n", + "\n", "simplify_latex_rendering()\n", "logging.getLogger(\"jax\").setLevel(logging.ERROR) # mute JAX\n", "os.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\" # mute TF\n", @@ -643,17 +649,16 @@ "outputs": [], "source": [ "def create_sliders() -> dict[str, ToggleButtons]:\n", - " all_parameters = {k: v for k, v in ampform_model.parameter_defaults.items()}\n", - " all_parameters.update({k: v for k, v in dpd_model.parameter_defaults.items()})\n", + " all_parameters = dict(ampform_model.parameter_defaults.items())\n", + " all_parameters.update(dpd_model.parameter_defaults)\n", " sliders = {}\n", " for symbol, value in all_parameters.items():\n", " value = \"+1\"\n", " if (\n", " symbol.name.startswith(R\"\\mathcal{H}^\\mathrm{decay}\")\n", " and \"+\" in symbol.name\n", - " ):\n", - " if any(s in symbol.name for s in [\"{1}\", \"*\", \"rho\"]):\n", - " value = \"-1\"\n", + " ) and any(s in symbol.name for s in [\"{1}\", \"*\", \"rho\"]):\n", + " value = \"-1\"\n", " sliders[symbol.name] = ToggleButtons(\n", " description=Rf\"\\({sp.latex(symbol)}\\)\",\n", " options=[\"-1\", \"0\", \"+1\"],\n", @@ -666,7 +671,7 @@ "def to_unicode(particle: Particle) -> str:\n", " unicode = particle.name\n", " unicode = unicode.replace(\"pi\", \"π\")\n", - " unicode = unicode.replace(\"rho\", \"ρ\")\n", + " unicode = unicode.replace(\"rho\", \"p\")\n", " unicode = unicode.replace(\"Sigma\", \"Σ\")\n", " unicode = unicode.replace(\"~\", \"\")\n", " unicode = unicode.replace(\"Σ\", \"~Σ\")\n", @@ -674,8 +679,7 @@ " unicode = unicode.replace(\"-\", \"⁻\")\n", " unicode = unicode.replace(\"(0)\", \"₀\")\n", " unicode = unicode.replace(\"(1)\", \"₁\")\n", - " unicode = unicode.replace(\")0\", \")⁰\")\n", - " return unicode\n", + " return unicode.replace(\")0\", \")⁰\")\n", "\n", "\n", "sliders = create_sliders()\n", @@ -1030,7 +1034,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.16" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/docs/comparison/jpsi2phipipi.ipynb b/docs/comparison/jpsi2phipipi.ipynb index a6ded54f..869f28a4 100644 --- a/docs/comparison/jpsi2phipipi.ipynb +++ b/docs/comparison/jpsi2phipipi.ipynb @@ -35,7 +35,7 @@ "import logging\n", "import os\n", "from textwrap import dedent\n", - "from typing import Iterable\n", + "from typing import TYPE_CHECKING, Iterable\n", "\n", "import ampform\n", "import graphviz\n", @@ -44,7 +44,6 @@ "import matplotlib.pyplot as plt\n", "import qrules\n", "import sympy as sp\n", - "from ampform.helicity import HelicityModel\n", "from ampform.kinematics import FourMomentumSymbol, InvariantMass\n", "from ampform.sympy import perform_cached_doit\n", "from IPython.display import SVG, Latex, Markdown, clear_output, display\n", @@ -60,11 +59,9 @@ " VBox,\n", " interactive_output,\n", ")\n", - "from qrules.transition import ReactionInfo\n", "from tensorwaves.data.phasespace import TFPhaseSpaceGenerator\n", "from tensorwaves.data.rng import TFUniformRealNumberGenerator\n", "from tensorwaves.data.transform import SympyDataTransformer\n", - "from tensorwaves.interface import DataSample, ParameterValue, ParametrizedFunction\n", "\n", "from ampform_dpd import DalitzPlotDecompositionBuilder, simplify_latex_rendering\n", "from ampform_dpd.decay import (\n", @@ -81,6 +78,15 @@ ")\n", "from ampform_dpd.spin import filter_parity_violating_ls, generate_ls_couplings\n", "\n", + "if TYPE_CHECKING:\n", + " from ampform.helicity import HelicityModel\n", + " from qrules.transition import ReactionInfo\n", + " from tensorwaves.interface import (\n", + " DataSample,\n", + " ParameterValue,\n", + " ParametrizedFunction,\n", + " )\n", + "\n", "simplify_latex_rendering()\n", "logging.getLogger(\"jax\").setLevel(logging.ERROR) # mute JAX\n", "os.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\" # mute TF\n", @@ -626,17 +632,16 @@ "outputs": [], "source": [ "def create_sliders() -> dict[str, ToggleButtons]:\n", - " all_parameters = {k: v for k, v in ampform_model.parameter_defaults.items()}\n", - " all_parameters.update({k: v for k, v in dpd_model.parameter_defaults.items()})\n", + " all_parameters = dict(ampform_model.parameter_defaults.items())\n", + " all_parameters.update(dpd_model.parameter_defaults)\n", " sliders = {}\n", " for symbol, value in all_parameters.items():\n", " value = \"+1\"\n", " if (\n", " symbol.name.startswith(R\"\\mathcal{H}^\\mathrm{decay}\")\n", " and \"+\" in symbol.name\n", - " ):\n", - " if any(s in symbol.name for s in [\"{1}\", \"*\", \"rho\"]):\n", - " value = \"-1\"\n", + " ) and any(s in symbol.name for s in [\"{1}\", \"*\", \"rho\"]):\n", + " value = \"-1\"\n", " sliders[symbol.name] = ToggleButtons(\n", " description=Rf\"\\({sp.latex(symbol)}\\)\",\n", " options=[\"-1\", \"0\", \"+1\"],\n", @@ -649,7 +654,7 @@ "def to_unicode(particle: Particle) -> str:\n", " unicode = particle.name\n", " unicode = unicode.replace(\"pi\", \"π\")\n", - " unicode = unicode.replace(\"rho\", \"ρ\")\n", + " unicode = unicode.replace(\"rho\", \"p\")\n", " unicode = unicode.replace(\"Sigma\", \"Σ\")\n", " unicode = unicode.replace(\"~\", \"\")\n", " unicode = unicode.replace(\"Σ\", \"~Σ\")\n", @@ -657,8 +662,7 @@ " unicode = unicode.replace(\"-\", \"⁻\")\n", " unicode = unicode.replace(\"(0)\", \"₀\")\n", " unicode = unicode.replace(\"(1)\", \"₁\")\n", - " unicode = unicode.replace(\")0\", \")⁰\")\n", - " return unicode\n", + " return unicode.replace(\")0\", \")⁰\")\n", "\n", "\n", "sliders = create_sliders()\n", @@ -1015,7 +1019,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.16" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/docs/comparison/jpsi2pipipi.ipynb b/docs/comparison/jpsi2pipipi.ipynb index ecf90aa4..92acc26d 100644 --- a/docs/comparison/jpsi2pipipi.ipynb +++ b/docs/comparison/jpsi2pipipi.ipynb @@ -35,7 +35,7 @@ "import logging\n", "import os\n", "from textwrap import dedent\n", - "from typing import Iterable\n", + "from typing import TYPE_CHECKING, Iterable\n", "\n", "import ampform\n", "import graphviz\n", @@ -44,7 +44,6 @@ "import matplotlib.pyplot as plt\n", "import qrules\n", "import sympy as sp\n", - "from ampform.helicity import HelicityModel\n", "from ampform.kinematics import FourMomentumSymbol, InvariantMass\n", "from ampform.sympy import perform_cached_doit\n", "from IPython.display import SVG, Latex, Markdown, clear_output, display\n", @@ -60,11 +59,9 @@ " VBox,\n", " interactive_output,\n", ")\n", - "from qrules.transition import ReactionInfo\n", "from tensorwaves.data.phasespace import TFPhaseSpaceGenerator\n", "from tensorwaves.data.rng import TFUniformRealNumberGenerator\n", "from tensorwaves.data.transform import SympyDataTransformer\n", - "from tensorwaves.interface import DataSample, ParameterValue, ParametrizedFunction\n", "\n", "from ampform_dpd import DalitzPlotDecompositionBuilder, simplify_latex_rendering\n", "from ampform_dpd.decay import (\n", @@ -81,6 +78,15 @@ ")\n", "from ampform_dpd.spin import filter_parity_violating_ls, generate_ls_couplings\n", "\n", + "if TYPE_CHECKING:\n", + " from ampform.helicity import HelicityModel\n", + " from qrules.transition import ReactionInfo\n", + " from tensorwaves.interface import (\n", + " DataSample,\n", + " ParameterValue,\n", + " ParametrizedFunction,\n", + " )\n", + "\n", "simplify_latex_rendering()\n", "logging.getLogger(\"jax\").setLevel(logging.ERROR) # mute JAX\n", "os.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\" # mute TF\n", @@ -626,17 +632,16 @@ "outputs": [], "source": [ "def create_sliders() -> dict[str, ToggleButtons]:\n", - " all_parameters = {k: v for k, v in ampform_model.parameter_defaults.items()}\n", - " all_parameters.update({k: v for k, v in dpd_model.parameter_defaults.items()})\n", + " all_parameters = dict(ampform_model.parameter_defaults.items())\n", + " all_parameters.update(dpd_model.parameter_defaults)\n", " sliders = {}\n", " for symbol, value in all_parameters.items():\n", " value = \"+1\"\n", " if (\n", " symbol.name.startswith(R\"\\mathcal{H}^\\mathrm{decay}\")\n", " and \"+\" in symbol.name\n", - " ):\n", - " if any(s in symbol.name for s in [\"{1}\", \"*\", \"rho\"]):\n", - " value = \"-1\"\n", + " ) and any(s in symbol.name for s in [\"{1}\", \"*\", \"rho\"]):\n", + " value = \"-1\"\n", " sliders[symbol.name] = ToggleButtons(\n", " description=Rf\"\\({sp.latex(symbol)}\\)\",\n", " options=[\"-1\", \"0\", \"+1\"],\n", @@ -649,7 +654,7 @@ "def to_unicode(particle: Particle) -> str:\n", " unicode = particle.name\n", " unicode = unicode.replace(\"pi\", \"π\")\n", - " unicode = unicode.replace(\"rho\", \"ρ\")\n", + " unicode = unicode.replace(\"rho\", \"p\")\n", " unicode = unicode.replace(\"Sigma\", \"Σ\")\n", " unicode = unicode.replace(\"~\", \"\")\n", " unicode = unicode.replace(\"Σ\", \"~Σ\")\n", @@ -657,8 +662,7 @@ " unicode = unicode.replace(\"-\", \"⁻\")\n", " unicode = unicode.replace(\"(0)\", \"₀\")\n", " unicode = unicode.replace(\"(1)\", \"₁\")\n", - " unicode = unicode.replace(\")0\", \")⁰\")\n", - " return unicode\n", + " return unicode.replace(\")0\", \")⁰\")\n", "\n", "\n", "sliders = create_sliders()\n", @@ -1013,7 +1017,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.16" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/docs/conf.py b/docs/conf.py index 71f1c12e..05ec2219 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,6 +16,8 @@ from importlib.metadata import version as get_package_version sys.path.insert(0, os.path.abspath(".")) +import contextlib + from _relink_references import relink_references from _unsrt_et_al import MyStyle @@ -36,13 +38,11 @@ def get_execution_mode() -> str: def get_logo_path() -> str | None: path = "_static/logo.svg" - try: + with contextlib.suppress(requests.exceptions.ConnectionError): _fetch_logo( url="https://raw.githubusercontent.com/ComPWA/ComPWA/04e5199/doc/images/logo.svg", output_path=path, ) - except requests.exceptions.ConnectionError: - pass if os.path.exists(path): return path return None @@ -69,8 +69,8 @@ def generate_api() -> None: " ".join( [ "sphinx-apidoc", - f"../src/ampform_dpd/", - f"../src/ampform_dpd/version.py", + "../src/ampform_dpd/", + "../src/ampform_dpd/version.py", "-o api/", "--force", "--no-toc", @@ -78,7 +78,7 @@ def generate_api() -> None: "--templatedir _templates", ] ), - shell=True, + shell=True, # noqa: S602 ) @@ -112,7 +112,7 @@ def generate_api() -> None: "references.bib", ] codeautolink_concat_default = True -copyright = "2022" +copyright = "2022" # noqa: A001 default_role = "py:obj" exclude_patterns = [ "**.ipynb_checkpoints", diff --git a/docs/jpsi2ksp.ipynb b/docs/jpsi2ksp.ipynb index 3bf110fb..705223fd 100644 --- a/docs/jpsi2ksp.ipynb +++ b/docs/jpsi2ksp.ipynb @@ -29,7 +29,7 @@ "import itertools\n", "import logging\n", "import os\n", - "from typing import Iterable\n", + "from typing import TYPE_CHECKING, Iterable\n", "\n", "import jax.numpy as jnp\n", "import matplotlib.pyplot as plt\n", @@ -46,7 +46,6 @@ ")\n", "from IPython.display import Latex, Markdown\n", "from tensorwaves.data.transform import SympyDataTransformer\n", - "from tensorwaves.interface import DataSample, ParametrizedFunction\n", "from tqdm.auto import tqdm\n", "\n", "from ampform_dpd import (\n", @@ -63,6 +62,9 @@ "from ampform_dpd.io import as_markdown_table, aslatex, perform_cached_lambdify\n", "from ampform_dpd.spin import filter_parity_violating_ls, generate_ls_couplings\n", "\n", + "if TYPE_CHECKING:\n", + " from tensorwaves.interface import DataSample, ParametrizedFunction\n", + "\n", "simplify_latex_rendering()\n", "logging.getLogger(\"absl\").setLevel(logging.ERROR) # mute JAX\n", "NO_TQDM = \"EXECUTE_NB\" in os.environ\n", @@ -470,9 +472,8 @@ " return s2\n", " if decay_masses == {m1, m2}:\n", " return s3\n", - " raise NotImplementedError(\n", - " f\"Cannot find Mandelstam variable for {''.join(decay_masses)}\"\n", - " )" + " msg = f\"Cannot find Mandelstam variable for {''.join(decay_masses)}\"\n", + " raise NotImplementedError(msg)" ] }, { @@ -969,7 +970,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.16" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/docs/lc2pkpi.ipynb b/docs/lc2pkpi.ipynb index c2a3d7da..d5147f1e 100644 --- a/docs/lc2pkpi.ipynb +++ b/docs/lc2pkpi.ipynb @@ -307,9 +307,8 @@ " return s2\n", " if decay_masses == {m1, m2}:\n", " return s3\n", - " raise NotImplementedError(\n", - " f\"Cannot find Mandelstam variable for {''.join(decay_masses)}\"\n", - " )\n", + " msg = f\"Cannot find Mandelstam variable for {''.join(decay_masses)}\"\n", + " raise NotImplementedError(msg)\n", "\n", "\n", "def _to_mass_symbol(particle: Particle) -> sp.Symbol:\n", @@ -374,7 +373,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.16" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/pyproject.toml b/pyproject.toml index 891e8526..5fd81195 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,26 +32,42 @@ target-version = [ "py39", ] -[tool.isort] -known_third_party = "THIRDPARTY,sympy" -profile = "black" -src_paths = [ - "src", -] - [tool.nbqa.addopts] -black = [ - "--line-length=85", -] -flake8 = [ - "--extend-ignore=E501,E731", -] -isort = [ +black = ["--line-length=85"] +ruff = [ + "--extend-ignore=B018", + "--extend-ignore=C90", + "--extend-ignore=D", + "--extend-ignore=N806", + "--extend-ignore=N816", + "--extend-ignore=PLR09", + "--extend-ignore=PLR2004", + "--extend-ignore=PLW0602", + "--extend-ignore=PLW0603", + "--extend-ignore=PLW2901", "--line-length=85", ] -[tool.nbqa.exclude] -flake8 = "^docs/appendix/benchmark.ipynb" +[tool.pyright] +reportGeneralTypeIssues = false +reportImportCycles = false +reportIncompatibleMethodOverride = false +reportMissingParameterType = false +reportMissingTypeArgument = false +reportMissingTypeStubs = false +reportPrivateImportUsage = false +reportUnknownArgumentType = false +reportUnknownLambdaType = false +reportUnknownMemberType = false +reportUnknownParameterType = false +reportUnknownVariableType = false +reportUnnecessaryContains = false +reportUnnecessaryIsInstance = false +reportUnusedClass = true +reportUnusedFunction = true +reportUnusedImport = true +reportUnusedVariable = true +typeCheckingMode = "strict" [tool.pytest.ini_options] addopts = [ @@ -78,3 +94,98 @@ testpaths = [ "src", "tests", ] + +[tool.ruff] +extend-select = [ + "A", + "B", + "BLE", + "C4", + "C90", + "D", + "EM", + "ERA", + "FA", + "I", + "ICN", + "INP", + "ISC", + "N", + "NPY", + "PGH", + "PIE", + "PL", + "Q", + "RET", + "RSE", + "RUF", + "S", + "SIM", + "T20", + "TCH", + "TID", + "TRY", + "UP", + "YTT", +] +ignore = [ + "B028", # missing explicit stacklevel keyword + "C408", + "D101", + "D102", + "D103", + "D105", + "D107", + "D203", + "D213", + "D407", + "D416", + "E501", + "ISC003", + "PLR0913", # sympy class + "S301", + "SIM108", +] +show-fixes = true +src = [ + "src", + "tests", +] +target-version = "py37" +task-tags = ["cspell"] + +[tool.ruff.per-file-ignores] +"*" = ["D"] +"docs/*" = [ + "E402", + "INP001", + "PLR2004", + "S101", + "S113", + "T201", +] +"setup.py" = ["D100"] +"tests/*" = [ + "D", + "INP001", + "PGH001", + "PLR0913", + "PLR2004", + "S101", +] + +[tool.ruff.pep8-naming] +ignore-names = [ + "A", + "H", + "L", + "R", + "R_dec", + "R_prod", + "S", + "Γ*", + "λ*", +] + +[tool.ruff.pydocstyle] +convention = "google" diff --git a/pyrightconfig.json b/pyrightconfig.json deleted file mode 100644 index bb58f27a..00000000 --- a/pyrightconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "exclude": [ - "**/__pycache__", - "**/_build", - "**/.git", - "**/.ipynb_checkpoints", - "**/.mypy_cache", - "**/.pytest_cache", - "**/.tox" - ], - "reportGeneralTypeIssues": false, - "reportImportCycles": false, - "reportIncompatibleMethodOverride": false, - "reportMissingParameterType": false, - "reportMissingTypeArgument": false, - "reportMissingTypeStubs": false, - "reportPrivateImportUsage": false, - "reportUnknownArgumentType": false, - "reportUnknownLambdaType": false, - "reportUnknownMemberType": false, - "reportUnknownParameterType": false, - "reportUnknownVariableType": false, - "reportUnnecessaryContains": false, - "reportUnnecessaryIsInstance": false, - "reportUnusedClass": true, - "reportUnusedFunction": true, - "reportUnusedImport": true, - "reportUnusedVariable": true, - "typeCheckingMode": "strict" -} diff --git a/setup.cfg b/setup.cfg index 01a1f626..8a48ebf6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -70,22 +70,24 @@ doc = tqdm jupyter = %(doc)s - aquirdturtle-collapsible-headings jupyterlab >=3.0 jupyterlab-code-formatter jupyterlab-myst - ypy-websocket <0.8.3 # https://github.com/ComPWA/ampform-dpd/actions/runs/4350341987/jobs/7600958934#step:3:78 + ypy-websocket <0.8.3; python_version <"3.8.0" test = - nbmake <=1.3.0 # https://github.com/ComPWA/ampform-dpd/actions/runs/3190469093/jobs/5205620578#step:3:69 + nbmake + nbmake <1.3; python_version <"3.8.0" numpy pytest >=6.0 # pyproject.toml pytest-cov pytest-xdist format = black - isort +lint = + ruff sty = %(format)s + %(lint)s %(test)s # for pytest type hints docutils pre-commit >=1.4.0 diff --git a/src/ampform_dpd/__init__.py b/src/ampform_dpd/__init__.py index 33b87f33..d1d15fc8 100644 --- a/src/ampform_dpd/__init__.py +++ b/src/ampform_dpd/__init__.py @@ -10,9 +10,8 @@ from attrs import field, frozen from sympy.core.symbol import Str from sympy.physics.matrices import msigma -from sympy.physics.quantum.spin import CG +from sympy.physics.quantum.spin import CG, WignerD from sympy.physics.quantum.spin import Rotation as Wigner -from sympy.physics.quantum.spin import WignerD from ampform_dpd.decay import ( IsobarNode, @@ -66,16 +65,14 @@ def __init__( if isinstance(min_ls, bool): self.use_production_helicity_couplings = min_ls self.use_decay_helicity_couplings = min_ls - elif isinstance(min_ls, tuple) and len(min_ls) == 2: + elif isinstance(min_ls, tuple) and len(min_ls) == 2: # noqa: PLR2004 ( self.use_production_helicity_couplings, self.use_decay_helicity_couplings, ) = min_ls else: - raise NotImplementedError( - f"Cannot configure helicity couplings with a {type(min_ls).__name__}", - min_ls, - ) + msg = f"Cannot configure helicity couplings with a {type(min_ls).__name__}" + raise NotImplementedError(msg, min_ls) def formulate( self, @@ -309,15 +306,13 @@ def __get_chain(self, identifier) -> ThreeBodyDecayChain: if isinstance(identifier, ThreeBodyDecayChain): chain = identifier if chain not in set(self.__decay.chains): - raise ValueError( - f"Decay does not have chain with resonance {chain.resonance.name}" - ) + msg = f"Decay does not have chain with resonance {chain.resonance.name}" + raise ValueError(msg) return chain if isinstance(identifier, str): return self.__decay.find_chain(identifier) - raise NotImplementedError( - f"Cannot get decay chain for identifier type {type(identifier)}" - ) + msg = f"Cannot get decay chain for identifier type {type(identifier)}" + raise NotImplementedError(msg) @property def decay(self) -> ThreeBodyDecay: @@ -340,7 +335,7 @@ def formulate_non_resonant( def simplify_latex_rendering() -> None: """Improve LaTeX rendering of an `~sympy.tensor.indexed.Indexed` object.""" - def _print_Indexed_latex(self, printer, *args): + def _print_Indexed_latex(self, printer, *args): # noqa: N802 base = printer._print(self.base) indices = ", ".join(map(printer._print, self.indices)) return f"{base}_{{{indices}}}" @@ -353,9 +348,8 @@ def _formulate_clebsch_gordan_factors( helicities: dict[Particle, sp.Rational | sp.Symbol], ) -> sp.Expr: if isobar.interaction is None: - raise ValueError( - "Cannot formulate amplitude model in LS-basis if LS-couplings are missing" - ) + msg = "Cannot formulate amplitude model in LS-basis if LS-couplings are missing" + raise ValueError(msg) # https://github.com/ComPWA/ampform/blob/65b4efa/src/ampform/helicity/__init__.py#L785-L802 # and supplementary material p.1 (https://cds.cern.ch/record/2824328/files) child1 = _get_particle(isobar.child1) @@ -396,10 +390,11 @@ def formulate_polarimetry( ) -> tuple[PoolSum, PoolSum, PoolSum]: half = sp.Rational(1, 2) if builder.decay.initial_state.spin != half: - raise ValueError( + msg = ( "Can only formulate polarimetry for an initial state with spin 1/2, but" f" got {builder.decay.initial_state.spin}" ) + raise ValueError(msg) model = builder.formulate(reference_subsystem) λ0, λ0_prime = sp.symbols(R"lambda \lambda^{\prime}", rational=True) λ = { diff --git a/src/ampform_dpd/_attrs.py b/src/ampform_dpd/_attrs.py index 65aa6502..509eb3d6 100644 --- a/src/ampform_dpd/_attrs.py +++ b/src/ampform_dpd/_attrs.py @@ -4,17 +4,17 @@ from typing import TYPE_CHECKING, SupportsFloat import sympy as sp -from attrs import Attribute if TYPE_CHECKING: + from attrs import Attribute + from ampform_dpd.decay import LSCoupling def assert_spin_value(instance, attribute: Attribute, value: sp.Rational) -> None: if value.denominator not in {1, 2}: - raise ValueError( - f"{attribute.name} value should be integer or half-integer, not {value}" - ) + msg = f"{attribute.name} value should be integer or half-integer, not {value}" + raise ValueError(msg) def to_ls(obj: LSCoupling | tuple[int, SupportsFloat] | None) -> LSCoupling: @@ -27,7 +27,8 @@ def to_ls(obj: LSCoupling | tuple[int, SupportsFloat] | None) -> LSCoupling: if isinstance(obj, tuple): L, S = obj return LSCoupling(L, S) - raise TypeError(f"Cannot convert {type(obj).__name__} to {LSCoupling.__name__}") + msg = f"Cannot convert {type(obj).__name__} to {LSCoupling.__name__}" + raise TypeError(msg) def to_rational(obj: SupportsFloat) -> sp.Rational: diff --git a/src/ampform_dpd/angles.py b/src/ampform_dpd/angles.py index 1ef059a3..224d3a47 100644 --- a/src/ampform_dpd/angles.py +++ b/src/ampform_dpd/angles.py @@ -15,17 +15,18 @@ def formulate_scattering_angle( rest frame of the isobar resonance :math:`(ij)`. """ if not {state_id, sibling_id} <= {1, 2, 3}: - raise ValueError(f"Child IDs need to be one of 1, 2, 3") + msg = "Child IDs need to be one of 1, 2, 3" + raise ValueError(msg) # pyright: ignore[reportUnnecessaryContains] if {state_id, sibling_id} in {(2, 1), (3, 2), (1, 3)}: - raise NotImplementedError( - f"Cannot compute scattering angle θ{state_id}{sibling_id}" - ) + msg = f"Cannot compute scattering angle θ{state_id}{sibling_id}" + raise NotImplementedError(msg) if state_id == sibling_id: - raise ValueError(f"IDs of the decay products cannot be equal: {state_id}") + msg = f"IDs of the decay products cannot be equal: {state_id}" + raise ValueError(msg) symbol = sp.Symbol(Rf"theta_{state_id}{sibling_id}", real=True) spectator_id = next(iter({1, 2, 3} - {state_id, sibling_id})) - m0 = sp.Symbol(f"m0", nonnegative=True) + m0 = sp.Symbol("m0", nonnegative=True) mi = sp.Symbol(f"m{state_id}", nonnegative=True) mj = sp.Symbol(f"m{sibling_id}", nonnegative=True) mk = sp.Symbol(f"m{spectator_id}", nonnegative=True) @@ -50,15 +51,14 @@ def formulate_theta_hat_angle( r"""Formulate an expression for :math:`\hat\theta_{i(j)}`.""" allowed_ids = {1, 2, 3} if not {isobar_id, aligned_subsystem} <= allowed_ids: - raise ValueError( - f"Child IDs need to be one of {', '.join(map(str, allowed_ids))}" - ) + msg = f"Child IDs need to be one of {', '.join(map(str, allowed_ids))}" + raise ValueError(msg) symbol = sp.Symbol(Rf"\hat\theta_{isobar_id}({aligned_subsystem})", real=True) if isobar_id == aligned_subsystem: return symbol, sp.S.Zero if (isobar_id, aligned_subsystem) in {(3, 1), (1, 2), (2, 3)}: remaining_id = next(iter(allowed_ids - {isobar_id, aligned_subsystem})) - m0 = sp.Symbol(f"m0", nonnegative=True) + m0 = sp.Symbol("m0", nonnegative=True) mi = sp.Symbol(f"m{isobar_id}", nonnegative=True) mj = sp.Symbol(f"m{aligned_subsystem}", nonnegative=True) σi = sp.Symbol(f"sigma{isobar_id}", nonnegative=True) @@ -79,7 +79,7 @@ def formulate_theta_hat_angle( return symbol, -theta -def formulate_zeta_angle( +def formulate_zeta_angle( # noqa: C901, PLR0911 rotated_state: int, aligned_subsystem: int, reference_subsystem: int, @@ -158,7 +158,10 @@ def formulate_zeta_angle( (2, 3, 1), (3, 1, 2), }: - create_symbols = lambda i: sp.symbols(f"m{i} sigma{i}", nonnegative=True) + + def create_symbols(i): + return sp.symbols(f"m{i} sigma{i}", nonnegative=True) + mi, σi = create_symbols(rotated_state) mj, σj = create_symbols(aligned_subsystem) mk, σk = create_symbols(reference_subsystem) @@ -174,11 +177,9 @@ def formulate_zeta_angle( (1, 3, 1), (2, 1, 2), (3, 2, 3), - # Eq (A8) (1, 1, 2), (2, 2, 3), (3, 3, 1), - # Eq (A11) (1, 3, 2), (2, 1, 3), (3, 2, 1), @@ -187,7 +188,8 @@ def formulate_zeta_angle( rotated_state, reference_subsystem, aligned_subsystem ) return zeta_symbol, -zeta - raise NotImplementedError( + msg = ( "No expression for" f" ζ^{rotated_state}_{aligned_subsystem}({reference_subsystem})" ) + raise NotImplementedError(msg) diff --git a/src/ampform_dpd/decay.py b/src/ampform_dpd/decay.py index a26eabd5..93e17e13 100644 --- a/src/ampform_dpd/decay.py +++ b/src/ampform_dpd/decay.py @@ -2,14 +2,16 @@ from __future__ import annotations import sys -from typing import Dict +from typing import TYPE_CHECKING, Dict -import sympy as sp from attrs import field, frozen from attrs.validators import instance_of from ampform_dpd._attrs import assert_spin_value, to_ls, to_rational +if TYPE_CHECKING: + import sympy as sp + if sys.version_info < (3, 8): from typing_extensions import Literal else: @@ -48,17 +50,22 @@ def __attrs_post_init__(self) -> None: expected_final_state = set(self.final_state.values()) for i, chain in enumerate(self.chains): if chain.parent != expected_initial_state: - raise ValueError( + msg = ( f"Chain {i} has initial state {chain.parent.name}, but should have" f" {expected_initial_state.name}" ) + raise ValueError(msg) final_state = {chain.spectator, *chain.decay_products} if final_state != expected_final_state: - to_str = lambda s: ", ".join(p.name for p in s) - raise ValueError( + + def to_str(s): + return ", ".join(p.name for p in s) + + msg = ( f"Chain {i} has final state {to_str(final_state)}, but should have" f" {to_str(expected_final_state)}" ) + raise ValueError(msg) @property def initial_state(self) -> Particle: @@ -72,7 +79,8 @@ def find_chain(self, resonance_name: str) -> ThreeBodyDecayChain: for chain in self.chains: if chain.resonance.name == resonance_name: return chain - raise KeyError(f"No decay chain found for resonance {resonance_name}") + msg = f"No decay chain found for resonance {resonance_name}" + raise KeyError(msg) def get_subsystem(self, subsystem_id: Literal[1, 2, 3]) -> ThreeBodyDecay: child1_id, child2_id = get_decay_product_ids(subsystem_id) @@ -89,11 +97,12 @@ def get_subsystem(self, subsystem_id: Literal[1, 2, 3]) -> ThreeBodyDecay: def get_decay_product_ids(spectator_id: Literal[1, 2, 3]) -> tuple[int, int]: if spectator_id == 1: return 2, 3 - if spectator_id == 2: + if spectator_id == 2: # noqa: PLR2004 return 3, 1 - if spectator_id == 3: + if spectator_id == 3: # noqa: PLR2004 return 1, 2 - raise ValueError(f"Spectator ID has to be one of 1, 2, 3, not {spectator_id}") + msg = f"Spectator ID has to be one of 1, 2, 3, not {spectator_id}" + raise ValueError(msg) OuterStates = Dict[Literal[0, 1, 2, 3], Particle] @@ -106,17 +115,23 @@ class ThreeBodyDecayChain: def __attrs_post_init__(self) -> None: if not isinstance(self.decay.child1, IsobarNode): - raise TypeError(f"Child 1 has of type {IsobarNode.__name__} (the decay)") + msg = f"Child 1 has of type {IsobarNode.__name__} (the decay)" + raise TypeError(msg) if not isinstance(self.decay.child1.child1, Particle): - raise TypeError(f"Child 1 of child 1 has of type {Particle.__name__}") + msg = f"Child 1 of child 1 has of type {Particle.__name__}" + raise TypeError(msg) if not isinstance(self.decay.child1.child2, Particle): - raise TypeError(f"Child 2 of child 1 has of type {Particle.__name__}") + msg = f"Child 2 of child 1 has of type {Particle.__name__}" + raise TypeError(msg) if not isinstance(self.decay.child2, Particle): - raise TypeError(f"Child 2 has of type {Particle.__name__} (spectator)") + msg = f"Child 2 has of type {Particle.__name__} (spectator)" + raise TypeError(msg) if self.incoming_ls is None: # pyright: ignore[reportUnnecessaryComparison] - raise ValueError(f"LS-coupling for production node required") + msg = "LS-coupling for production node required" + raise ValueError(msg) if self.outgoing_ls is None: # pyright: ignore[reportUnnecessaryComparison] - raise ValueError(f"LS-coupling for decay node required") + msg = "LS-coupling for decay node required" + raise ValueError(msg) @property def parent(self) -> Particle: diff --git a/src/ampform_dpd/dynamics.py b/src/ampform_dpd/dynamics.py index a085f6c2..35c83818 100644 --- a/src/ampform_dpd/dynamics.py +++ b/src/ampform_dpd/dynamics.py @@ -106,7 +106,7 @@ def __new__(cls, s, m0, Γ0, m1, m2, γ): def evaluate(self): s, m0, Γ0, m1, m2, γ = self.args - s_A = m1**2 - m2**2 / 2 # Adler zero + s_A = m1**2 - m2**2 / 2 # Adler zero # noqa: N806 g_squared = sp.Mul( (s - s_A) / (m0**2 - s_A), m0 * Γ0 * sp.exp(-γ * s), diff --git a/src/ampform_dpd/io.py b/src/ampform_dpd/io.py index 3db25857..13593299 100644 --- a/src/ampform_dpd/io.py +++ b/src/ampform_dpd/io.py @@ -25,18 +25,23 @@ from functools import lru_cache from os.path import abspath, dirname, expanduser from textwrap import dedent -from typing import Iterable, Mapping, Sequence, overload +from typing import TYPE_CHECKING, Iterable, Mapping, Sequence, overload from warnings import warn import cloudpickle import sympy as sp from ampform.io import aslatex -from tensorwaves.function import ParametrizedBackendFunction, PositionalArgumentFunction from tensorwaves.function.sympy import create_function, create_parametrized_function -from tensorwaves.interface import Function, ParameterValue, ParametrizedFunction from ampform_dpd.decay import IsobarNode, Particle, ThreeBodyDecay, ThreeBodyDecayChain +if TYPE_CHECKING: + from tensorwaves.function import ( + ParametrizedBackendFunction, + PositionalArgumentFunction, + ) + from tensorwaves.interface import Function, ParameterValue, ParametrizedFunction + _LOGGER = logging.getLogger(__name__) @@ -62,7 +67,8 @@ def _(obj: sp.Basic, **kwargs) -> str: @aslatex.register(abc.Mapping) def _(obj: Mapping, **kwargs) -> str: if len(obj) == 0: - raise ValueError("Need at least one dictionary item") + msg = "Need at least one dictionary item" + raise ValueError(msg) latex = R"\begin{array}{rcl}" + "\n" for lhs, rhs in obj.items(): latex += Rf" {aslatex(lhs, **kwargs)} &=& {aslatex(rhs, **kwargs)} \\" + "\n" @@ -74,7 +80,8 @@ def _(obj: Mapping, **kwargs) -> str: def _(obj: Iterable, **kwargs) -> str: obj = list(obj) if len(obj) == 0: - raise ValueError("Need at least one item to render as LaTeX") + msg = "Need at least one item to render as LaTeX" + raise ValueError(msg) latex = R"\begin{array}{c}" + "\n" for item in obj: item_latex = aslatex(item, **kwargs) @@ -135,19 +142,22 @@ def as_markdown_table(obj: Sequence) -> str: return _as_decay_markdown_table(obj.chains) if item_type is ThreeBodyDecayChain: return _as_decay_markdown_table(obj) - raise NotImplementedError( + msg = ( f"Cannot render a sequence with {item_type.__name__} items as a Markdown table" ) + raise NotImplementedError(msg) def _determine_item_type(obj) -> type: if not isinstance(obj, abc.Sequence): return type(obj) if len(obj) < 1: - raise ValueError(f"Need at least one entry to render a table") + msg = "Need at least one entry to render a table" + raise ValueError(msg) item_type = type(obj[0]) - if not all(map(lambda i: isinstance(i, item_type), obj)): - raise ValueError(f"Not all items are of type {item_type.__name__}") + if not all(isinstance(i, item_type) for i in obj): + msg = f"Not all items are of type {item_type.__name__}" + raise ValueError(msg) return item_type @@ -185,7 +195,7 @@ def _as_decay_markdown_table(decay_chains: Sequence[ThreeBodyDecayChain]) -> str for chain in decay_chains: child1, child2 = map(aslatex, chain.decay_products) row_items = [ - Rf"${chain.resonance.latex} \to" Rf" {child1} {child2}$", + Rf"${chain.resonance.latex} \to {child1} {child2}$", Rf"${aslatex(chain.resonance, only_jp=True)}$", f"{int(1e3 * chain.resonance.mass):,.0f}", f"{int(1e3 * chain.resonance.width):,.0f}", @@ -203,8 +213,7 @@ def _create_markdown_table_header(column_names: list[str]): def _create_markdown_table_row(items: Iterable): - items = map(lambda i: f"{i}", items) - return "| " + " | ".join(items) + " |\n" + return "| " + " | ".join(f"{i}" for i in items) + " |\n" def perform_cached_doit( diff --git a/src/ampform_dpd/spin.py b/src/ampform_dpd/spin.py index 5797a0fa..c25258c3 100644 --- a/src/ampform_dpd/spin.py +++ b/src/ampform_dpd/spin.py @@ -10,7 +10,7 @@ def generate_ls_couplings( parent_spin: SupportsFloat, child1_spin: SupportsFloat, child2_spin: SupportsFloat, - max_L: int = 3, + max_L: int = 3, # noqa: N803 ) -> list[tuple[int, sp.Rational]]: r""" >>> generate_ls_couplings(1.5, 0.5, 0) diff --git a/tests/test_angles.py b/tests/test_angles.py index ca8eb2cc..efef4763 100644 --- a/tests/test_angles.py +++ b/tests/test_angles.py @@ -52,7 +52,7 @@ def test_formulate_theta_hat_angle(): assert formulate_theta_hat_angle(i, i)[1] == 0 -def test_formulate_zeta_angle_equation_A6(): +def test_formulate_zeta_angle_equation_A6(): # noqa: N802 """Test Eq. (A6), https://journals.aps.org/prd/pdf/10.1103/PhysRevD.101.034033#page=10.""" for i in [1, 2, 3]: for k in [1, 2, 3]: diff --git a/tests/test_io.py b/tests/test_io.py index 9e8f7b73..f11760ae 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -18,7 +18,7 @@ THIS_DIR = dirname(abspath(__file__)) # https://compwa-org--129.org.readthedocs.build/report/018.html#resonances-and-ls-scheme -dummy_args = dict(mass=0, width=0) +dummy_args = {"mass": 0, "width": 0} Λc = Particle("Λc", latex=R"\Lambda_c^+", spin=0.5, parity=+1, **dummy_args) p = Particle("p", latex="p", spin=0.5, parity=+1, **dummy_args) π = Particle("π+", latex=R"\pi^+", spin=0, parity=-1, **dummy_args)