diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9d67d41..4a4bedb 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -3,9 +3,9 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review] paths-ignore: - - '**/*.md' - - '**/*.png' - - '**/*.json' + - "**/*.md" + - "**/*.png" + - "**/*.json" jobs: test: @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.9, 3.11] + python-version: [3.9, 3.12] poetry-version: [1.4.2] os: [ubuntu-latest] runs-on: ${{ matrix.os }} @@ -63,4 +63,4 @@ jobs: - name: Install dependencies run: make init - name: Run style checks - run: make check-formatting \ No newline at end of file + run: make check-formatting diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f54d81b..bfb8c08 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.11] + python-version: [3.12] poetry-version: [1.4.2] os: [ubuntu-latest] runs-on: ${{ matrix.os }} @@ -27,4 +27,4 @@ jobs: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} run: | poetry config pypi-token.pypi $PYPI_TOKEN - poetry publish --build \ No newline at end of file + poetry publish --build diff --git a/examples/cpf_digit.py b/examples/cpf_digit.py index e33b513..3a68653 100644 --- a/examples/cpf_digit.py +++ b/examples/cpf_digit.py @@ -1,4 +1,4 @@ -""" Example of rule to get the eighth digit of a CPF.""" +"""Example of rule to get the eighth digit of a CPF.""" import retrack import pandas as pd diff --git a/pyproject.toml b/pyproject.toml index 7dee8b7..a80f015 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "retrack" -version = "2.9.0" +version = "2.10.0" description = "A business rules engine" authors = ["Gabriel Guarisa "] license = "MIT" @@ -11,16 +11,16 @@ keywords = ["rules", "models", "business", "node", "graph"] [tool.poetry.dependencies] python = ">=3.9,<4.0.0" -pandas = "^1.2.0" -numpy = "^1.19.5" -pydantic = "2.4.2" -networkx = "^2.6.3" -pandera = "^0.17.2" +pandas = ">=1.2.0,~2" +numpy = ">=1.19.5,<2" +pydantic = "~2" +networkx = "~3" +pandera = "~0.20" [tool.poetry.dev-dependencies] pytest = "*" pytest-cov = "*" -ruff = "^0.1.2" +ruff = "*" pytest-mock = "*" [tool.pytest.ini_options] diff --git a/retrack/engine/request_manager.py b/retrack/engine/request_manager.py index 39570dc..9cc0064 100644 --- a/retrack/engine/request_manager.py +++ b/retrack/engine/request_manager.py @@ -102,7 +102,9 @@ def __create_model( default=Ellipsis if input_field.data.default is None else input_field.data.default, - optional=input_field.data.default is not None, + json_schema_extra={ + "optional": input_field.data.default is not None + }, validate_default=False, ), ) diff --git a/retrack/nodes/base.py b/retrack/nodes/base.py index e53ed23..5977c39 100644 --- a/retrack/nodes/base.py +++ b/retrack/nodes/base.py @@ -81,12 +81,12 @@ class InputConnectionModel(pydantic.BaseModel): class BaseNode(pydantic.BaseModel): id: CastedToStringType name: str - inputs: typing.Optional[ - typing.Dict[CastedToStringType, InputConnectionModel] - ] = None - outputs: typing.Optional[ - typing.Dict[CastedToStringType, OutputConnectionModel] - ] = None + inputs: typing.Optional[typing.Dict[CastedToStringType, InputConnectionModel]] = ( + None + ) + outputs: typing.Optional[typing.Dict[CastedToStringType, OutputConnectionModel]] = ( + None + ) def run(self, **kwargs) -> typing.Dict[str, typing.Any]: return {} diff --git a/retrack/nodes/dynamic/flow.py b/retrack/nodes/dynamic/flow.py index 1fd9448..6032234 100644 --- a/retrack/nodes/dynamic/flow.py +++ b/retrack/nodes/dynamic/flow.py @@ -76,7 +76,7 @@ def run(self, **kwargs) -> typing.Dict[str, typing.Any]: def generate_input_nodes(self): input_nodes = [] - for component in rule_instance.components_registry.data.values(): + for component in rule_instance.components_registry.memory.values(): input_nodes.extend(component.generate_input_nodes()) return input_nodes diff --git a/retrack/utils/graph.py b/retrack/utils/graph.py index e15fa0a..416ac50 100644 --- a/retrack/utils/graph.py +++ b/retrack/utils/graph.py @@ -69,7 +69,7 @@ def validate_data(data: dict) -> dict: def validate_with_validators( graph_data: dict, edges: dict, validator_registry: Registry ): - for validator_name, validator in validator_registry.data.items(): + for validator_name, validator in validator_registry.memory.items(): if not validator.validate(graph_data=graph_data, edges=edges): raise ValueError(f"Invalid graph data: {validator_name}") diff --git a/retrack/utils/registry.py b/retrack/utils/registry.py index 4455c25..24233f1 100644 --- a/retrack/utils/registry.py +++ b/retrack/utils/registry.py @@ -1,5 +1,4 @@ import typing -import warnings class Registry: @@ -33,15 +32,6 @@ def get(self, key: str, default: typing.Any = None) -> typing.Any: return self._memory.get(key, default) - @property - def data(self) -> typing.Dict[str, typing.Any]: - """Return the registry memory.""" - warnings.warn( - "The 'data' property is deprecated, use 'memory' instead.", - DeprecationWarning, - ) - return self._memory - @property def keys(self) -> typing.List[str]: """Return the registry keys.""" diff --git a/tests/test_engine/test_conditional_connector_rule.py b/tests/test_engine/test_conditional_connector_rule.py index 7981854..a68daaf 100644 --- a/tests/test_engine/test_conditional_connector_rule.py +++ b/tests/test_engine/test_conditional_connector_rule.py @@ -6,7 +6,11 @@ import pandas as pd import pytest -VALUES = {"qtd_sinistros_rcf": 1, "qtd_sinistros_indefinido": 10, "is_defendant_and_court_type": False} +VALUES = { + "qtd_sinistros_rcf": 1, + "qtd_sinistros_indefinido": 10, + "is_defendant_and_court_type": False, +} def bureau_connector_factory( @@ -24,11 +28,13 @@ def run( raise ValueError( f"Missing input {in_node_key} in BureauConnector node" ) - + if node_inputs[in_node_key].empty: return {"output_value": None} - parsed_inputs[self.data.headers[i]] = node_inputs[in_node_key].to_list()[0] + parsed_inputs[self.data.headers[i]] = node_inputs[ + in_node_key + ].to_list()[0] return {"output_value": VALUES[self.data.resource]} @@ -68,4 +74,4 @@ def test_bureau_connector_factory( result = rule_executor.execute(df, raise_raw_exception=True) assert result["output"].to_list()[0] == expected_result - assert result["message"].to_list()[0] == expected_message \ No newline at end of file + assert result["message"].to_list()[0] == expected_message diff --git a/tests/test_registry.py b/tests/test_registry.py index 8a6e9c0..108be45 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -5,35 +5,35 @@ def test_create_registry(): registry = Registry() - assert registry.data == {} + assert registry.memory == {} def test_register_model(): registry = Registry() - registry.register("test", str) - assert registry.data == {"test": str} + registry.register("test", "example") + assert registry.memory == {"test": "example"} def test_get_model(): registry = Registry() - registry.register("test", str) - assert registry.get("test") == str + registry.register("test", "example") + assert registry.get("test") == "example" def test_get_model_not_found(): registry = Registry() - registry.register("test", str) + registry.register("test", "example") assert registry.get("test2") is None def test_contains_model(): registry = Registry() - registry.register("test", str) + registry.register("test", "example") assert "test" in registry def test_model_already_registered(): registry = Registry() - registry.register("test", str) + registry.register("test", "example") with pytest.raises(ValueError): - registry.register("test", str) + registry.register("test", "example")