Skip to content

Commit

Permalink
refactor: remove implement_pretty_repr() layer (#154)
Browse files Browse the repository at this point in the history
* ci: remove outdated VSCode settings
* ci: run pytest non-verbose in VSCode (verbose is a bit slower)
* ci: switch to VSCode telemetry.telemetryLevel settings
* docs: abbreviate type hints with autodoc_typehints_format
* docs: sort API by position in the source code
  • Loading branch information
redeboer authored Feb 21, 2022
1 parent c743249 commit 6ff2a37
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 58 deletions.
10 changes: 2 additions & 8 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
"**/.tox/**": true
},
"git.rebaseWhenSync": true,
"githubPullRequests.telemetry.enabled": false,
"gitlens.advanced.telemetry.enabled": false,
"json.schemas": [
{
"fileMatch": ["*particle*.json"],
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
65 changes: 29 additions & 36 deletions src/qrules/_implementers.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
2 changes: 1 addition & 1 deletion src/qrules/combinatorics.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/qrules/quantum_numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
14 changes: 7 additions & 7 deletions src/qrules/solving.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -123,7 +123,7 @@ class QNProblemSet:
solving_settings: GraphSettings


@implement_pretty_repr()
@implement_pretty_repr
@frozen
class QuantumNumberSolution:
node_quantum_numbers: Dict[int, GraphNodePropertyMap]
Expand Down Expand Up @@ -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."""
Expand Down
2 changes: 1 addition & 1 deletion src/qrules/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions src/qrules/transition.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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."""
Expand Down

0 comments on commit 6ff2a37

Please sign in to comment.