diff --git a/.vscode/settings.json b/.vscode/settings.json index 620427bd..dfca8a18 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -37,8 +37,6 @@ "**/.tox/**": true }, "git.rebaseWhenSync": true, - "githubPullRequests.telemetry.enabled": false, - "gitlens.advanced.telemetry.enabled": false, "json.schemas": [ { "fileMatch": ["*particle*.json"], @@ -52,7 +50,6 @@ "python.analysis.autoImportCompletions": false, "python.analysis.diagnosticMode": "workspace", "python.formatting.provider": "black", - "python.languageServer": "Pylance", "python.linting.banditEnabled": false, "python.linting.enabled": true, "python.linting.flake8Enabled": true, @@ -61,9 +58,7 @@ "python.linting.pylamaEnabled": false, "python.linting.pylintCategorySeverity.refactor": "Information", "python.linting.pylintEnabled": true, - "python.linting.pylintUseMinimalCheckers": false, - "python.testing.nosetestsEnabled": false, - "python.testing.pytestArgs": ["--color=no", "--no-cov", "-vv"], + "python.testing.pytestArgs": ["--color=no", "--no-cov"], "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, "rewrap.wrappingColumn": 79, @@ -72,8 +67,7 @@ "*/.pydocstyle": true, ".constraints/*.txt": true }, - "telemetry.enableCrashReporter": false, - "telemetry.enableTelemetry": false, + "telemetry.telemetryLevel": "off", "yaml.schemas": { "./src/qrules/particle-validation.json": ["*particle*.y*ml"], "https://raw.githubusercontent.com/readthedocs/readthedocs.org/master/readthedocs/rtd_tests/fixtures/spec/v2/schema.yml": ".readthedocs.yml" diff --git a/docs/conf.py b/docs/conf.py index 16986856..59faa962 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -174,6 +174,8 @@ def fetch_logo(url: str, output_path: str) -> None: ] ), } +autodoc_member_order = "bysource" +autodoc_typehints_format = "short" codeautolink_concat_default = True AUTODOC_INSERT_SIGNATURE_LINEBREAKS = True graphviz_output_format = "svg" diff --git a/src/qrules/_implementers.py b/src/qrules/_implementers.py index 9224f7fd..12c02835 100644 --- a/src/qrules/_implementers.py +++ b/src/qrules/_implementers.py @@ -1,6 +1,6 @@ """A collection of implementation tools to can be used accross all modules.""" -from typing import TYPE_CHECKING, Any, Callable, Type, TypeVar +from typing import TYPE_CHECKING, Any, Type, TypeVar import attrs @@ -14,39 +14,32 @@ _DecoratedClass = TypeVar("_DecoratedClass") -def implement_pretty_repr() -> Callable[ - [Type[_DecoratedClass]], Type[_DecoratedClass] -]: +def implement_pretty_repr( + decorated_class: Type[_DecoratedClass], +) -> Type[_DecoratedClass]: """Implement a pretty :code:`repr` in a class decorated by `attrs`.""" - - def decorator( - decorated_class: Type[_DecoratedClass], - ) -> Type[_DecoratedClass]: - if not attrs.has(decorated_class): - raise TypeError( - "Can only implement a pretty repr for a class created with" - " attrs" - ) - - def repr_pretty(self: Any, p: "PrettyPrinter", cycle: bool) -> None: - class_name = type(self).__name__ - if cycle: - p.text(f"{class_name}(...)") - else: - with p.group(indent=2, open=f"{class_name}("): - for field in attrs.fields(type(self)): - if not field.init: - continue - value = getattr(self, field.name) - p.breakable() - p.text(f"{field.name}=") - p.pretty(value) - p.text(",") - p.breakable() - p.text(")") - - # pylint: disable=protected-access - decorated_class._repr_pretty_ = repr_pretty # type: ignore[attr-defined] - return decorated_class - - return decorator + if not attrs.has(decorated_class): + raise TypeError( + "Can only implement a pretty repr for a class created with attrs" + ) + + def repr_pretty(self: Any, p: "PrettyPrinter", cycle: bool) -> None: + class_name = type(self).__name__ + if cycle: + p.text(f"{class_name}(...)") + else: + with p.group(indent=2, open=f"{class_name}("): + for field in attrs.fields(type(self)): + if not field.init: + continue + value = getattr(self, field.name) + p.breakable() + p.text(f"{field.name}=") + p.pretty(value) + p.text(",") + p.breakable() + p.text(")") + + # pylint: disable=protected-access + decorated_class._repr_pretty_ = repr_pretty # type: ignore[attr-defined] + return decorated_class diff --git a/src/qrules/combinatorics.py b/src/qrules/combinatorics.py index 09ee0f1a..372ca900 100644 --- a/src/qrules/combinatorics.py +++ b/src/qrules/combinatorics.py @@ -37,7 +37,7 @@ StateDefinition = Union[str, StateWithSpins] -@implement_pretty_repr() +@implement_pretty_repr @frozen class InitialFacts: edge_props: Dict[int, ParticleWithSpin] = field(factory=dict) diff --git a/src/qrules/quantum_numbers.py b/src/qrules/quantum_numbers.py index 1ca570a5..e76c48f5 100644 --- a/src/qrules/quantum_numbers.py +++ b/src/qrules/quantum_numbers.py @@ -164,7 +164,7 @@ def _to_optional_int(optional_int: Optional[int]) -> Optional[int]: return int(optional_int) -@implement_pretty_repr() +@implement_pretty_repr @frozen(order=True) class InteractionProperties: """Immutable data structure containing interaction properties. diff --git a/src/qrules/solving.py b/src/qrules/solving.py index 11789ce9..9502bb51 100644 --- a/src/qrules/solving.py +++ b/src/qrules/solving.py @@ -58,7 +58,7 @@ from .topology import Topology -@implement_pretty_repr() +@implement_pretty_repr @define class EdgeSettings: """Solver settings for a specific edge of a graph.""" @@ -68,7 +68,7 @@ class EdgeSettings: qn_domains: Dict[Any, list] = field(factory=dict) -@implement_pretty_repr() +@implement_pretty_repr @define class NodeSettings: """Container class for the interaction settings. @@ -89,21 +89,21 @@ class NodeSettings: interaction_strength: float = 1.0 -@implement_pretty_repr() +@implement_pretty_repr @define class GraphSettings: edge_settings: Dict[int, EdgeSettings] = field(factory=dict) node_settings: Dict[int, NodeSettings] = field(factory=dict) -@implement_pretty_repr() +@implement_pretty_repr @define class GraphElementProperties: edge_props: Dict[int, GraphEdgePropertyMap] = field(factory=dict) node_props: Dict[int, GraphNodePropertyMap] = field(factory=dict) -@implement_pretty_repr() +@implement_pretty_repr @frozen class QNProblemSet: """Particle reaction problem set, defined as a graph like data structure. @@ -123,7 +123,7 @@ class QNProblemSet: solving_settings: GraphSettings -@implement_pretty_repr() +@implement_pretty_repr @frozen class QuantumNumberSolution: node_quantum_numbers: Dict[int, GraphNodePropertyMap] @@ -174,7 +174,7 @@ def get_name(rule: Any) -> str: return converted_dict -@implement_pretty_repr() +@implement_pretty_repr @define(on_setattr=attrs.setters.frozen) class QNResult: """Defines a result to a problem set processed by the solving code.""" diff --git a/src/qrules/topology.py b/src/qrules/topology.py index 16f409e8..b8e6b769 100644 --- a/src/qrules/topology.py +++ b/src/qrules/topology.py @@ -168,7 +168,7 @@ def _to_frozenset(iterable: Iterable[int]) -> FrozenSet[int]: return frozenset(iterable) -@implement_pretty_repr() +@implement_pretty_repr @frozen(order=True) class Topology: """Directed Feynman-like graph without edge or node properties. diff --git a/src/qrules/transition.py b/src/qrules/transition.py index 75f03346..d0f3e96c 100644 --- a/src/qrules/transition.py +++ b/src/qrules/transition.py @@ -103,7 +103,7 @@ class SolvingMode(Enum): """Find all possible solutions.""" -@implement_pretty_repr() +@implement_pretty_repr @define(on_setattr=attrs.setters.frozen) class ExecutionInfo: not_executed_node_rules: Dict[int, Set[str]] = field( @@ -180,7 +180,7 @@ def extend( ) -@implement_pretty_repr() +@implement_pretty_repr @define class ProblemSet: """Particle reaction problem set, defined as a graph like data structure. @@ -736,14 +736,14 @@ def _strip_spin(state_definition: Sequence[StateDefinition]) -> List[str]: return particle_names -@implement_pretty_repr() +@implement_pretty_repr @frozen(order=True) class State: particle: Particle = field(validator=instance_of(Particle)) spin_projection: float = field(converter=_to_float) -@implement_pretty_repr() +@implement_pretty_repr @frozen(order=True) class StateTransition: """Frozen instance of a `.StateTransitionGraph` of a particle with spin."""