diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 47bea3b..c5e7167 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,11 @@ CHANGELOG ========= +0.18.0 +=============== + +* SumType variants are attribute-strict #48 + 0.16.0 - 0.17.0 =============== diff --git a/docs/conf.py b/docs/conf.py index 06c051b..7214dab 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.17' +version = '0.18' # The full version, including alpha/beta/rc tags. -release = '0.17.0' +release = '0.18.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index e9a1483..bbd6826 100644 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ def requirements(at_path: Path): # ---------------------------- setup(name='typeit', - version='0.17.0', + version='0.18.0', description='typeit brings typed data into your project', long_description=README, classifiers=[ diff --git a/tests/test_sums.py b/tests/test_sums.py index 8983f90..34bbfa3 100644 --- a/tests/test_sums.py +++ b/tests/test_sums.py @@ -1,4 +1,4 @@ -from typing import Dict +from typing import Dict, NamedTuple import pytest import pickle @@ -148,4 +148,26 @@ class VariantB: 'b': True, } x = mk_x(data) - assert serialize_x(x) == data \ No newline at end of file + assert serialize_x(x) == data + + +def test_sumtype_attr_strictness(): + class Versioning(SumType): + class V1: + a: int + + class V2: + a: int + b: int + + class X(NamedTuple): + payload: Versioning + + mk_x, serialize_x = ( + typeit.type_constructor & typeit.flags.SUM_TYPE_DICT('_version_') ^ X + ) + + with pytest.raises(typeit.Error): + x = mk_x({'payload': {'_version_': 'v1', 'a': 1, 'b': 1}}) + + x = mk_x({'payload': {'_version_': 'v2', 'a': 1, 'b': 1}}) diff --git a/typeit/parser.py b/typeit/parser.py index 8b87437..58768b4 100644 --- a/typeit/parser.py +++ b/typeit/parser.py @@ -175,6 +175,7 @@ def _maybe_node_for_sum_type( overrides, memo ) + node.typ.unknown = 'raise' variant_nodes.append((variant, node)) sum_node = schema.nodes.SchemaNode( schema.types.Sum( diff --git a/typeit/utils.py b/typeit/utils.py index 78f4fd6..5b5758c 100644 --- a/typeit/utils.py +++ b/typeit/utils.py @@ -23,9 +23,12 @@ def is_named_tuple(typ: Type[Any]) -> bool: def clone_schema_node(node): """ Clonning the node and reassigning the same children, because clonning is recursive, but we are only interested - in new version of the outermost schema node, the children nodes + in a new version of the outermost schema node, the children nodes should be shared to avoid unnecessary duplicates. """ new_node = node.clone() - new_node.children = node.children - return new_node \ No newline at end of file + # a list comprehension to place the same nodes into + # a new wrapping list object, so that extending + # the cloned node with new children doesn't affect the original node + new_node.children = [x for x in node.children] + return new_node