From 34f10655657b633e4bd723f68e659a4013a5b6f0 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Tue, 16 Dec 2025 18:12:14 -0800 Subject: [PATCH 1/5] prepping for 0.2.1 - mypy enablement --- py/pyproject.toml | 5 ++++- py/src/jsonlogic/py.typed | 0 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 py/src/jsonlogic/py.typed diff --git a/py/pyproject.toml b/py/pyproject.toml index 65d507d..19a8705 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "jsonlogic-py" -version = "0.2" +version = "0.2.1" authors = [ { name="Peter Pirkelbauer"}, { name="Seth Bromberger"} ] @@ -24,7 +24,10 @@ classifiers = [ dependencies = {file = ["requirements.txt"]} optional-dependencies = {dev = {file = ["requirements-dev.txt"] }} +[tool.setuptools.package-data] +jsonlogic = ["py.typed"] [project.urls] Homepage = "https://github.com/MetallData/jsonlogic" Issues = "https://github.com/MetallData/jsonlogic/issues" + diff --git a/py/src/jsonlogic/py.typed b/py/src/jsonlogic/py.typed new file mode 100644 index 0000000..e69de29 From 75fd0c1b8687e7e044d6e9c8144342b4b540f3c7 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 18 Dec 2025 16:25:00 -0800 Subject: [PATCH 2/5] move methods and variables to underline - requires accompanying clippy PR --- py/src/jsonlogic/__init__.py | 23 +++++++++++++---------- py/src/jsonlogic/jsontypes.py | 12 ++++++------ py/test/test_classes.py | 10 ++++------ py/test/test_jsonlogic.py | 2 +- py/test/test_types.py | 14 +++++++------- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/py/src/jsonlogic/__init__.py b/py/src/jsonlogic/__init__.py index 89bc991..6e0012a 100644 --- a/py/src/jsonlogic/__init__.py +++ b/py/src/jsonlogic/__init__.py @@ -17,16 +17,16 @@ def __new__(cls, *_, **__): setattr(cls, dunder, lambda self, *x, o=op: Expression(o, self, *x)) return super().__new__(cls) - def prepare(self) -> Any: + def _prepare(self) -> Any: """prepares the structure for json by converting it into something that can be dumped""" raise NotImplementedError() - def to_json(self) -> str: + def _to_json(self) -> str: """represents the object as JSON""" - return json.dumps(self.prepare()) + return json.dumps(self._prepare()) def __str__(self): - return self.to_json() + return self._to_json() class Literal(Operand): @@ -46,8 +46,8 @@ def __repr__(self): def __str__(self): return str(self.type) - def prepare(self) -> PyJsonType: - return self.type.prepare() + def _prepare(self) -> PyJsonType: + return self.type._prepare() class Variable(Operand): @@ -59,7 +59,7 @@ def __init__(self, var: str, docstr: str | None = None): if docstr is not None: self.__doc__ = docstr - def prepare(self): + def _prepare(self): return {"var": self.var} @@ -83,10 +83,10 @@ def __init__( # add the remaining variables, casting them to Literals if they're not Variables, Expressions, or Literals. self.on = tuple(Literal(o) if not isinstance(o, Operand) else o for o in on) - def prepare(self): + def _prepare(self): return { - str(self.op): [self.o1.prepare()] - + list(x.prepare() if isinstance(x, Operand) else x for x in self.on) + str(self.op): [self.o1._prepare()] + + list(x._prepare() if isinstance(x, Operand) else x for x in self.on) } @@ -126,3 +126,6 @@ def prepare(self): # class _Any(Type, Any): # """Type representing any JSONLogic type""" + + +__all__ = ["Operation", "Operand", "Literal", "Variable", "Expression"] \ No newline at end of file diff --git a/py/src/jsonlogic/jsontypes.py b/py/src/jsonlogic/jsontypes.py index c822697..6b16271 100644 --- a/py/src/jsonlogic/jsontypes.py +++ b/py/src/jsonlogic/jsontypes.py @@ -22,7 +22,7 @@ def __init__(self, val): def __str__(self): return f"[{self.typename}]{self.val}" - def prepare(self) -> PyJsonType: + def _prepare(self) -> PyJsonType: """Prepares the type for JSON serialization""" raise NotImplementedError("class has not defined prepare()") @@ -32,7 +32,7 @@ class JsonNumber(JsonType): typename = "Number" - def prepare(self): + def _prepare(self): return int(self.val) if isinstance(self.val, int) else float(self.val) @@ -41,7 +41,7 @@ class JsonBool(JsonType): typename = "Boolean" - def prepare(self) -> bool: + def _prepare(self) -> bool: return bool(self.val) @@ -50,7 +50,7 @@ class JsonStr(JsonType): typename = "String" - def prepare(self) -> str: + def _prepare(self) -> str: return str(self.val) @@ -59,7 +59,7 @@ class JsonArray(JsonType): typename = "Array" - def prepare(self) -> list: + def _prepare(self) -> list: return list(self.val) @@ -68,7 +68,7 @@ class JsonObj(JsonType): typename = "Object" - def prepare(self) -> dict: + def _prepare(self) -> dict: return dict(self.val) diff --git a/py/test/test_classes.py b/py/test/test_classes.py index a6ddfac..85394ac 100644 --- a/py/test/test_classes.py +++ b/py/test/test_classes.py @@ -4,8 +4,6 @@ sys.path.append("src") from jsonlogic import Expression, Variable, Literal, Operand, Operation -from jsonlogic.classes import Entity -from dataclasses import dataclass @pytest.fixture @@ -40,13 +38,13 @@ def l2(): def test_expression(op1, op2, v1, v2, l1, l2): e = Expression(op1, v1) - assert e.to_json() == str(e) == '{"op1": [{"var": "var1"}]}' + assert e._to_json() == str(e) == '{"op1": [{"var": "var1"}]}' e = Expression(op2, v1, v2) - assert e.to_json() == str(e) == '{"op2": [{"var": "var1"}, {"var": "var2"}]}' + assert e._to_json() == str(e) == '{"op2": [{"var": "var1"}, {"var": "var2"}]}' e = Expression(op2, v1, l1) - assert e.to_json() == str(e) == '{"op2": [{"var": "var1"}, 5]}' + assert e._to_json() == str(e) == '{"op2": [{"var": "var1"}, 5]}' def test_operations(): @@ -63,4 +61,4 @@ def test_literals(l1, l2): def test_operand(): o = Operand() with pytest.raises(NotImplementedError): - o.prepare() + o._prepare() diff --git a/py/test/test_jsonlogic.py b/py/test/test_jsonlogic.py index 8f35d4a..eab23e1 100644 --- a/py/test/test_jsonlogic.py +++ b/py/test/test_jsonlogic.py @@ -41,7 +41,7 @@ def _s(): def assert_op(e: jl.Expression, d): - assert jsonLogic(e.prepare(), d) + assert jsonLogic(e._prepare(), d) def test_lt_gt_ne(_s, _i, _f): diff --git a/py/test/test_types.py b/py/test/test_types.py index ec39ec9..945f2ec 100644 --- a/py/test/test_types.py +++ b/py/test/test_types.py @@ -12,7 +12,7 @@ def test_bool(): assert b.val is True assert isinstance(b.val, bool) assert str(b) == "[Boolean]True" - assert b.prepare() is True + assert b._prepare() is True def test_int(): @@ -21,7 +21,7 @@ def test_int(): assert b.val == 10 assert isinstance(b.val, int) assert str(b) == "[Number]10" - assert b.prepare() == 10 + assert b._prepare() == 10 def test_float(): @@ -30,7 +30,7 @@ def test_float(): assert b.val == 10.1 assert isinstance(b.val, float) assert str(b) == "[Number]10.1" - assert b.prepare() == 10.1 + assert b._prepare() == 10.1 def test_dict(): @@ -40,7 +40,7 @@ def test_dict(): assert b.val == d assert isinstance(b.val, dict) assert str(b).startswith("[Object]") - assert b.prepare() == d + assert b._prepare() == d def test_str(): @@ -49,7 +49,7 @@ def test_str(): assert b.val == "hello" assert isinstance(b.val, str) assert str(b).startswith("[String]") - assert b.prepare() == "hello" + assert b._prepare() == "hello" def test_list(): @@ -59,7 +59,7 @@ def test_list(): assert b.val == d assert isinstance(b.val, list) assert str(b).startswith("[Array]") - assert b.prepare() == d + assert b._prepare() == d def test_deduce(): @@ -82,4 +82,4 @@ class TestType(JsonType): assert tt.typename == "UNDEFINED" assert str(tt) == "[UNDEFINED]10" with pytest.raises(NotImplementedError): - tt.prepare() + tt._prepare() From 4696cafdf2c832cafb3ae001dbbeef71b9cef3cb Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 18 Dec 2025 16:28:58 -0800 Subject: [PATCH 3/5] more --- py/src/jsonlogic/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/src/jsonlogic/__init__.py b/py/src/jsonlogic/__init__.py index 6e0012a..756df25 100644 --- a/py/src/jsonlogic/__init__.py +++ b/py/src/jsonlogic/__init__.py @@ -55,12 +55,12 @@ class Variable(Operand): def __init__(self, var: str, docstr: str | None = None): super().__init__() - self.var = var + self._var = var if docstr is not None: self.__doc__ = docstr def _prepare(self): - return {"var": self.var} + return {"var": self._var} class Expression(Operand): From c57cab314d58000b2b9c1b996af7a737718b224d Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 18 Dec 2025 18:47:02 -0800 Subject: [PATCH 4/5] removes Callables from jl_operations --- py/src/jsonlogic/operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/src/jsonlogic/operations.py b/py/src/jsonlogic/operations.py index 5234834..2f2d7ac 100644 --- a/py/src/jsonlogic/operations.py +++ b/py/src/jsonlogic/operations.py @@ -62,7 +62,7 @@ def __str__(self): # string and array concatenation _jl_cat = Operation("cat", None) -jl_operations: dict[str, Operation | Callable[..., Operation]] = { +jl_operations: dict[str, Operation] = { "__lt__": _jl_lt, "__le__": _jl_le, "__eq__": _jl_eq, From e123343d780e6f6c7a9dc4514a622967bd4c1ed1 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Fri, 19 Dec 2025 12:45:04 -0800 Subject: [PATCH 5/5] flake8->ruff --- py/.github/workflows/pr.yml | 4 ++-- py/requirements-dev.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/py/.github/workflows/pr.yml b/py/.github/workflows/pr.yml index 39719b8..417893a 100644 --- a/py/.github/workflows/pr.yml +++ b/py/.github/workflows/pr.yml @@ -20,9 +20,9 @@ jobs: if [ -f requirements.txt ]; then pip install -r requirements.txt; fi if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi - - name: Lint with flake8 + - name: Lint with ruff run: | - flake8 src/jsonlogic --count --show-source --statistics --max-line-length=120 + ruff check src/jsonlogic --output-format=concise --statistics --line-length=120 - name: MyPy diff --git a/py/requirements-dev.txt b/py/requirements-dev.txt index 3c26817..926c93b 100644 --- a/py/requirements-dev.txt +++ b/py/requirements-dev.txt @@ -1,5 +1,5 @@ pytest coverage json-logic-qubit -flake8 +ruff mypy