Skip to content

Commit aa90974

Browse files
MAINT: upgrade lock files (#322)
* DX: use Python 3.13 in developer environment * MAINT: accommodate code for f₂(2150) * MAINT: make MyPy happy * MAINT: update test values
1 parent b760d81 commit aa90974

File tree

15 files changed

+1263
-1050
lines changed

15 files changed

+1263
-1050
lines changed

.binder/runtime.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
python-3.12
1+
python-3.13

.github/release-drafter.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ categories:
1919
- title: 📝 Documentation
2020
label: 📝 Docs
2121
- title: 🔨 Maintenance
22-
label: 🔨 Maintenance
22+
labels:
23+
- 🔨 Maintenance
24+
- ⬆️ Lock
2325
- title: 🖱️ Developer Experience
2426
label: 🖱️ DX
2527

.pre-commit-config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ repos:
1515
- id: check-useless-excludes
1616

1717
- repo: https://github.com/ComPWA/policy
18-
rev: 0.7.1
18+
rev: 0.7.3
1919
hooks:
2020
- id: check-dev-files
2121
args:
@@ -62,9 +62,9 @@ repos:
6262
metadata.vscode
6363
6464
- repo: https://github.com/astral-sh/ruff-pre-commit
65-
rev: v0.12.8
65+
rev: v0.14.0
6666
hooks:
67-
- id: ruff
67+
- id: ruff-check
6868
args: [--fix]
6969
types_or: [python, pyi, jupyter]
7070
- id: ruff-format
@@ -104,14 +104,14 @@ repos:
104104
- id: taplo-format
105105

106106
- repo: https://github.com/pappasam/toml-sort
107-
rev: v0.24.2
107+
rev: v0.24.3
108108
hooks:
109109
- id: toml-sort
110110
args:
111111
- --in-place
112112

113113
- repo: https://github.com/python-jsonschema/check-jsonschema
114-
rev: 0.33.2
114+
rev: 0.34.1
115115
hooks:
116116
- id: check-jsonschema
117117
name: Check CITATION.cff
@@ -129,7 +129,7 @@ repos:
129129
- id: cspell
130130

131131
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
132-
rev: 3.2.1
132+
rev: 3.4.0
133133
hooks:
134134
- id: editorconfig-checker
135135
name: editorconfig
@@ -150,11 +150,11 @@ repos:
150150
- python
151151

152152
- repo: https://github.com/ComPWA/pyright-pre-commit
153-
rev: v1.1.403
153+
rev: v1.1.406
154154
hooks:
155155
- id: pyright
156156

157157
- repo: https://github.com/astral-sh/uv-pre-commit
158-
rev: 0.8.8
158+
rev: 0.9.2
159159
hooks:
160160
- id: uv-lock

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.12
1+
3.13

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: 2
33
build:
44
os: ubuntu-24.04
55
tools:
6-
python: "3.12"
6+
python: "3.13"
77
commands:
88
- |-
99
export PIXI_HOME=$READTHEDOCS_VIRTUALENV_PATH

docs/usage/reaction.ipynb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,24 @@
487487
"outputs": [],
488488
"source": [
489489
"stm.set_allowed_intermediate_particles(r\"f\\([02]\\)\", regex=True)\n",
490-
"reaction = stm.find_solutions(problem_sets)\n",
491-
"assert len(reaction.get_intermediate_particles().names) == 13"
490+
"reaction = stm.find_solutions(problem_sets)"
491+
]
492+
},
493+
{
494+
"cell_type": "code",
495+
"execution_count": null,
496+
"metadata": {
497+
"jupyter": {
498+
"source_hidden": true
499+
},
500+
"tags": [
501+
"remove-cell"
502+
]
503+
},
504+
"outputs": [],
505+
"source": [
506+
"n_resonances = len(reaction.get_intermediate_particles())\n",
507+
"assert n_resonances == 14, n_resonances"
492508
]
493509
},
494510
{
@@ -604,7 +620,7 @@
604620
"name": "python",
605621
"nbconvert_exporter": "python",
606622
"pygments_lexer": "ipython3",
607-
"version": "3.9.19"
623+
"version": "3.12.11"
608624
}
609625
},
610626
"nbformat": 4,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ uv run \
358358
help = "Run all tests on a specific Python version"
359359

360360
[[tool.poe.tasks.test-py.args]]
361-
default = "3.12"
361+
default = "3.13"
362362
help = "Selected Python version"
363363
name = "version"
364364
positional = true

src/qrules/_attrs.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from __future__ import annotations
2+
3+
from fractions import Fraction
4+
from typing import SupportsFloat
5+
6+
from qrules.quantum_numbers import Parity
7+
8+
9+
def to_fraction(value: SupportsFloat) -> Fraction:
10+
float_value = float(value)
11+
if float_value == -0.0:
12+
float_value = 0.0
13+
return Fraction(float_value)
14+
15+
16+
def to_parity(value: Parity | int) -> Parity:
17+
return Parity(value)

src/qrules/conservation_rules.py

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
from attrs import define, field, frozen
5656
from attrs.converters import optional
5757

58+
from qrules._attrs import to_fraction, to_parity
5859
from qrules.quantum_numbers import EdgeQuantumNumbers as EdgeQN
5960
from qrules.quantum_numbers import NodeQuantumNumbers as NodeQN
6061
from qrules.quantum_numbers import arange
@@ -186,9 +187,9 @@ def parity_conservation(
186187

187188
@frozen
188189
class HelicityParityEdgeInput:
189-
parity: EdgeQN.parity = field(converter=EdgeQN.parity)
190-
spin_magnitude: EdgeQN.spin_magnitude = field(converter=EdgeQN.spin_magnitude)
191-
spin_projection: EdgeQN.spin_projection = field(converter=EdgeQN.spin_projection)
190+
parity: EdgeQN.parity = field(converter=to_parity)
191+
spin_magnitude: EdgeQN.spin_magnitude = field(converter=to_fraction)
192+
spin_projection: EdgeQN.spin_projection = field(converter=to_fraction)
192193

193194

194195
def parity_conservation_helicity(
@@ -229,16 +230,18 @@ def parity_conservation_helicity(
229230

230231
@frozen
231232
class CParityEdgeInput:
232-
spin_magnitude: EdgeQN.spin_magnitude = field(converter=EdgeQN.spin_magnitude)
233-
pid: EdgeQN.pid = field(converter=EdgeQN.pid)
234-
c_parity: Optional[EdgeQN.c_parity] = field(converter=EdgeQN.c_parity, default=None)
233+
spin_magnitude: EdgeQN.spin_magnitude = field(converter=to_fraction)
234+
pid: EdgeQN.pid = field(converter=int)
235+
c_parity: Optional[EdgeQN.c_parity] = field(
236+
converter=optional(to_parity), default=None
237+
)
235238

236239

237240
@frozen
238241
class CParityNodeInput:
239242
# These converters currently do not do anything, as "NewType"s do not have constructors
240-
l_magnitude: NodeQN.l_magnitude = field(converter=NodeQN.l_magnitude)
241-
s_magnitude: NodeQN.s_magnitude = field(converter=NodeQN.s_magnitude)
243+
l_magnitude: NodeQN.l_magnitude = field(converter=to_fraction)
244+
s_magnitude: NodeQN.s_magnitude = field(converter=to_fraction)
242245

243246

244247
def c_parity_conservation(
@@ -284,18 +287,18 @@ def _get_c_parity_multiparticle(
284287

285288
@frozen
286289
class GParityEdgeInput:
287-
isospin_magnitude: EdgeQN.isospin_magnitude = field(
288-
converter=EdgeQN.isospin_magnitude
290+
isospin_magnitude: EdgeQN.isospin_magnitude = field(converter=to_fraction)
291+
spin_magnitude: EdgeQN.spin_magnitude = field(converter=to_fraction)
292+
pid: EdgeQN.pid = field(converter=int)
293+
g_parity: Optional[EdgeQN.g_parity] = field(
294+
converter=optional(to_parity), default=None
289295
)
290-
spin_magnitude: EdgeQN.spin_magnitude = field(converter=EdgeQN.spin_magnitude)
291-
pid: EdgeQN.pid = field(converter=EdgeQN.pid)
292-
g_parity: Optional[EdgeQN.g_parity] = field(converter=EdgeQN.g_parity, default=None)
293296

294297

295298
@frozen
296299
class GParityNodeInput:
297-
l_magnitude: NodeQN.l_magnitude = field(converter=NodeQN.l_magnitude)
298-
s_magnitude: NodeQN.s_magnitude = field(converter=NodeQN.s_magnitude)
300+
l_magnitude: NodeQN.l_magnitude = field(converter=to_fraction)
301+
s_magnitude: NodeQN.s_magnitude = field(converter=to_fraction)
299302

300303

301304
def g_parity_conservation( # noqa: C901
@@ -375,9 +378,9 @@ def check_g_parity_isobar(
375378

376379
@frozen
377380
class IdenticalParticleSymmetryOutEdgeInput:
378-
spin_magnitude: EdgeQN.spin_magnitude = field(converter=EdgeQN.spin_magnitude)
379-
spin_projection: EdgeQN.spin_projection = field(converter=EdgeQN.spin_projection)
380-
pid: EdgeQN.pid = field(converter=EdgeQN.pid)
381+
spin_magnitude: EdgeQN.spin_magnitude = field(converter=to_fraction)
382+
spin_projection: EdgeQN.spin_projection = field(converter=to_fraction)
383+
pid: EdgeQN.pid = field(converter=int)
381384

382385

383386
def identical_particle_symmetrization(
@@ -455,16 +458,16 @@ def _is_clebsch_gordan_coefficient_zero(
455458

456459
@frozen
457460
class SpinNodeInput:
458-
l_magnitude: NodeQN.l_magnitude = field(converter=NodeQN.l_magnitude)
459-
l_projection: NodeQN.l_projection = field(converter=NodeQN.l_projection)
460-
s_magnitude: NodeQN.s_magnitude = field(converter=NodeQN.s_magnitude)
461-
s_projection: NodeQN.s_projection = field(converter=NodeQN.s_projection)
461+
l_magnitude: NodeQN.l_magnitude = field(converter=to_fraction)
462+
l_projection: NodeQN.l_projection = field(converter=to_fraction)
463+
s_magnitude: NodeQN.s_magnitude = field(converter=to_fraction)
464+
s_projection: NodeQN.s_projection = field(converter=to_fraction)
462465

463466

464467
@frozen
465468
class SpinMagnitudeNodeInput:
466-
l_magnitude: NodeQN.l_magnitude = field(converter=NodeQN.l_magnitude)
467-
s_magnitude: NodeQN.s_magnitude = field(converter=NodeQN.s_magnitude)
469+
l_magnitude: NodeQN.l_magnitude = field(converter=to_fraction)
470+
s_magnitude: NodeQN.s_magnitude = field(converter=to_fraction)
468471

469472

470473
def ls_spin_validity(spin_input: SpinNodeInput) -> bool:
@@ -585,12 +588,8 @@ def __spin_couplings(spin1: _Spin, spin2: _Spin) -> set[_Spin]:
585588

586589
@define
587590
class IsoSpinEdgeInput:
588-
isospin_magnitude: EdgeQN.isospin_magnitude = field(
589-
converter=EdgeQN.isospin_magnitude
590-
)
591-
isospin_projection: EdgeQN.isospin_projection = field(
592-
converter=EdgeQN.isospin_projection
593-
)
591+
isospin_magnitude: EdgeQN.isospin_magnitude = field(converter=to_fraction)
592+
isospin_projection: EdgeQN.isospin_projection = field(converter=to_fraction)
594593

595594

596595
def _check_spin_valid(magnitude: Fraction, projection: Fraction) -> bool:

src/qrules/particle.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
from fractions import Fraction
2020
from functools import total_ordering
2121
from math import copysign
22-
from typing import TYPE_CHECKING, Any, Callable, SupportsFloat
22+
from typing import TYPE_CHECKING, Any, Callable
2323

2424
import attrs
2525
from attrs import field, frozen
2626
from attrs.converters import optional
2727
from attrs.validators import instance_of
2828

29+
from qrules._attrs import to_fraction, to_parity
2930
from qrules.conservation_rules import GellMannNishijimaInput, gellmann_nishijima
3031
from qrules.quantum_numbers import Parity, _float_as_signed_str
3132

@@ -44,13 +45,6 @@
4445
_LOGGER = logging.getLogger(__name__)
4546

4647

47-
def _to_fraction(value: SupportsFloat) -> Fraction:
48-
float_value = float(value)
49-
if float_value == -0.0:
50-
float_value = 0.0
51-
return Fraction(float_value)
52-
53-
5448
def _validate_fraction_for_spin(
5549
instance: Spin,
5650
attribute: Attribute, # noqa: ARG001
@@ -82,11 +76,11 @@ class Spin: # noqa: PLW1641
8276
"""Safe, immutable data container for spin **with projection**."""
8377

8478
magnitude: Fraction = field(
85-
converter=_to_fraction,
79+
converter=to_fraction,
8680
validator=_validate_fraction_for_spin,
8781
)
8882
projection: Fraction = field(
89-
converter=_to_fraction,
83+
converter=to_fraction,
9084
validator=_validate_fraction_for_spin,
9185
)
9286

@@ -125,10 +119,6 @@ def _render_fraction(fraction: Fraction, plusminus: bool = False) -> str:
125119
return str(fraction)
126120

127121

128-
def _to_parity(value: Parity | int) -> Parity:
129-
return Parity(int(value))
130-
131-
132122
def _to_spin(value: Spin | tuple[Fraction, Fraction] | tuple[float, float]) -> Spin:
133123
if isinstance(value, tuple):
134124
return Spin(*value)
@@ -173,9 +163,9 @@ class Particle:
173163
electron_lepton_number: int = field(default=0, validator=instance_of(int))
174164
muon_lepton_number: int = field(default=0, validator=instance_of(int))
175165
tau_lepton_number: int = field(default=0, validator=instance_of(int))
176-
parity: Parity | None = field(converter=optional(_to_parity), default=None)
177-
c_parity: Parity | None = field(converter=optional(_to_parity), default=None)
178-
g_parity: Parity | None = field(converter=optional(_to_parity), default=None)
166+
parity: Parity | None = field(converter=optional(to_parity), default=None)
167+
c_parity: Parity | None = field(converter=optional(to_parity), default=None)
168+
g_parity: Parity | None = field(converter=optional(to_parity), default=None)
179169

180170
def __attrs_post_init__(self) -> None:
181171
if self.isospin is not None and not gellmann_nishijima(

0 commit comments

Comments
 (0)