diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8bd369..2eaff7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,9 @@ on: jobs: doc: uses: ComPWA/actions/.github/workflows/ci-docs.yml@v1 + permissions: + pages: write + id-token: write with: gh-pages: true specific-pip-packages: ${{ inputs.specific-pip-packages }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 81408a6..0fd7d24 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.179 + rev: 0.0.192 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 @@ -56,7 +57,7 @@ repos: - id: black - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: 2.7.1 + rev: 2.7.2 hooks: - id: editorconfig-checker name: editorconfig @@ -66,11 +67,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: @@ -78,6 +74,7 @@ repos: args: - --extra-keys - | + cell.attachments cell.metadata.code_folding cell.metadata.id cell.metadata.user_expressions @@ -95,22 +92,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.305 + rev: v1.1.316 hooks: - id: pyright - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 + rev: v3.9.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 5a21a52..be4c9f8 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", @@ -15,5 +17,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 162eff7..9740e18 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,8 +31,12 @@ "github-actions.workflows.pinned.workflows": [".github/workflows/ci.yml"], "livePreview.defaultPreviewPath": "docs/_build/html", "python.analysis.autoImportCompletions": false, - "python.analysis.diagnosticMode": "workspace", "python.formatting.provider": "black", "python.linting.enabled": true, - "rewrap.wrappingColumn": 88 + "python.linting.flake8Enabled": false, + "python.linting.pydocstyleEnabled": false, + "python.linting.pylintEnabled": false, + "rewrap.wrappingColumn": 88, + "ruff.enable": true, + "ruff.organizeImports": true } diff --git a/README.md b/README.md index b4638bd..422ca9d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ # ComPWA benchmark scripts [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) diff --git a/docs/conf.py b/docs/conf.py index 293ae71..398ce10 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,6 +6,7 @@ from __future__ import annotations +import contextlib import os import re @@ -15,7 +16,7 @@ project = "ComPWA benchmarks" PACKAGE = "benchmarks" REPO_NAME = "benchmarks" -copyright = "2022, ComPWA" +copyright = "2022, ComPWA" # noqa: A001 author = "Common Partial Wave Analysis" @@ -30,13 +31,11 @@ def get_branch_name() -> 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 diff --git a/docs/visualize-jax-benchmark.ipynb b/docs/visualize-jax-benchmark.ipynb index f2a777d..1a9ac7d 100644 --- a/docs/visualize-jax-benchmark.ipynb +++ b/docs/visualize-jax-benchmark.ipynb @@ -50,7 +50,7 @@ " filename: str,\n", ") -> tuple[np.ndarray, dict[str, np.ndarray]]:\n", " with open(filename) as f:\n", - " imported_data = yaml.load(f, Loader=yaml.FullLoader)\n", + " imported_data = yaml.safe_load(f)\n", " x_values = np.array(sorted(imported_data))\n", " y_values = defaultdict(list)\n", " for x in x_values:\n", @@ -156,7 +156,7 @@ "\n", " selector = np.full(X.shape, True)\n", " if max_x is not None:\n", - " selector = X <= max_x\n", + " selector = max_x >= X\n", " ax1.errorbar(\n", " X[selector],\n", " y_values[\"parametrized, run 1\"].mean(axis=1)[selector],\n", diff --git a/pyproject.toml b/pyproject.toml index 8a5ccfd..61b16ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,25 +16,25 @@ include = '\.pyi?$' preview = true target-version = [ "py310", + "py311", "py37", "py38", "py39", ] -[tool.isort] -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=C408", + "--extend-ignore=C90", + "--extend-ignore=D", + "--extend-ignore=N806", + "--extend-ignore=N816", + "--extend-ignore=PLR09", + "--extend-ignore=PLR2004", + "--extend-ignore=PLW0602", + "--extend-ignore=PLW0603", "--line-length=85", ] @@ -66,3 +66,86 @@ testpaths = [ "src", "tests", ] + +[tool.pyright] +reportGeneralTypeIssues = false +reportImportCycles = false +reportMissingParameterType = false +reportMissingTypeArgument = false +reportMissingTypeStubs = false +reportPrivateImportUsage = false +reportUnknownArgumentType = false +reportUnknownLambdaType = false +reportUnknownMemberType = false +reportUnknownParameterType = false +reportUnknownVariableType = false +reportUnnecessaryIsInstance = false +reportUnusedClass = true +reportUnusedFunction = true +reportUnusedImport = true +reportUnusedVariable = true +typeCheckingMode = "strict" + +[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 = [ + "D101", + "D102", + "D103", + "D105", + "D107", + "D203", + "D213", + "D407", + "D416", + "E501", + "SIM108", +] +show-fixes = true +target-version = "py37" +task-tags = ["cspell"] + +[tool.ruff.per-file-ignores] +"docs/*" = [ + "E402", + "INP001", + "S101", + "S113", + "T201", +] +"scripts/*" = ["INP001"] +"setup.py" = ["D100"] + +[tool.ruff.pydocstyle] +convention = "google" diff --git a/pyrightconfig.json b/pyrightconfig.json deleted file mode 100644 index 540a6bd..0000000 --- a/pyrightconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "reportGeneralTypeIssues": false, - "reportImportCycles": false, - "reportMissingParameterType": false, - "reportMissingTypeArgument": false, - "reportMissingTypeStubs": false, - "reportPrivateImportUsage": false, - "reportUnknownArgumentType": false, - "reportUnknownLambdaType": false, - "reportUnknownMemberType": false, - "reportUnknownParameterType": false, - "reportUnknownVariableType": false, - "reportUnnecessaryIsInstance": false, - "reportUnusedClass": true, - "reportUnusedFunction": true, - "reportUnusedImport": true, - "reportUnusedVariable": true, - "typeCheckingMode": "strict" -} diff --git a/scripts/execute_jax_benchmark.py b/scripts/execute_jax_benchmark.py index 912472c..897026e 100644 --- a/scripts/execute_jax_benchmark.py +++ b/scripts/execute_jax_benchmark.py @@ -1,4 +1,4 @@ -# cspell:disable +"""Execute JAX over a combination of physical cores.""" from __future__ import annotations import logging @@ -7,23 +7,25 @@ from functools import partial from os.path import dirname from time import time -from typing import TypeVar +from typing import TYPE_CHECKING, TypeVar import attrs import jax import polarization.lhcb import yaml -from polarization.amplitude import AmplitudeModel from polarization.data import create_data_transformer, generate_phasespace_sample from polarization.io import mute_jax_warnings, perform_cached_doit from polarization.lhcb import load_model_builder, load_model_parameters from polarization.lhcb.particle import load_particles from tensorwaves.function import ParametrizedBackendFunction, PositionalArgumentFunction from tensorwaves.function.sympy import create_function, create_parametrized_function -from tensorwaves.interface import DataSample, Function from tqdm.auto import tqdm from yaml.representer import Representer +if TYPE_CHECKING: + from polarization.amplitude import AmplitudeModel + from tensorwaves.interface import DataSample, Function + THIS_DIRECTORY = dirname(__file__) DATA_DIRECTORY = dirname(polarization.lhcb.__file__) logging.basicConfig( @@ -78,8 +80,7 @@ def main() -> int: logging.warning(f"Benchmark for {n:,} events already exists") progress_bar.update(NUMBER_OF_RUNS) continue - else: - t[n] = defaultdict(list) + t[n] = defaultdict(list) warmup_sample = generate_sample(model, n, seed=123456) run_sample = generate_sample(model, n, seed=0) for _ in range(NUMBER_OF_RUNS): @@ -143,8 +144,7 @@ def generate_sample( LOGGER.setLevel(logging.ERROR) phsp_sample = generate_phasespace_sample(model.decay, n_events, seed) LOGGER.setLevel(original_log_level) - phsp_sample = transformer(phsp_sample) - return phsp_sample + return transformer(phsp_sample) T = TypeVar("T", ParametrizedBackendFunction, PositionalArgumentFunction) @@ -174,7 +174,7 @@ def benchmark(func: Function, sample: DataSample) -> float: def load_benchmark(filename: str) -> dict[str, dict[str, list[float]]]: with open(filename) as f: - return yaml.load(f, Loader=yaml.FullLoader) + return yaml.safe_load(f) def write_benchmark(times: dict[str, dict[str, list[float]]], filename: str) -> None: diff --git a/scripts/visualize_jax_benchmark.py b/scripts/visualize_jax_benchmark.py index dcecc27..4fa7f32 100644 --- a/scripts/visualize_jax_benchmark.py +++ b/scripts/visualize_jax_benchmark.py @@ -1,4 +1,4 @@ -# cspell:disable +"""Visualize benchmark results from :file:`execute_jax_benchmark.py`.""" from __future__ import annotations import logging @@ -66,8 +66,9 @@ def plot( if logy: ax.set_yscale("log") - plot(ax1, "parametrized, compilation", "parametrized", x_selector=x <= 1e6) - plot(ax1, "substituted, compilation", "substituted", x_selector=x <= 1e6) + max_x = 1e6 + plot(ax1, "parametrized, compilation", "parametrized", x_selector=x <= max_x) + plot(ax1, "substituted, compilation", "substituted", x_selector=x <= max_x) plot(ax2, "parametrized, run 1, same shape", "parametrized", logy=True) plot(ax2, "substituted, run 1, same shape", "substituted", logy=True) axes.flatten()[-1].legend() @@ -80,7 +81,7 @@ def plot( def load_benchmark(filename: str) -> dict[str, dict[str, list[float]]]: with open(filename) as f: - return yaml.load(f, Loader=yaml.FullLoader) + return yaml.safe_load(f) if "__main__" in __name__: diff --git a/setup.cfg b/setup.cfg index 9c4df89..8589581 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,6 +16,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 Topic :: Scientific/Engineering Topic :: Scientific/Engineering :: Physics Typing :: Typed @@ -41,15 +42,16 @@ doc = sphinx-copybutton sphinx-togglebutton jupyter = - aquirdturtle-collapsible-headings jupyterlab >=3.0 jupyterlab-code-formatter jupyterlab-myst; python_version >="3.7.0" format = black - isort +lint = + ruff sty = %(format)s + %(lint)s pre-commit >=1.4.0 dev = %(doc)s