from __future__ import annotations import json import uuid from dataclasses import dataclass from enum import Enum from typing import Optional, get_type_hints from megasniff import SchemaDeflatorGenerator from src.megasniff import SchemaInflatorGenerator def test_basic_constructor(): class A: def __init__(self, a: int): self.a = a infl = SchemaInflatorGenerator() fn = infl.schema_to_inflator(A) a = fn({'a': 42}) assert a.a == 42 def test_unions(): @dataclass class A: a: int | str infl = SchemaInflatorGenerator() fn = infl.schema_to_inflator(A) a = fn({'a': 42}) assert a.a == 42 a = fn({'a': '42'}) assert a.a == 42 a = fn({'a': '42a'}) assert a.a == '42a' @dataclass class CircA: b: CircB @dataclass class CircB: a: CircA | None def test_circular(): infl = SchemaInflatorGenerator() fn = infl.schema_to_inflator(CircA) a = fn({'b': {'a': None}}) assert isinstance(a.b, CircB) def test_optional(): @dataclass class C: a: Optional[int] = None infl = SchemaInflatorGenerator() fn = infl.schema_to_inflator(C) c = fn({}) assert c.a is None def test_uuid(): @dataclass class K: a: uuid.UUID b: list[uuid.UUID] c: Optional[uuid.UUID] d: dict[uuid.UUID, uuid.UUID] infl = SchemaInflatorGenerator(store_sources=True) defl = SchemaDeflatorGenerator(store_sources=True) infl_fn = infl.schema_to_inflator(K) defl_fn = defl.schema_to_deflator(K) okd = { 'a': str(uuid.uuid4()), 'b': [str(uuid.uuid4()), str(uuid.uuid4()), str(uuid.uuid4())], 'c': None, 'd': {str(uuid.uuid4()): str(uuid.uuid4()), str(uuid.uuid4()): str(uuid.uuid4())} } k = infl_fn(okd) kd = defl_fn(k) assert isinstance(kd['a'], str) assert isinstance(kd['b'], list) assert len(kd['b']) == 3 assert isinstance(kd['b'][0], str) assert isinstance(kd['b'][1], str) assert isinstance(kd['b'][2], str) assert kd['c'] is None assert isinstance(kd['d'], dict) assert len(kd['d']) == 2 assert all(map(lambda x: isinstance(x, str), kd['d'].keys())) assert all(map(lambda x: isinstance(x, str), kd['d'].values())) assert isinstance(k.a, uuid.UUID) assert isinstance(k.b[0], uuid.UUID) assert isinstance(k.b[1], uuid.UUID) assert isinstance(k.b[2], uuid.UUID) assert k.c is None assert isinstance(k.d, dict) assert len(k.d) == 2 assert all(map(lambda x: isinstance(x, uuid.UUID), k.d.keys())) assert all(map(lambda x: isinstance(x, uuid.UUID), k.d.values())) class AEnum(Enum): a = 'a' b = 'b' c = 42 e1 = {'a': 'b'} e2 = ['a', 'b'] @dataclass class Z: a: Optional[AEnum] = None def test_enum(): infl = SchemaInflatorGenerator() defl = SchemaDeflatorGenerator() infl_fn = infl.schema_to_inflator(Z) defl_fn = defl.schema_to_deflator(Z) for it in AEnum: ref = {'a': it.value} ref_str = json.dumps(ref) z = infl_fn(json.loads(ref_str)) assert z.a is not None assert z.a.value == it.value assert z.a.name == it.name zdict = defl_fn(z) assert len(zdict) == 1 assert zdict['a'] == it.value assert json.dumps(zdict) == ref_str assert infl_fn(zdict) == z