147 lines
3.3 KiB
Python
147 lines
3.3 KiB
Python
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
|