Skip to content

Commit 856ac75

Browse files
authored
Merge pull request #25 from Nishela/support_nested_paths_in_process_attr
feat: support for nested paths in ProcessAttr
2 parents e637fbd + 63ac07b commit 856ac75

16 files changed

+119
-40
lines changed

.pre-commit-config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ default_language_version:
33

44
repos:
55
- repo: https://github.com/pre-commit/pre-commit-hooks
6-
rev: v4.5.0
6+
rev: v5.0.0
77
hooks:
88
- id: check-added-large-files
99
- id: pretty-format-json
@@ -18,21 +18,21 @@ repos:
1818
- id: requirements-txt-fixer
1919

2020
- repo: https://github.com/astral-sh/ruff-pre-commit
21-
rev: v0.1.14
21+
rev: v0.8.0
2222
hooks:
2323
- id: ruff-format
2424
- id: ruff
2525
args: [ --fix, --unsafe-fixes ]
2626

2727
- repo: https://github.com/pycqa/flake8
28-
rev: '7.0.0'
28+
rev: '7.1.1'
2929
hooks:
3030
- id: flake8
3131
args: ["--config=pyproject.toml"]
3232
additional_dependencies: ["flake8-pyproject", "wemake-python-styleguide"]
3333

3434
- repo: https://github.com/pre-commit/mirrors-mypy
35-
rev: 'v1.8.0'
35+
rev: 'v1.13.0'
3636
hooks:
3737
- id: mypy
3838
additional_dependencies: [ "no_implicit_optional" ]

logic_processes_layer/extensions/mappers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
__all__ = ("InitMapper", "ProcessAttr")
55

66
import dataclasses
7+
from operator import attrgetter
78
import typing
89

910

@@ -17,9 +18,8 @@ class ProcessAttr:
1718
from_context: bool = dataclasses.field(default=False)
1819

1920
def get_value(self, context: typing.Any) -> typing.Any: # noqa: ANN401
20-
if self.from_context:
21-
return getattr(context, self.attr_name)
22-
return getattr(context.process, self.attr_name)
21+
source = (context.process, context)[self.from_context]
22+
return attrgetter(self.attr_name)(source)
2323

2424

2525
class InitMapper:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "logic_processes_layer"
7-
version = "1.1.3"
7+
version = "1.1.4"
88
requires-python = ">=3.8"
99
description = "Abstractions for create business logic"
1010
readme = "README.md"

ruff.toml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
1-
21
force-exclude = true
3-
ignore-init-module-imports = true
4-
select = ["ALL"]
52
line-length = 120
63
output-format = "grouped"
74
target-version = "py38"
5+
6+
[lint]
7+
select = ["ALL"]
88
fixable = ["ALL"]
99
ignore = [
10-
'ANN002', 'ANN003', 'ANN101',
10+
'ANN002', 'ANN003',
1111
'COM812',
1212
'D100', 'D101', 'D103', 'D102', 'D104', 'D105', 'D106', "D107", "D400",
1313
'D203', 'D205',
1414
"G004",
1515
'ISC001',
1616
"TD001", "TID252",
1717
]
18-
external = ["WPS221", "WPS432", "WPS529", "WPS601",]
1918

20-
[per-file-ignores]
19+
external = ["WPS221", "WPS432", "WPS529", "WPS601","WPS428"]
20+
21+
[lint.per-file-ignores]
2122
"__init__.py" = ["F401", "F403"]
2223
"tests/test_*.py" = ["S101", "S311"]
2324

24-
[flake8-annotations]
25+
[lint.flake8-annotations]
2526
mypy-init-return = true
2627
ignore-fully-untyped = true
2728
allow-star-arg-any = true
2829

29-
[pydocstyle]
30+
[lint.pydocstyle]
3031
convention = "pep257"
3132

32-
[isort]
33+
[lint.isort]
3334
force-single-line = false
3435
force-wrap-aliases = true
3536
force-sort-within-sections = true

tests/examples/processors/mylty_process.py renamed to tests/examples/processors/multy_process.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from logic_processes_layer.extensions import InitMapper, ProcessAsSubprocess, ProcessAttr
77
from logic_processes_layer.processors.base import ResultsT
88

9-
from ..sub_processors import SympleSubprocessor
9+
from ..sub_processors import SimpleSubprocessor
1010

1111

1212
class CompositionContext(BaseProcessorContext["ProcessComposition"]):
@@ -38,7 +38,7 @@ class ProcessComposition(BaseProcessor[CompositionContext, ResultsT]):
3838
context_cls = CompositionContext
3939

4040
pre_run = (
41-
SympleSubprocessor(),
41+
SimpleSubprocessor(),
4242
SubProc(
4343
process_cls=ProcessWithInitalData,
4444
init_mapper=InitMapper(1, 2),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from __future__ import annotations
2+
3+
import dataclasses
4+
from typing import TYPE_CHECKING
5+
6+
from logic_processes_layer import BaseProcessor
7+
from logic_processes_layer.extensions import InitMapper, ProcessAttr
8+
9+
from .multy_process import ProcessWithInitalData, SubProc
10+
11+
12+
if TYPE_CHECKING:
13+
from ..protocols.supports_get_attribute import SupportsGetAttribute
14+
15+
16+
@dataclasses.dataclass
17+
class ProcessWithNestedAttributes(BaseProcessor):
18+
attr: SupportsGetAttribute
19+
20+
post_run = (
21+
SubProc(
22+
process_cls=ProcessWithInitalData,
23+
init_mapper=InitMapper(
24+
some_attr_one=ProcessAttr("attr.some_attr_one"),
25+
some_attr_two=ProcessAttr("attr.some_attr_two"),
26+
),
27+
),
28+
)
29+
30+
def run(self):
31+
return self.attr.some_attr_one + self.attr.some_attr_two
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from __future__ import annotations
22

33

4-
__all__ = ("SympleProcessor",)
4+
__all__ = ("SimpleProcessor",)
55

66
from logic_processes_layer import BaseProcessor
77

88

9-
class SympleProcessor(BaseProcessor):
9+
class SimpleProcessor(BaseProcessor):
1010
def run(self):
1111
return self.__class__.__name__

tests/examples/protocols/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .supports_get_attribute import *
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from __future__ import annotations
2+
3+
4+
__all__ = ("SupportsGetAttribute",)
5+
6+
import typing
7+
8+
9+
class SupportsGetAttribute(typing.Protocol):
10+
some_attr_one: int
11+
some_attr_two: int
12+
13+
def __getattribute__(self, name: str) -> typing.Any: # noqa: ANN401
14+
... # noqa: WPS428
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from __future__ import annotations
22

3-
from .symple import *
3+
from .simple import *

tests/examples/sub_processors/symple.py renamed to tests/examples/sub_processors/simple.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
from logic_processes_layer import BaseSubprocessor
44

55

6-
__all__ = ("SympleSubprocessor",)
6+
__all__ = ("SimpleSubprocessor",)
77

88

9-
class SympleSubprocessor(BaseSubprocessor):
9+
class SimpleSubprocessor(BaseSubprocessor):
1010
def __call__(self):
1111
return self.__class__.__name__

tests/test_process_composition.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22

33
import random
44

5-
from tests.examples.processors.mylty_process import ProcessComposition
5+
from tests.examples.processors.multy_process import ProcessComposition
66

77

88
class TestProcessComposition:
99
def setup_method(self):
1010
self.start_data = (random.randint(1, 10), random.randint(1, 10))
1111
self.process: ProcessComposition = ProcessComposition(*self.start_data)
1212
self.expected_result = {
13-
"pre_run": ("SympleSubprocessor", 3, sum(self.start_data)),
13+
"pre_run": ("SimpleSubprocessor", 3, sum(self.start_data)),
1414
"post_run": (333, 333),
1515
}
1616

1717
def check_state(self, state_name):
1818
proc_state_instances = getattr(self.process, state_name)
1919
for idx, state_instance in enumerate(proc_state_instances):
20-
assert state_instance.call_result == self.expected_result[state_name][idx], (state_name, idx)
20+
assert state_instance.call_result == self.expected_result[state_name][idx]
2121

2222
def test_process_composition(self):
2323
self.process()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from __future__ import annotations
2+
3+
import dataclasses
4+
import random
5+
6+
from .examples.processors.process_with_nested_attrs import ProcessWithNestedAttributes
7+
8+
9+
@dataclasses.dataclass
10+
class TestData:
11+
some_attr_one: int = dataclasses.field(default_factory=lambda: random.randint(1, 100))
12+
some_attr_two: int = dataclasses.field(default_factory=lambda: random.randint(1, 100))
13+
14+
15+
class TestProcessWithNestedAttributes:
16+
def setup_method(self):
17+
self.start_data = TestData()
18+
self.process: ProcessWithNestedAttributes = ProcessWithNestedAttributes(self.start_data)
19+
self.expected_result = {
20+
"post_run": (self.start_data.some_attr_one, self.start_data.some_attr_two),
21+
}
22+
23+
def check_state(self, state_name):
24+
proc_state_instances = getattr(self.process, state_name)
25+
for idx, state_instance in enumerate(proc_state_instances):
26+
assert state_instance.call_result == sum(self.expected_result[state_name]), (state_name, idx)
27+
28+
def test_process_composition(self):
29+
self.process()
30+
31+
for state_name in self.expected_result:
32+
self.check_state(state_name)

tests/test_processor_with_subprocessors.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
from __future__ import annotations
22

3-
from tests.examples.processors.symple import SympleProcessor
4-
from tests.examples.sub_processors import SympleSubprocessor
3+
from tests.examples.processors.simple import SimpleProcessor
4+
from tests.examples.sub_processors import SimpleSubprocessor
55

66

7-
def make_symple_subprocessor(cls_name):
8-
return type(cls_name, (SympleSubprocessor,), {})
7+
def make_simple_subprocessor(cls_name):
8+
return type(cls_name, (SimpleSubprocessor,), {})
99

1010

11-
class ProcessorWithSubprocess(SympleProcessor):
12-
pre_run = tuple(make_symple_subprocessor(f"Subprocessor{idx}")() for idx in range(2)) # noqa: WPS221
13-
post_run = tuple(make_symple_subprocessor(f"Subprocessor{idx}")() for idx in range(2, 5)) # noqa: WPS221
11+
class ProcessorWithSubprocess(SimpleProcessor):
12+
pre_run = tuple(make_simple_subprocessor(f"Subprocessor{idx}")() for idx in range(2)) # noqa: WPS221
13+
post_run = tuple(make_simple_subprocessor(f"Subprocessor{idx}")() for idx in range(2, 5)) # noqa: WPS221
1414

1515

1616
class TestProcessorWithSubprocess:

tests/test_symple_processor.py renamed to tests/test_simple_processor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from __future__ import annotations
22

3-
from tests.examples.processors.symple import SympleProcessor
3+
from tests.examples.processors.simple import SimpleProcessor
44

55

6-
class TestSympleProcessor:
6+
class TestSimpleProcessor:
77
def setup_method(self):
8-
self.processor = SympleProcessor()
8+
self.processor = SimpleProcessor()
99

1010
def test_run(self):
1111
assert self.processor.run() == self.processor.__class__.__name__

tests/test_sub_processor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
from logic_processes_layer import BaseProcessor, BaseProcessorContext
66

7-
from .examples.sub_processors import SympleSubprocessor
7+
from .examples.sub_processors import SimpleSubprocessor
88

99

10-
class TestSympleSubprocessor:
10+
class TestSimpleSubprocessor:
1111
def setup_method(self):
1212
self.context = BaseProcessorContext(process=Mock(spec=BaseProcessor))
13-
self.subprocessor = SympleSubprocessor()
13+
self.subprocessor = SimpleSubprocessor()
1414
self.subprocessor.context = self.context
1515

1616
def test_call(self):

0 commit comments

Comments
 (0)