From 9e1763c35af055b0a0f1b4546e5495cc27420bb7 Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Date: Tue, 8 Apr 2025 00:18:24 -0300 Subject: [PATCH] Implements Int, Float, String Validators --- jambo/{types => parser}/__init__.py | 0 jambo/{types => parser}/_type_parser.py | 0 jambo/{types => parser}/array_type_parser.py | 2 +- .../{types => parser}/boolean_type_parser.py | 2 +- jambo/parser/float_type_parser.py | 12 +++++ jambo/parser/int_type_parser.py | 12 +++++ jambo/{types => parser}/object_type_parser.py | 2 +- jambo/parser/string_type_parser.py | 21 ++++++++ jambo/schema_converter.py | 4 +- jambo/types/float_type_parser.py | 11 ---- jambo/types/int_type_parser.py | 24 --------- jambo/types/string_type_parser.py | 11 ---- jambo/utils/__init__.py | 0 jambo/utils/properties_builder/__init__.py | 0 .../numeric_properties_builder.py | 14 +++++ jambo/utils/types/__init__.py | 0 tests/test_type_parser.py | 52 ++++++++++++++++--- 17 files changed, 110 insertions(+), 57 deletions(-) rename jambo/{types => parser}/__init__.py (100%) rename jambo/{types => parser}/_type_parser.py (100%) rename jambo/{types => parser}/array_type_parser.py (87%) rename jambo/{types => parser}/boolean_type_parser.py (77%) create mode 100644 jambo/parser/float_type_parser.py create mode 100644 jambo/parser/int_type_parser.py rename jambo/{types => parser}/object_type_parser.py (84%) create mode 100644 jambo/parser/string_type_parser.py delete mode 100644 jambo/types/float_type_parser.py delete mode 100644 jambo/types/int_type_parser.py delete mode 100644 jambo/types/string_type_parser.py create mode 100644 jambo/utils/__init__.py create mode 100644 jambo/utils/properties_builder/__init__.py create mode 100644 jambo/utils/properties_builder/numeric_properties_builder.py create mode 100644 jambo/utils/types/__init__.py diff --git a/jambo/types/__init__.py b/jambo/parser/__init__.py similarity index 100% rename from jambo/types/__init__.py rename to jambo/parser/__init__.py diff --git a/jambo/types/_type_parser.py b/jambo/parser/_type_parser.py similarity index 100% rename from jambo/types/_type_parser.py rename to jambo/parser/_type_parser.py diff --git a/jambo/types/array_type_parser.py b/jambo/parser/array_type_parser.py similarity index 87% rename from jambo/types/array_type_parser.py rename to jambo/parser/array_type_parser.py index 328a6d4..52fec64 100644 --- a/jambo/types/array_type_parser.py +++ b/jambo/parser/array_type_parser.py @@ -1,4 +1,4 @@ -from jambo.types._type_parser import GenericTypeParser +from jambo.parser._type_parser import GenericTypeParser from typing import TypeVar diff --git a/jambo/types/boolean_type_parser.py b/jambo/parser/boolean_type_parser.py similarity index 77% rename from jambo/types/boolean_type_parser.py rename to jambo/parser/boolean_type_parser.py index 2af98fb..198154f 100644 --- a/jambo/types/boolean_type_parser.py +++ b/jambo/parser/boolean_type_parser.py @@ -1,4 +1,4 @@ -from jambo.types._type_parser import GenericTypeParser +from jambo.parser._type_parser import GenericTypeParser class BooleanTypeParser(GenericTypeParser): diff --git a/jambo/parser/float_type_parser.py b/jambo/parser/float_type_parser.py new file mode 100644 index 0000000..c303ff7 --- /dev/null +++ b/jambo/parser/float_type_parser.py @@ -0,0 +1,12 @@ +from jambo.parser._type_parser import GenericTypeParser +from jambo.utils.properties_builder.numeric_properties_builder import numeric_properties_builder + + +class FloatTypeParser(GenericTypeParser): + mapped_type = float + + json_schema_type = "number" + + @staticmethod + def from_properties(name, properties): + return float, numeric_properties_builder(properties) diff --git a/jambo/parser/int_type_parser.py b/jambo/parser/int_type_parser.py new file mode 100644 index 0000000..365e346 --- /dev/null +++ b/jambo/parser/int_type_parser.py @@ -0,0 +1,12 @@ +from jambo.parser._type_parser import GenericTypeParser +from jambo.utils.properties_builder.numeric_properties_builder import numeric_properties_builder + + +class IntTypeParser(GenericTypeParser): + mapped_type = int + + json_schema_type = "integer" + + @staticmethod + def from_properties(name, properties): + return int, numeric_properties_builder(properties) diff --git a/jambo/types/object_type_parser.py b/jambo/parser/object_type_parser.py similarity index 84% rename from jambo/types/object_type_parser.py rename to jambo/parser/object_type_parser.py index b63de81..6fd0c16 100644 --- a/jambo/types/object_type_parser.py +++ b/jambo/parser/object_type_parser.py @@ -1,4 +1,4 @@ -from jambo.types._type_parser import GenericTypeParser +from jambo.parser._type_parser import GenericTypeParser class ObjectTypeParser(GenericTypeParser): diff --git a/jambo/parser/string_type_parser.py b/jambo/parser/string_type_parser.py new file mode 100644 index 0000000..ee088de --- /dev/null +++ b/jambo/parser/string_type_parser.py @@ -0,0 +1,21 @@ +from jambo.parser._type_parser import GenericTypeParser + + +class StringTypeParser(GenericTypeParser): + mapped_type = str + + json_schema_type = "string" + + @staticmethod + def from_properties(name, properties): + _mappings = { + "maxLength": "max_length", + "minLength": "min_length", + "pattern": "pattern", + } + + return str, { + _mappings[key]: value + for key, value in properties.items() + if key in _mappings + } diff --git a/jambo/schema_converter.py b/jambo/schema_converter.py index e69d1b8..196fc8f 100644 --- a/jambo/schema_converter.py +++ b/jambo/schema_converter.py @@ -1,4 +1,4 @@ -from jambo.types import GenericTypeParser +from jambo.parser import GenericTypeParser from jsonschema.exceptions import SchemaError from jsonschema.protocols import Validator @@ -78,7 +78,7 @@ class SchemaConverter: @staticmethod def _build_field( name, properties: dict, required_keys: list[str] - ) -> tuple[type, Field]: + ) -> tuple[type, dict]: _field_type, _field_args = GenericTypeParser.get_impl( properties["type"] ).from_properties(name, properties) diff --git a/jambo/types/float_type_parser.py b/jambo/types/float_type_parser.py deleted file mode 100644 index f10f3e3..0000000 --- a/jambo/types/float_type_parser.py +++ /dev/null @@ -1,11 +0,0 @@ -from jambo.types._type_parser import GenericTypeParser - - -class FloatTypeParser(GenericTypeParser): - mapped_type = float - - json_schema_type = "number" - - @staticmethod - def from_properties(name, properties): - return float, {} diff --git a/jambo/types/int_type_parser.py b/jambo/types/int_type_parser.py deleted file mode 100644 index 4fa9778..0000000 --- a/jambo/types/int_type_parser.py +++ /dev/null @@ -1,24 +0,0 @@ -from dataclasses import Field - -from jambo.types._type_parser import GenericTypeParser - - -class IntTypeParser(GenericTypeParser): - mapped_type = int - - json_schema_type = "integer" - - @staticmethod - def from_properties(name, properties): - _field_properties = dict() - - if "minimum" in properties: - _field_properties["ge"] = properties["minimum"] - - if "maximum" in properties: - _field_properties["le"] = properties["maximum"] - - if "multipleOf" in properties: - _field_properties["multiple_of"] = properties["multipleOf"] - - return int, Field(**_field_properties) diff --git a/jambo/types/string_type_parser.py b/jambo/types/string_type_parser.py deleted file mode 100644 index d846eed..0000000 --- a/jambo/types/string_type_parser.py +++ /dev/null @@ -1,11 +0,0 @@ -from jambo.types._type_parser import GenericTypeParser - - -class StringTypeParser(GenericTypeParser): - mapped_type = str - - json_schema_type = "string" - - @staticmethod - def from_properties(name, properties): - return str, {} diff --git a/jambo/utils/__init__.py b/jambo/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jambo/utils/properties_builder/__init__.py b/jambo/utils/properties_builder/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jambo/utils/properties_builder/numeric_properties_builder.py b/jambo/utils/properties_builder/numeric_properties_builder.py new file mode 100644 index 0000000..fd5b0cf --- /dev/null +++ b/jambo/utils/properties_builder/numeric_properties_builder.py @@ -0,0 +1,14 @@ +def numeric_properties_builder(properties): + _mappings = { + "minimum": "ge", + "exclusiveMinimum": "gt", + "maximum": "le", + "exclusiveMaximum": "lt", + "multipleOf": "multiple_of", + } + + return { + _mappings[key]: value + for key, value in properties.items() + if key in _mappings + } \ No newline at end of file diff --git a/jambo/utils/types/__init__.py b/jambo/utils/types/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_type_parser.py b/tests/test_type_parser.py index c96c629..1ac8d3e 100644 --- a/tests/test_type_parser.py +++ b/tests/test_type_parser.py @@ -1,4 +1,4 @@ -from jambo.types import ( +from jambo.parser import ( ArrayTypeParser, FloatTypeParser, GenericTypeParser, @@ -22,21 +22,61 @@ class TestTypeParser(unittest.TestCase): def test_int_parser(self): parser = IntTypeParser() - type_parsing, type_validator = parser.from_properties("placeholder", {}) + type_parsing, type_validator = parser.from_properties( + "placeholder", { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": 1, + "maximum": 10, + "exclusiveMaximum": 11, + "multipleOf": 2, + } + ) self.assertEqual(type_parsing, int) + self.assertEqual(type_validator["ge"], 0) + self.assertEqual(type_validator["gt"], 1) + self.assertEqual(type_validator["le"], 10) + self.assertEqual(type_validator["lt"], 11) + self.assertEqual(type_validator["multiple_of"], 2) def test_float_parser(self): parser = FloatTypeParser() - expected_definition = (float, {}) - self.assertEqual(parser.from_properties("placeholder", {}), expected_definition) + type_parsing, type_validator = parser.from_properties( + "placeholder", { + "type": "number", + "minimum": 0, + "exclusiveMinimum": 1, + "maximum": 10, + "exclusiveMaximum": 11, + "multipleOf": 2, + } + ) + + self.assertEqual(type_parsing, float) + self.assertEqual(type_validator["ge"], 0) + self.assertEqual(type_validator["gt"], 1) + self.assertEqual(type_validator["le"], 10) + self.assertEqual(type_validator["lt"], 11) + self.assertEqual(type_validator["multiple_of"], 2) def test_string_parser(self): parser = StringTypeParser() - expected_definition = (str, {}) - self.assertEqual(parser.from_properties("placeholder", {}), expected_definition) + type_parsing, type_validator = parser.from_properties( + "placeholder", { + "type": "string", + "maxLength": 10, + "minLength": 1, + "pattern": "[a-zA-Z0-9]", + } + ) + + self.assertEqual(type_parsing, str) + self.assertEqual(type_validator["max_length"], 10) + self.assertEqual(type_validator["min_length"], 1) + self.assertEqual(type_validator["pattern"], "[a-zA-Z0-9]") def test_object_parser(self): parser = ObjectTypeParser()