Repository: s-knibbs/dataclasses-jsonschema
Pull request #113 (2019-10-19 09:40:02)

Raise error if dataclass inheritance & additional_properties=False both used
See  issue #111 


Patch:
diff --git a/dataclasses_jsonschema/__init__.py b/dataclasses_jsonschema/__init__.py
index 994d50b..cd9f81f 100644
--- a/dataclasses_jsonschema/__init__.py
+++ b/dataclasses_jsonschema/__init__.py
@@ -231,6 +231,8 @@ class JsonSchemaMixin:
                 klass for klass in cls.__bases__ if is_dataclass(klass) and issubclass(klass, JsonSchemaMixin)
             ]
             if len(dataclass_bases) > 0:
+                if not allow_additional_props:
+                    raise TypeError("Dataclass inheritance and additional_props_false=False not currently supported")
                 base_discriminators = [
                     base._discriminator() for base in dataclass_bases if base._discriminator() is not None
                 ]
@@ -325,15 +327,15 @@ class JsonSchemaMixin:
             dataclass_bases = [
                 klass for klass in cls.__bases__ if is_dataclass(klass) and issubclass(klass, JsonSchemaMixin)
             ]
-            base_field_names = set()
+            base_fields_types = set()
             for base in dataclass_bases:
-                base_field_names |= {f.name for f in fields(base)}
+                base_fields_types |= {(f.name, f.type) for f in fields(base)}
 
             mapped_fields = []
             type_hints = get_type_hints(cls)
             for f in fields(cls):
                 # Skip internal fields
-                if f.name.startswith("__") or (not base_fields and f.name in base_field_names):
+                if f.name.startswith("__") or (not base_fields and (f.name, f.type) in base_fields_types):
                     continue
                 # Note fields() doesn't resolve forward refs
                 f.type = type_hints[f.name]


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
index 4919d13..0473651 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -848,6 +848,49 @@ def test_property_serialisation_all_properties():
     assert Rectangle.json_schema() == expected_schema
 
 
+def test_inherited_field_narrowing():
+    @dataclass
+    class BaseObject(JsonSchemaMixin):
+        """Base"""
+        other: float
+        field: str
+
+    @dataclass
+    class NarrowedObject(BaseObject, JsonSchemaMixin):
+        """Narrowed"""
+        field: Literal['staticstr']
+
+    expected_schema = compose_schema({
+      "allOf": [
+        {
+          "$ref": "#/definitions/BaseObject"
+        },
+        {
+          "type": "object",
+          "required": ["field"],
+          "properties": {
+            "field": {"enum": ["staticstr"]}
+          }
+        }
+      ],
+      "description": "Narrowed",
+      "$schema": "http://json-schema.org/draft-06/schema#",
+      "definitions": {
+        "BaseObject": {
+          "type": "object",
+          "required": ["other", "field"],
+          "properties": {
+            "field": {"type": "string"},
+            "other": {"type": "number"}
+          },
+          "description": "Base"
+        }
+      }
+    })
+
+    assert NarrowedObject.json_schema() == expected_schema
+
+
 def test_unrecognized_enum_value():
     class PetType(Enum):
         CAT = "cat"
@@ -860,3 +903,16 @@ def test_unrecognized_enum_value():
 
     p = Pet.from_dict({'name': 'snakey', 'type': 'python'}, validate_enums=False)
     assert p.type == "python"
+
+
+def test_inheritance_and_additional_properties_disallowed():
+    @dataclass
+    class Pet(JsonSchemaMixin):
+        name: str
+
+    # Currently this should raise an error until https://github.com/s-knibbs/dataclasses-jsonschema/issues/111
+    # is implemented
+    with pytest.raises(TypeError):
+        @dataclass
+        class Cat(Pet, allow_additional_props=False):
+            hunting_skill: str