Example #1
0
def test_enum_unstructure(enum, dump_strat, data):
    """Dumping enums of primitives converts them to their primitives."""
    converter = Converter(unstruct_strat=dump_strat)

    member = data.draw(sampled_from(list(enum.__members__.values())))

    assert converter.unstructure(member) == member.value
Example #2
0
def test_seq_of_simple_classes_unstructure(cls_and_vals, seq_type):
    """Dumping a sequence of primitives is a simple copy operation."""
    converter = Converter()

    inputs = seq_type(cl(*vals) for cl, vals in cls_and_vals)
    outputs = converter.unstructure(inputs)
    assert type(outputs) == seq_type
    assert all(type(e) is dict for e in outputs)
Example #3
0
def test_mapping_unstructure(map_and_type, dump_strat):
    """Dumping a mapping of primitives is a simple copy operation."""
    converter = Converter(unstruct_strat=dump_strat)
    mapping = map_and_type[0]
    dumped = converter.unstructure(mapping)
    assert dumped == mapping
    assert dumped is not mapping
    assert type(dumped) is type(mapping)
Example #4
0
def test_enum_unstructure(enum, dump_strat, choice):
    # type: (EnumMeta, UnstructureStrategy) -> None
    """Dumping enums of primitives converts them to their primitives."""
    converter = Converter(unstruct_strat=dump_strat)

    member = choice(list(enum.__members__.values()))

    assert converter.unstructure(member) == member.value
Example #5
0
def test_seq_unstructure(seq_and_type, dump_strat):
    """Dumping a sequence of primitives is a simple copy operation."""
    converter = Converter(unstruct_strat=dump_strat)
    assert converter.unstruct_strat is dump_strat
    seq = seq_and_type[0]
    dumped = converter.unstructure(seq)
    assert dumped == seq
    if not isinstance(seq, tuple):
        assert dumped is not seq
    assert type(dumped) is type(seq)
Example #6
0
def test_roundtrip(cl_and_vals):
    """We dump the class, then we load it."""
    converter = Converter()
    cl, vals = cl_and_vals
    obj = cl(*vals)

    dumped = converter.unstructure(obj)
    loaded = converter.structure(dumped, cl)

    assert obj == loaded
Example #7
0
def test_structure_simple_from_dict(cl_and_vals):
    """Test structuring non-nested attrs classes dumped with asdict."""
    converter = Converter()
    cl, vals = cl_and_vals
    obj = cl(*vals)

    dumped = asdict(obj)
    loaded = converter.structure(dumped, cl)

    assert obj == loaded
Example #8
0
def test_set_unstructure(set_and_type, dump_strat):
    """Dumping a set of primitives is a simple copy operation."""
    converter = Converter(unstruct_strat=dump_strat)
    assert converter.unstruct_strat is dump_strat
    set = set_and_type[0]
    dumped = converter.unstructure(set)
    assert dumped == set
    if set:
        assert dumped is not set
    assert type(dumped) is type(set)
Example #9
0
def test_unstructure_hooks(cl_and_vals):
    """
    Unstructure hooks work.
    """
    converter = Converter()
    cl, vals = cl_and_vals
    inst = cl(*vals)

    converter.register_unstructure_hook(cl, lambda _: "test")

    assert converter.unstructure(inst) == "test"
Example #10
0
def test_structure_tuple(cl_and_vals):
    """Test loading from a tuple, by registering the loader."""
    converter = Converter()
    cl, vals = cl_and_vals
    converter.register_structure_hook(cl, converter.structure_attrs_fromtuple)
    obj = cl(*vals)

    dumped = astuple(obj)
    loaded = converter.structure(dumped, cl)

    assert obj == loaded
Example #11
0
def test_structure_forward_ref(class_with_forward_ref_attr, strat):
    """
    Classes with forward_ref field can be unstructured and structured.
    """
    converter = Converter(unstruct_strat=strat)

    unstructured_expected = converter.unstructure(class_with_forward_ref_attr)
    structured = converter.structure(unstructured_expected, C)
    unstructured_actual = converter.unstructure(structured)

    assert structured == class_with_forward_ref_attr
    assert unstructured_actual == unstructured_expected
Example #12
0
def test_structure_union(cl_and_vals_a, cl_and_vals_b):
    """Structuring of automatically-disambiguable unions works."""
    converter = Converter()
    cl_a, vals_a = cl_and_vals_a
    cl_b, vals_b = cl_and_vals_b
    a_field_names = {a.name for a in fields(cl_a)}
    b_field_names = {a.name for a in fields(cl_b)}
    assume(a_field_names)
    assume(b_field_names)

    common_names = a_field_names & b_field_names
    if len(a_field_names) > len(common_names):
        obj = cl_a(*vals_a)
        dumped = asdict(obj)
        res = converter.structure(dumped, Union[cl_a, cl_b])
        assert isinstance(res, cl_a)
        assert obj == res
Example #13
0
def test_structure_simple_from_dict_default(cl_and_vals, data):
    """Test structuring non-nested attrs classes with default value."""
    converter = Converter()
    cl, vals = cl_and_vals
    obj = cl(*vals)
    attrs_with_defaults = [a for a in fields(cl) if a.default is not NOTHING]
    to_remove = data.draw(
        lists(elements=sampled_from(attrs_with_defaults), unique=True))

    for a in to_remove:
        if isinstance(a.default, Factory):
            setattr(obj, a.name, a.default.factory())
        else:
            setattr(obj, a.name, a.default)

    dumped = asdict(obj)

    for a in to_remove:
        del dumped[a.name]

    assert obj == converter.structure(dumped, cl)
Example #14
0
def enrich_unstructured_wildcat(converter: Converter, obj: WC,
                                unstructured_obj_dict: dict) -> dict:
    wildcat_attrs_names = get_attrs_names(type(obj))
    wildcat_nonattrs_dict = {
        key: converter.unstructure(obj[key])
        for key in obj if key not in wildcat_attrs_names
    }
    # note that typed entries take absolute precedence over untyped in case of collisions.
    # these collisions should generally be prevented at runtime by the wildcat
    # logic that is injected into the type, but if something were to sneak through
    # we would prefer whatever had been set via the attribute.
    return {**wildcat_nonattrs_dict, **unstructured_obj_dict}
Example #15
0
def test_structure_union_explicit(cl_and_vals_a, cl_and_vals_b):
    """Structuring of manually-disambiguable unions works."""
    converter = Converter()
    cl_a, vals_a = cl_and_vals_a
    cl_b, vals_b = cl_and_vals_b

    def dis(obj, _):
        return converter.structure(obj, cl_a)

    converter.register_structure_hook(Union[cl_a, cl_b], dis)

    inst = cl_a(*vals_a)

    assert inst == converter.structure(converter.unstructure(inst),
                                       Union[cl_a, cl_b])
Example #16
0
def test_attrs_astuple_unstructure(nested_class):
    # type: (Type) -> None
    """Our dumping should be identical to `attrs`."""
    converter = Converter(unstruct_strat=UnstructureStrategy.AS_TUPLE)
    instance = nested_class[0]()
    assert converter.unstructure(instance) == astuple(instance)
Example #17
0
from marshmallow import fields
from cattr.converters import Converter

from simple_smartsheet import config
from simple_smartsheet import exceptions
from simple_smartsheet import utils
from simple_smartsheet.types import IndexesType, IndexesKeysType

if TYPE_CHECKING:
    from simple_smartsheet.smartsheet import Smartsheet  # noqa: F401
    from simple_smartsheet.models.extra import Result


logger = logging.getLogger(__name__)

converter = Converter()
converter.register_structure_hook(datetime, lambda ts, _: ts)
converter.register_structure_hook(IndexesKeysType, lambda x, _: x)
converter.register_structure_hook(IndexesType, lambda x, _: x)
converter.register_structure_hook(Union[float, str, datetime, None], lambda ts, _: ts)


class Schema(marshmallow.Schema):
    class Meta:
        unknown = utils.get_unknown_field_handling(config.DEBUG)

    @marshmallow.post_dump
    def remove_none(self, data):
        return {key: value for key, value in data.items() if value is not None}

Example #18
0
from datetime import date, datetime
from typing import List, Dict
from typing import Optional, Union

import attr
import dateutil.parser
from cattr.converters import Converter
from dateutil import tz

converter = Converter()
converter.register_unstructure_hook(datetime, lambda dt: dt.isoformat())
converter.register_structure_hook(datetime,
                                  lambda ts, _: dateutil.parser.parse(ts))
converter.register_unstructure_hook(date, lambda dt: dt.isoformat())
converter.register_structure_hook(date,
                                  lambda ts, _: dateutil.parser.parse(ts))
converter.register_structure_hook(
    Union[date, datetime],
    lambda ts, _: dateutil.parser.parse(ts).date()
    if len(ts) == 10 else dateutil.parser.parse(ts),
)

format_version = 2


@attr.s(frozen=True, auto_attribs=True)
class Person:
    name: str
    party: Optional[str]
    begin: Optional[date] = None
    end: Optional[date] = None
from datetime import date, datetime
from typing import List, Dict
from typing import Optional, Union

import attr
from cattr.converters import Converter
from dateutil import tz

converter = Converter()
converter.register_unstructure_hook(datetime, lambda dt: dt.isoformat())
converter.register_structure_hook(datetime,
                                  lambda ts, _: datetime.fromisoformat(ts))
converter.register_unstructure_hook(date, lambda dt: dt.isoformat())
converter.register_structure_hook(date, lambda ts, _: date.fromisoformat(ts))
converter.register_structure_hook(
    Optional[Union[date, datetime]],
    lambda ts, _: date.fromisoformat(ts)
    if len(ts) == 10 else datetime.fromisoformat(ts),
)

format_version = 4


@attr.s(frozen=True, auto_attribs=True)
class Person:
    # Overview page
    name: str
    party: Optional[str]
    begin: Optional[date] = None
    end: Optional[date] = None
    original_id: Optional[int] = None
Example #20
0
    if _is_attrs_class(obj_to_unstructure.__class__):
        keys_to_strip = _get_names_of_defaulted_nonliteral_attrs(
            obj_to_unstructure)
        return {
            k: v
            for k, v in unstructured_but_unclean.items()
            if k not in keys_to_strip
        }
    return unstructured_but_unclean


class StripAttrsDefaultsOnUnstructurePatch(TypecatsCattrPatch):
    def unstructure_patch(self, original_handler: ty.Callable,
                          obj_to_unstructure: ty.Any) -> ty.Any:
        rv = super().unstructure_patch(original_handler, obj_to_unstructure)
        return _strip_attrs_defaults(rv, obj_to_unstructure)


_STRIP_DEFAULTS_CONVERTER = Converter()  # create converter
__PATCH = StripAttrsDefaultsOnUnstructurePatch(
    _STRIP_DEFAULTS_CONVERTER)  # patch it


def get_stripping_converter() -> Converter:
    return _STRIP_DEFAULTS_CONVERTER


def unstruc_strip_defaults(obj: ty.Any) -> ty.Any:
    """This is the only thing anyone outside needs to worry about"""
    return _STRIP_DEFAULTS_CONVERTER.unstructure(obj)
Example #21
0
def test_attrs_asdict_unstructure(nested_class):
    """Our dumping should be identical to `attrs`."""
    converter = Converter()
    instance = nested_class[0]()
    assert converter.unstructure(instance) == asdict(instance)