diff --git a/.gitpod.yml b/.gitpod.yml index f74de0a4..abc3e5cc 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -23,7 +23,6 @@ vscode: - github.vscode-github-actions - github.vscode-pull-request-github - joaompinto.vscode-graphviz - - ms-python.black-formatter - ms-python.mypy-type-checker - ms-python.python - ms-python.vscode-pylance diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bb362378..4ff44cb0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: metadata.vscode - repo: https://github.com/ComPWA/policy - rev: 0.2.4 + rev: 0.2.5 hooks: - id: check-dev-files args: @@ -58,6 +58,15 @@ repos: - --additional-packages=IPython - --extras-require=doc,viz + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.1 + hooks: + - id: ruff + args: [--fix] + types_or: [python, pyi, jupyter] + - id: ruff-format + types_or: [python, pyi, jupyter] + - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: @@ -81,19 +90,6 @@ repos: args: ["--django"] - id: trailing-whitespace - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.1.1 - hooks: - - id: black - - id: black-jupyter - args: [--line-length=85] - types_or: [jupyter] - - - repo: https://github.com/asottile/blacken-docs - rev: 1.16.0 - hooks: - - id: blacken-docs - - repo: https://github.com/pre-commit/mirrors-prettier rev: v4.0.0-alpha.8 hooks: @@ -154,10 +150,3 @@ repos: rev: v1.1.350 hooks: - id: pyright - - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.1 - hooks: - - id: ruff - args: [--fix] - types_or: [python, pyi, jupyter] diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 2e319018..a021dd4e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -9,7 +9,6 @@ "github.vscode-github-actions", "github.vscode-pull-request-github", "joaompinto.vscode-graphviz", - "ms-python.black-formatter", "ms-python.mypy-type-checker", "ms-python.python", "ms-python.vscode-pylance", @@ -27,6 +26,7 @@ "bungcip.better-toml", "davidanson.vscode-markdownlint", "garaioag.garaio-vscode-unwanted-recommendations", + "ms-python.black-formatter", "ms-python.flake8", "ms-python.isort", "ms-python.pylint", diff --git a/.vscode/settings.json b/.vscode/settings.json index c807f0c8..5610dec3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,13 +19,12 @@ "editor.codeActionsOnSave": { "source.organizeImports": "explicit" }, - "editor.defaultFormatter": "ms-python.black-formatter", + "editor.defaultFormatter": "charliermarsh.ruff", "editor.rulers": [88] }, "[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "black-formatter.importStrategy": "fromEnvironment", "coverage-gutters.coverageFileNames": ["coverage.xml"], "coverage-gutters.coverageReportFileName": "**/htmlcov/index.html", "coverage-gutters.showGutterCoverage": false, diff --git a/README.md b/README.md index 8c583494..09e719ff 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/deeee5b9e2bb4b3daa655942c71e17da)](https://www.codacy.com/gh/ComPWA/qrules) [![Spelling checked](https://img.shields.io/badge/cspell-checked-brightgreen.svg)](https://github.com/streetsidesoftware/cspell/tree/master/packages/cspell) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) QRules is a Python package for **validating and generating particle reactions** using diff --git a/docs/usage/particle.ipynb b/docs/usage/particle.ipynb index 14a62c42..4cb16ace 100644 --- a/docs/usage/particle.ipynb +++ b/docs/usage/particle.ipynb @@ -205,10 +205,8 @@ "source": [ "from IPython.display import Math\n", "\n", - "sigmas = particle_db.filter(\n", - " lambda p: p.name.startswith(\"Sigma\") and p.charmness == 1\n", - ")\n", - "Math(\", \".join([p.latex for p in sigmas]))" + "sigmas = particle_db.filter(lambda p: p.name.startswith(\"Sigma\") and p.charmness == 1)\n", + "Math(\", \".join(p.latex for p in sigmas))" ] }, { diff --git a/pyproject.toml b/pyproject.toml index 4428f4e1..36579625 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,32 +8,6 @@ requires = [ [tool.setuptools_scm] write_to = "src/qrules/version.py" -[tool.black] -exclude = ''' -/( - .*\.egg-info - | .*build - | \.eggs - | \.git - | \.pytest_cache - | \.tox - | \.venv - | \.vscode - | dist -)/ -''' -include = '\.pyi?$' -preview = true -target-version = [ - "py310", - "py311", - "py312", - "py36", - "py37", - "py38", - "py39", -] - [tool.coverage.run] branch = true source = ["src"] @@ -150,7 +124,11 @@ filterwarnings = [ "ignore:unclosed .*:ResourceWarning", ] markers = ["slow: marks tests as slow (deselect with '-m \"not slow\"')"] -norecursedirs = ["_build"] +norecursedirs = [ + ".ipynb_checkpoints", + ".virtual_documents", + "_build", +] testpaths = [ "docs", "src", @@ -168,6 +146,10 @@ src = [ ] target-version = "py37" +[tool.ruff.format] +docstring-code-format = true +line-ending = "lf" + [tool.ruff.lint] extend-select = [ "A", @@ -211,6 +193,7 @@ ignore = [ "D407", "D416", "E501", + "ISC001", "PLR0913", "PLR2004", "PLR5501", diff --git a/setup.cfg b/setup.cfg index f9b8914b..c531ccc2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -87,23 +87,21 @@ test = pytest-cov pytest-profiling pytest-xdist -format = - black -mypy = - mypy >=0.730 # attrs and error code support +types = + ipython + pydot <2 # problem with pydot.graph_from_dot_data + pytest sphinx-api-relink >=0.0.4; python_version >="3.7.0" sphobjinv types-PyYAML types-setuptools -lint = - %(mypy)s - ruff; python_version >="3.7.0" sty = - %(format)s - %(lint)s - %(test)s # for pytest type hints + %(types)s + mypy >=0.730 # attrs and error code support pre-commit >=1.4.0 + ruff; python_version >="3.7.0" jupyter = + black ipywidgets isort jupyterlab diff --git a/src/qrules/io/_dot.py b/src/qrules/io/_dot.py index 1bdc448b..bf3ebaef 100644 --- a/src/qrules/io/_dot.py +++ b/src/qrules/io/_dot.py @@ -58,10 +58,12 @@ class GraphPrinter: converter=_create_default_figure_style, default=None ) edge_style: Dict[str, Any] = field( - converter=default_if_none(factory=dict), default=None # type: ignore[misc] + converter=default_if_none(factory=dict), # type: ignore[misc] + default=None, ) node_style: Dict[str, Any] = field( - converter=default_if_none(factory=dict), default=None # type: ignore[misc] + converter=default_if_none(factory=dict), # type: ignore[misc] + default=None, ) indent: int = 4 diff --git a/src/qrules/settings.py b/src/qrules/settings.py index 05cc64f8..3873cbc4 100644 --- a/src/qrules/settings.py +++ b/src/qrules/settings.py @@ -211,9 +211,10 @@ def create_interaction_settings( # noqa: PLR0917 ) strong_node_settings = deepcopy(em_node_settings) - strong_node_settings.conservation_rules.update( - {isospin_conservation, g_parity_conservation} - ) + strong_node_settings.conservation_rules.update({ + isospin_conservation, + g_parity_conservation, + }) strong_node_settings.interaction_strength = 60 strong_edge_settings = deepcopy(em_edge_settings) diff --git a/src/qrules/solving.py b/src/qrules/solving.py index 00835a0b..d2c3438d 100644 --- a/src/qrules/solving.py +++ b/src/qrules/solving.py @@ -515,7 +515,7 @@ def find_solutions(self, problem_set: QNProblemSet) -> QNResult: # noqa: C901 validate_full_solution( QNProblemSet( initial_facts=MutableTransition( - topology, states, interactions # type: ignore[arg-type] + topology, states, interactions ), solving_settings=MutableTransition( topology, @@ -810,9 +810,7 @@ def rule_passes(self) -> Dict[Tuple[int, Rule], int]: _QNType = TypeVar("_QNType", EdgeQuantumNumber, NodeQuantumNumber) -class _GraphElementConstraint( - Generic[_QNType], Constraint # pyright: ignore[reportUntypedBaseClass] -): +class _GraphElementConstraint(Generic[_QNType], Constraint): """Wrapper class of the python-constraint Constraint class. This allows a customized definition of conservation rules, and hence a cleaner user diff --git a/src/qrules/topology.py b/src/qrules/topology.py index 2fad0463..b8f9797b 100644 --- a/src/qrules/topology.py +++ b/src/qrules/topology.py @@ -661,10 +661,12 @@ def _extend_graph( # remove all combinations that originate from the same nodes for comb1, comb2 in itertools.combinations(combis, 2): if get_originating_node_list( - topology, comb1 # type: ignore[arg-type] + topology, # type: ignore[arg-type] + comb1, ) == get_originating_node_list( - topology, comb2 # type: ignore[arg-type] - ): # type: ignore[arg-type] + topology, # type: ignore[arg-type] + comb2, + ): combis.remove(comb2) for combi in combis: @@ -725,8 +727,8 @@ def create_n_body_topology( Example: >>> topology = create_n_body_topology( - ... number_of_initial_states=2, - ... number_of_final_states=5, + ... number_of_initial_states=2, + ... number_of_final_states=5, ... ) >>> topology Topology(nodes=..., edges...) @@ -739,14 +741,12 @@ def create_n_body_topology( """ n_in = number_of_initial_states n_out = number_of_final_states - builder = SimpleStateTransitionTopologyBuilder( - [ - InteractionNode( - number_of_ingoing_edges=n_in, - number_of_outgoing_edges=n_out, - ) - ] - ) + builder = SimpleStateTransitionTopologyBuilder([ + InteractionNode( + number_of_ingoing_edges=n_in, + number_of_outgoing_edges=n_out, + ) + ]) topologies = builder.build( number_of_initial_edges=n_in, number_of_final_edges=n_out, diff --git a/src/qrules/transition.py b/src/qrules/transition.py index 4f0d161c..e6cf30d3 100644 --- a/src/qrules/transition.py +++ b/src/qrules/transition.py @@ -204,9 +204,7 @@ def to_qn_problem_set(self) -> QNProblemSet: for k, v in self.initial_facts.states.items() } return QNProblemSet( - initial_facts=MutableTransition( - self.topology, states, interactions # type: ignore[arg-type] - ), + initial_facts=MutableTransition(self.topology, states, interactions), solving_settings=self.solving_settings, ) @@ -242,7 +240,9 @@ def __init__( # noqa: C901, PLR0912, PLR0917 final_state: Sequence[StateDefinition], particle_db: Optional[ParticleCollection] = None, allowed_intermediate_particles: Optional[List[str]] = None, - interaction_type_settings: Optional[Dict[InteractionType, Tuple[EdgeSettings, NodeSettings]]] = None, # type: ignore[assignment] + interaction_type_settings: Optional[ + Dict[InteractionType, Tuple[EdgeSettings, NodeSettings]] + ] = None, formalism: str = "helicity", topology_building: str = "isobar", solving_mode: SolvingMode = SolvingMode.FAST, diff --git a/tests/channels/test_nbody_reactions.py b/tests/channels/test_nbody_reactions.py index 186a1178..501324c1 100644 --- a/tests/channels/test_nbody_reactions.py +++ b/tests/channels/test_nbody_reactions.py @@ -32,11 +32,13 @@ def reduce_violated_rules( ), ( (["eta"], ["pi+", "pi-"]), - {( - "c_parity_conservation", - "parity_conservation", - "spin_magnitude_conservation", - )}, + { + ( + "c_parity_conservation", + "parity_conservation", + "spin_magnitude_conservation", + ) + }, ), ( (["Sigma0"], ["Lambda", "pi0"]), diff --git a/tests/unit/test_particle.py b/tests/unit/test_particle.py index 60e3bcdf..5f81df77 100644 --- a/tests/unit/test_particle.py +++ b/tests/unit/test_particle.py @@ -62,7 +62,8 @@ def test_exceptions(self): with pytest.raises(FrozenInstanceError): test_state.charge = 1 # type: ignore[misc] with pytest.raises( - ValueError, match=r"Fails Gell-Mann–Nishijima" # noqa: RUF001 + ValueError, + match=r"Fails Gell-Mann–Nishijima", # noqa: RUF001 ): Particle( name="Fails Gell-Mann–Nishijima formula", # noqa: RUF001