From 5744094ecab6e25a548fc1b3404e3ec0722921af Mon Sep 17 00:00:00 2001 From: Shane Curtin Date: Mon, 24 Jan 2022 15:48:17 +0000 Subject: [PATCH] Adding the ability to set a 'required' boolean kwarg in the Object.add_object method - Doing so will avoid the `required` keyword for an object in the schema to be included - Added test cases - Updated docs --- AUTHORS.rst | 1 + README.rst | 5 +++-- genson/schema/builder.py | 4 ++-- genson/schema/node.py | 4 ++-- genson/schema/strategies/array.py | 4 ++-- genson/schema/strategies/base.py | 2 +- genson/schema/strategies/object.py | 11 ++++++---- genson/schema/strategies/scalar.py | 2 +- test/base.py | 4 ++-- test/test_builder.py | 33 ++++++++++++++++++++++++++++++ 10 files changed, 54 insertions(+), 16 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index b32ade8..ebe8683 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -12,3 +12,4 @@ Contributors - `Heiho1 `_ - `YehudaCorsia `_ - `KOLANICH `_ +- `Shane Curtin `_ diff --git a/README.rst b/README.rst index b380ef1..f7b20f6 100644 --- a/README.rst +++ b/README.rst @@ -153,12 +153,13 @@ Merge in a JSON schema. This can be a ``dict`` or another ``SchemaBuilder`` obje There is no schema validation. If you pass in a bad schema, you might get back a bad schema. -``add_object(obj)`` -^^^^^^^^^^^^^^^^^^^ +``add_object(obj, **kwargs)`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Modify the schema to accommodate an object. :param obj: any object or scalar that can be serialized in JSON +:param \**required (bool): if set to `False` the required keyword in the schema will not be included ``to_schema()`` ^^^^^^^^^^^^^^^ diff --git a/genson/schema/builder.py b/genson/schema/builder.py index 4b7007c..3f3ae78 100644 --- a/genson/schema/builder.py +++ b/genson/schema/builder.py @@ -83,13 +83,13 @@ def add_schema(self, schema): del schema['$schema'] self._root_node.add_schema(schema) - def add_object(self, obj): + def add_object(self, obj, **kwargs): """ Modify the schema to accommodate an object. :param obj: any object or scalar that can be serialized in JSON """ - self._root_node.add_object(obj) + self._root_node.add_object(obj, **kwargs) def to_schema(self): """ diff --git a/genson/schema/node.py b/genson/schema/node.py index 9333978..e5cd90f 100644 --- a/genson/schema/node.py +++ b/genson/schema/node.py @@ -36,7 +36,7 @@ def add_schema(self, schema): # return self for easy method chaining return self - def add_object(self, obj): + def add_object(self, obj, **kwargs): """ Modify the schema to accommodate an object. @@ -47,7 +47,7 @@ def add_object(self, obj): # delegate to SchemaType object active_strategy = self._get_strategy_for_object(obj) - active_strategy.add_object(obj) + active_strategy.add_object(obj, **kwargs) # return self for easy method chaining return self diff --git a/genson/schema/strategies/array.py b/genson/schema/strategies/array.py index 9b4af37..d0ccae6 100644 --- a/genson/schema/strategies/array.py +++ b/genson/schema/strategies/array.py @@ -38,9 +38,9 @@ def add_schema(self, schema): if 'items' in schema: self._items.add_schema(schema['items']) - def add_object(self, obj): + def add_object(self, obj, **kwargs): for item in obj: - self._items.add_object(item) + self._items.add_object(item, **kwargs) def items_to_schema(self): return self._items.to_schema() diff --git a/genson/schema/strategies/base.py b/genson/schema/strategies/base.py index acadb42..9edab93 100644 --- a/genson/schema/strategies/base.py +++ b/genson/schema/strategies/base.py @@ -43,7 +43,7 @@ def _add_extra_keywords(self, schema): 'values ({1!r} vs. {2!r}). Using {1!r}').format( keyword, self._extra_keywords[keyword], value)) - def add_object(self, obj): + def add_object(self, obj, **kwargs): pass def to_schema(self): diff --git a/genson/schema/strategies/object.py b/genson/schema/strategies/object.py index c159ed0..317469d 100644 --- a/genson/schema/strategies/object.py +++ b/genson/schema/strategies/object.py @@ -46,7 +46,7 @@ def add_schema(self, schema): else: self._required &= required - def add_object(self, obj): + def add_object(self, obj, **kwargs): properties = set() for prop, subobj in obj.items(): pattern = None @@ -55,12 +55,15 @@ def add_object(self, obj): pattern = self._matching_pattern(prop) if pattern is not None: - self._pattern_properties[pattern].add_object(subobj) + self._pattern_properties[pattern].add_object(subobj, **kwargs) else: properties.add(prop) - self._properties[prop].add_object(subobj) + self._properties[prop].add_object(subobj, **kwargs) - if self._required is None: + # If 'required' is set to False they will not be added to the schema + if kwargs.get("required") is False: + self._required = set() + elif self._required is None: self._required = properties else: self._required &= properties diff --git a/genson/schema/strategies/scalar.py b/genson/schema/strategies/scalar.py index 67d6edf..a24c11c 100644 --- a/genson/schema/strategies/scalar.py +++ b/genson/schema/strategies/scalar.py @@ -68,7 +68,7 @@ def add_schema(self, schema): if schema.get('type') == 'number': self._type = 'number' - def add_object(self, obj): + def add_object(self, obj, **kwargs): if isinstance(obj, float): self._type = 'number' diff --git a/test/base.py b/test/base.py index 34f8d15..4e7c12a 100644 --- a/test/base.py +++ b/test/base.py @@ -16,8 +16,8 @@ def setUp(self): def set_schema_options(self, **options): self.builder = SchemaNode(**options) - def add_object(self, obj): - self.builder.add_object(obj) + def add_object(self, obj, **kwargs): + self.builder.add_object(obj, **kwargs) self._objects.append(obj) def add_schema(self, schema): diff --git a/test/test_builder.py b/test/test_builder.py index 4bbb3f2..a0283b0 100644 --- a/test/test_builder.py +++ b/test/test_builder.py @@ -28,6 +28,39 @@ def test_add_object(self): "$schema": SchemaBuilder.DEFAULT_URI, "type": "null"}) + def test_add_object_required_false(self): + mock_dict = { + "mock_value_one": "abc" + } + self.add_object(mock_dict, required=False) + + self.assertResult({ + "$schema": SchemaBuilder.DEFAULT_URI, + "type": "object", + "properties": { + "mock_value_one": { + "type": "string" + } + } + }) + + def test_add_object_required_true(self): + mock_dict = { + "mock_value_one": "abc" + } + self.add_object(mock_dict, required=True) + + self.assertResult({ + "$schema": SchemaBuilder.DEFAULT_URI, + "type": "object", + "properties": { + "mock_value_one": { + "type": "string" + } + }, + "required": ["mock_value_one"] + }) + def test_to_json(self): self.assertEqual( self.builder.to_json(),