Skip to content

Commit

Permalink
Support builtins parsing #24
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim Avanov committed Jul 1, 2019
1 parent 52b83aa commit 6d6d7b4
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
38 changes: 38 additions & 0 deletions tests/parser/test_parser.py
Expand Up @@ -365,6 +365,44 @@ class X(NamedTuple):
assert x.d == x.h


def test_parse_sequence():
class X(NamedTuple):
x: int
y: Dict[str, Any]

XS = Sequence[X]

data = [{'x': 1, 'y': {}}]
mk_xs, dict_xs = p.type_constructor(XS)
z = mk_xs(data)
assert z[0].x == 1
assert dict_xs(z) == data

# Sequences with primitives
XS = Sequence[int]

data = [1, 2, 3]
mk_xs, serialize_xs = p.type_constructor(XS)

z = mk_xs(data)
assert z[0] == 1
assert serialize_xs(z) == data


@pytest.mark.parametrize('typ, data', (
(int, 1),
(bool, True),
(str, '1'),
(Dict[str, Any], {'x': 1, 'y': True, 'z': '1'})
))
def test_parse_builtins(typ, data):
mk_x, serialize_x = p.type_constructor(typ)

z = mk_x(data)
assert z == data
assert serialize_x(z) == data


def test_schema_node():
x = schema.nodes.SchemaNode(schema.primitives.Int())
assert x.__repr__().startswith('SchemaNode(<typeit.schema.primitives.Int ')
Expand Down
25 changes: 13 additions & 12 deletions typeit/parser.py
Expand Up @@ -185,6 +185,9 @@ def _maybe_node_for_literal(
return None





def _maybe_node_for_list(
typ: Type[iface.IType],
overrides: OverridesT,
Expand Down Expand Up @@ -316,16 +319,13 @@ def _maybe_node_for_dict(
return None


def _node_for_type(
def _maybe_node_for_user_type(
typ: Type[iface.IType],
overrides: OverridesT
) -> Optional[schema.nodes.SchemaNode]:
""" Generates a Colander schema for the given `typ` that is capable
of both constructing (deserializing) and serializing the `typ`.
"""
if type(typ) is not type:
return None

if is_named_tuple(typ):
deserialize_overrides = pmap({
overrides[getattr(typ, x)]: x
Expand Down Expand Up @@ -382,7 +382,7 @@ def _maybe_node_for_overridden(
return None


PARSING_ORDER = [ _maybe_node_for_overridden
PARSING_ORDER = [_maybe_node_for_overridden
, _maybe_node_for_primitive
, _maybe_node_for_type_var
, _maybe_node_for_union
Expand All @@ -393,10 +393,10 @@ def _maybe_node_for_overridden(
, _maybe_node_for_literal
, _maybe_node_for_sum_type
, _maybe_node_for_subclass_based
# at this point it could be a user-defined type,
# so the parser may do another recursive iteration
# through the same plan
, _node_for_type ]
# at this point it could be a user-defined type,
# so the parser may do another recursive iteration
# through the same plan
, _maybe_node_for_user_type]


def decide_node_type(
Expand Down Expand Up @@ -440,10 +440,11 @@ def __call__(self,
:param overrides: a mapping of type_field => serialized_field_name.
"""
schema_node = _node_for_type(typ, overrides)
if not schema_node:
try:
schema_node = decide_node_type(typ, overrides)
except TypeError as e:
raise TypeError(
f'Cannot create a type constructor for {typ}'
f'Cannot create a type constructor for {typ}: {e}'
)
return schema_node.deserialize, schema_node.serialize

Expand Down

0 comments on commit 6d6d7b4

Please sign in to comment.