Example #1
0
 def test_instance(self, C):
     """
     Raises `TypeError` on non-classes.
     """
     with pytest.raises(TypeError) as e:
         fields(C(1, 2))
     assert "Passed object must be a class." == e.value.args[0]
Example #2
0
 def test_empty_metadata_singleton(self, list_of_attrs):
     """
     All empty metadata attributes share the same empty metadata dict.
     """
     C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))
     for a in fields(C)[1:]:
         assert a.metadata is fields(C)[0].metadata
Example #3
0
 def test_copies(self, C):
     """
     Returns a new list object with new `Attribute` objects.
     """
     assert C.__attrs_attrs__ is not fields(C)
     assert all(new == original and new is not original
                for new, original
                in zip(fields(C), C.__attrs_attrs__))
Example #4
0
    def test_instance(self, C):
        """
        Raises `TypeError` on non-classes.
        """
        with pytest.raises(TypeError) as e:
            fields(C(1, 2))

        assert "Passed object must be a class." == e.value.args[0]
Example #5
0
 def test_handler_non_attrs_class(self, C):
     """
     Raises `ValueError` if passed a non-``attrs`` instance.
     """
     with pytest.raises(ValueError) as e:
         fields(object)
     assert (
         "{o!r} is not an attrs-decorated class.".format(o=object)
     ) == e.value.args[0]
Example #6
0
    def test_fields_dict(self, C):
        """
        Returns an ordered dict of ``{attribute_name: Attribute}``.
        """
        d = fields_dict(C)

        assert isinstance(d, ordered_dict)
        assert list(fields(C)) == list(d.values())
        assert [a.name for a in fields(C)] == [field_name for field_name in d]
Example #7
0
    def test_handler_non_attrs_class(self, C):
        """
        Raises `ValueError` if passed a non-``attrs`` instance.
        """
        with pytest.raises(NotAnAttrsClassError) as e:
            fields(object)

        assert ("{o!r} is not an attrs-decorated class.".format(
            o=object)) == e.value.args[0]
Example #8
0
    def test_fields_dict(self, C):
        """
        Returns an ordered dict of ``{attribute_name: Attribute}``.
        """
        d = fields_dict(C)

        assert isinstance(d, ordered_dict)
        assert list(fields(C)) == list(d.values())
        assert [a.name for a in fields(C)] == [field_name for field_name in d]
Example #9
0
 def test_change(self, C, val):
     """
     Changes work.
     """
     # Take the first attribute, and change it.
     assume(fields(C))  # Skip classes with no attributes.
     original = C()
     attribute = fields(C)[0]
     changed = assoc(original, **{attribute.name: val})
     assert getattr(changed, attribute.name) == val
Example #10
0
    def test_not_none_metadata(self, list_of_attrs):
        """
        Non-empty metadata attributes exist as fields after ``@attr.s``.
        """
        C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))

        assert len(fields(C)) > 0

        for cls_a, raw_a in zip(fields(C), list_of_attrs):
            assert cls_a.metadata != {}
            assert cls_a.metadata == raw_a.metadata
Example #11
0
    def test_not_none_metadata(self, list_of_attrs):
        """
        Non-empty metadata attributes exist as fields after ``@attr.s``.
        """
        C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))

        assert len(fields(C)) > 0

        for cls_a, raw_a in zip(fields(C), list_of_attrs):
            assert cls_a.metadata != {}
            assert cls_a.metadata == raw_a.metadata
Example #12
0
    def test_types(self):
        """
        Sets the `Attribute.type` attr from type argument.
        """
        @attr.s
        class C(object):
            x = attr.ib(type=int)
            y = attr.ib(type=str)
            z = attr.ib()

        assert int is fields(C).x.type
        assert str is fields(C).y.type
        assert None is fields(C).z.type
Example #13
0
    def test_types(self):
        """
        Sets the `Attribute.type` attr from type argument.
        """
        @attr.s
        class C(object):
            x = attr.ib(type=int)
            y = attr.ib(type=str)
            z = attr.ib()

        assert int is fields(C).x.type
        assert str is fields(C).y.type
        assert None is fields(C).z.type
Example #14
0
 def test_change(self, C, data):
     """
     Changes work.
     """
     # Take the first attribute, and change it.
     assume(fields(C))  # Skip classes with no attributes.
     field_names = [a.name for a in fields(C)]
     original = C()
     chosen_names = data.draw(st.sets(st.sampled_from(field_names)))
     change_dict = {name: data.draw(st.integers())
                    for name in chosen_names}
     changed = assoc(original, **change_dict)
     for k, v in change_dict.items():
         assert getattr(changed, k) == v
Example #15
0
 def assert_proper_col_class(obj, obj_tuple):
     # Iterate over all attributes, and if they are lists or mappings
     # in the original, assert they are the same class in the dumped.
     for index, field in enumerate(fields(obj.__class__)):
         field_val = getattr(obj, field.name)
         if has(field_val.__class__):
             # This field holds a class, recurse the assertions.
             assert_proper_col_class(field_val, obj_tuple[index])
         elif isinstance(field_val, (list, tuple)):
             # This field holds a sequence of something.
             expected_type = type(obj_tuple[index])
             assert type(field_val) is expected_type  # noqa: E721
             for obj_e, obj_tuple_e in zip(field_val, obj_tuple[index]):
                 if has(obj_e.__class__):
                     assert_proper_col_class(obj_e, obj_tuple_e)
         elif isinstance(field_val, dict):
             orig = field_val
             tupled = obj_tuple[index]
             assert type(orig) is type(tupled)  # noqa: E721
             for obj_e, obj_tuple_e in zip(orig.items(),
                                           tupled.items()):
                 if has(obj_e[0].__class__):  # Dict key
                     assert_proper_col_class(obj_e[0], obj_tuple_e[0])
                 if has(obj_e[1].__class__):  # Dict value
                     assert_proper_col_class(obj_e[1], obj_tuple_e[1])
Example #16
0
 def assert_proper_tuple_class(obj, obj_tuple):
     assert isinstance(obj_tuple, tuple_class)
     for index, field in enumerate(fields(obj.__class__)):
         field_val = getattr(obj, field.name)
         if has(field_val.__class__):
             # This field holds a class, recurse the assertions.
             assert_proper_tuple_class(field_val, obj_tuple[index])
Example #17
0
    def test_asdict_preserve_order(self, cls):
        """
        Field order should be preserved when dumping to OrderedDicts.
        """
        instance = cls()
        dict_instance = asdict(instance, dict_factory=OrderedDict)

        assert [a.name for a in fields(cls)] == list(dict_instance.keys())
Example #18
0
    def test_asdict_preserve_order(self, cls):
        """
        Field order should be preserved when dumping to OrderedDicts.
        """
        instance = cls()
        dict_instance = asdict(instance, dict_factory=OrderedDict)

        assert [a.name for a in fields(cls)] == list(dict_instance.keys())
Example #19
0
def convert_key_to_attr_names(cls, original):
    """ convert key names to their corresponding attribute names """
    attrs = fields(cls)
    updated = {}

    for a in attrs:
        key_name = a.metadata.get('key') or a.name
        if key_name in original:
            updated[a.name] = original.get(key_name)

    return updated
Example #20
0
    def test_deprecated_convert(self):
        """
        Using *convert* raises a DeprecationWarning and sets the converter
        field.
        """
        def conv(v):
            return v

        with pytest.warns(DeprecationWarning) as wi:
            @attr.s
            class C(object):
                x = attr.ib(convert=conv)

            convert = fields(C).x.convert

        assert 2 == len(wi.list)
        w = wi.pop()

        assert conv == fields(C).x.converter == convert
        assert (
            "The `convert` argument is deprecated in favor of `converter`.  "
            "It will be removed after 2019/01.",
        ) == w.message.args
        assert __file__ == w.filename
Example #21
0
    def test_deprecated_convert(self):
        """
        Using *convert* raises a DeprecationWarning and sets the converter
        field.
        """
        def conv(v):
            return v

        with pytest.warns(DeprecationWarning) as wi:

            @attr.s
            class C(object):
                x = attr.ib(convert=conv)

            convert = fields(C).x.convert

        assert 2 == len(wi.list)
        w = wi.pop()

        assert conv == fields(C).x.converter == convert
        assert (
            "The `convert` argument is deprecated in favor of `converter`.  "
            "It will be removed after 2019/01.", ) == w.message.args
        assert __file__ == w.filename
    def test_validator_slots(self):
        """
        If a validator is passed, call it with the preliminary instance, the
        Attribute, and the argument.
        """
        class VException(Exception):
            pass

        def raiser(*args):
            raise VException(*args)

        C = make_class("C", {"a": attr("a", validator=raiser)}, slots=True)
        with pytest.raises(VException) as e:
            C(42)
        assert (fields(C)[0], 42,) == e.value.args[1:]
        assert isinstance(e.value.args[0], C)
Example #23
0
    def test_validator_slots(self):
        """
        If a validator is passed, call it with the preliminary instance, the
        Attribute, and the argument.
        """
        class VException(Exception):
            pass

        def raiser(*args):
            raise VException(*args)

        C = make_class("C", {"a": attr("a", validator=raiser)}, slots=True)
        with pytest.raises(VException) as e:
            C(42)
        assert (fields(C)[0], 42,) == e.value.args[1:]
        assert isinstance(e.value.args[0], C)
Example #24
0
def related_obj_to_dict(obj, **kwargs):
    """ Covert a known related object to a dictionary. """

    # Explicitly discard formatter kwarg, should not be cascaded down.
    kwargs.pop('formatter', None)

    # If True, remove fields that start with an underscore (e.g. _secret)
    suppress_private_attr = kwargs.get("suppress_private_attr", False)

    # if True, don't store fields with None values into dictionary.
    suppress_empty_values = kwargs.get("suppress_empty_values", False)

    # get list of attrs fields
    attrs = fields(obj.__class__)

    # instantiate return dict, use OrderedDict type by default
    return_dict = kwargs.get("dict_factory", OrderedDict)()

    for a in attrs:

        # skip if private attr and flag tells you to skip
        if suppress_private_attr and a.name.startswith("_"):
            continue

        metadata = a.metadata or {}

        # formatter is a related-specific `attrs` meta field
        #   see fields.DateField
        formatter = metadata.get('formatter')

        # get value and call to_dict on it, passing the kwargs/formatter
        value = getattr(obj, a.name)
        value = to_dict(value, formatter=formatter, **kwargs)

        # check flag, skip None values
        if suppress_empty_values and value is None:
            continue

        # field name can be overridden by the metadata field
        key_name = a.metadata.get('key') or a.name

        # store converted / formatted value into return dictionary
        return_dict[key_name] = value

    return return_dict
Example #25
0
 def assert_proper_dict_class(obj, obj_dict):
     assert isinstance(obj_dict, dict_class)
     for field in fields(obj.__class__):
         field_val = getattr(obj, field.name)
         if has(field_val.__class__):
             # This field holds a class, recurse the assertions.
             assert_proper_dict_class(field_val, obj_dict[field.name])
         elif isinstance(field_val, Sequence):
             dict_val = obj_dict[field.name]
             for item, item_dict in zip(field_val, dict_val):
                 if has(item.__class__):
                     assert_proper_dict_class(item, item_dict)
         elif isinstance(field_val, Mapping):
             # This field holds a dictionary.
             assert isinstance(obj_dict[field.name], dict_class)
             for key, val in field_val.items():
                 if has(val.__class__):
                     assert_proper_dict_class(val, obj_dict[key])
Example #26
0
 def assert_proper_dict_class(obj, obj_dict):
     assert isinstance(obj_dict, dict_class)
     for field in fields(obj.__class__):
         field_val = getattr(obj, field.name)
         if has(field_val.__class__):
             # This field holds a class, recurse the assertions.
             assert_proper_dict_class(field_val, obj_dict[field.name])
         elif isinstance(field_val, Sequence):
             dict_val = obj_dict[field.name]
             for item, item_dict in zip(field_val, dict_val):
                 if has(item.__class__):
                     assert_proper_dict_class(item, item_dict)
         elif isinstance(field_val, Mapping):
             # This field holds a dictionary.
             assert isinstance(obj_dict[field.name], dict_class)
             for key, val in field_val.items():
                 if has(val.__class__):
                     assert_proper_dict_class(val, obj_dict[key])
Example #27
0
def convert_key_to_attr_names(cls, original):
    """ convert key names to their corresponding attribute names """
    attrs = fields(cls)
    updated = {}
    keys_pulled = set()

    for a in attrs:
        key_name = a.metadata.get('key') or a.name
        if key_name in original:
            updated[a.name] = original.get(key_name)
            keys_pulled.add(key_name)

    if getattr(cls, '__related_strict__', False):
        extra = set(original.keys()) - keys_pulled
        if len(extra):
            raise ValueError("Extra keys (strict mode): {}".format(extra))

    return updated
Example #28
0
    def test_metadata_present(self, list_of_attrs):
        """
        Assert dictionaries are copied and present.
        """
        C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))

        for hyp_attr, class_attr in zip(list_of_attrs, fields(C)):
            if hyp_attr.metadata is None:
                # The default is a singleton empty dict.
                assert class_attr.metadata is not None
                assert len(class_attr.metadata) == 0
            else:
                assert hyp_attr.metadata == class_attr.metadata

                # Once more, just to assert getting items and iteration.
                for k in class_attr.metadata:
                    assert hyp_attr.metadata[k] == class_attr.metadata[k]
                    assert (
                        hyp_attr.metadata.get(k) == class_attr.metadata.get(k))
Example #29
0
    def test_metadata_present(self, list_of_attrs):
        """
        Assert dictionaries are copied and present.
        """
        C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))

        for hyp_attr, class_attr in zip(list_of_attrs, fields(C)):
            if hyp_attr.metadata is None:
                # The default is a singleton empty dict.
                assert class_attr.metadata is not None
                assert len(class_attr.metadata) == 0
            else:
                assert hyp_attr.metadata == class_attr.metadata

                # Once more, just to assert getting items and iteration.
                for k in class_attr.metadata:
                    assert hyp_attr.metadata[k] == class_attr.metadata[k]
                    assert (hyp_attr.metadata.get(k) ==
                            class_attr.metadata.get(k))
Example #30
0
    def from_config(cls, cfg):
        # TODO - create a nicer error message - see above
                # Verbose unrecognized field
        # for k in kwargs.keys():
        #     if k not in cls.REQ_FIELDS + cls.OPT_FIELDS:
        #         raise ValueError("Unrecognized field in info: '{f}'. Avaiable fields are: {l}".
        #                          format(f=k, l=cls.REQ_FIELDS))

        # # Verbose undefined field
        # undefined_set = set(cls.REQ_FIELDS) - kwargs.keys()
        # if undefined_set:
        #     raise ValueError("The following arguments were not specified: {0}. Please specify them.".
        #                      format(undefined_set))
        attrs = fields(cls)
        cls_keys = {a.metadata.get('key') or a.name for a in attrs}
        cfg_keys = set(cfg.keys())
        extra_keys = cfg_keys - cls_keys
        if len(extra_keys) > 0:
            raise ValueError("Unrecognized fields: {0}. Available fields are {1}".format(extra_keys, cls_keys))

        return related.to_model(cls, cfg)
Example #31
0
    def test_metadata_immutability(self, C, string):
        """
        The metadata dict should be best-effort immutable.
        """
        for a in fields(C):
            with pytest.raises(TypeError):
                a.metadata[string] = string
            with pytest.raises(AttributeError):
                a.metadata.update({string: string})
            with pytest.raises(AttributeError):
                a.metadata.clear()
            with pytest.raises(AttributeError):
                a.metadata.setdefault(string, string)

            for k in a.metadata:
                # For some reason, Python 3's MappingProxyType throws an
                # IndexError for deletes on a large integer key.
                with pytest.raises((TypeError, IndexError)):
                    del a.metadata[k]
                with pytest.raises(AttributeError):
                    a.metadata.pop(k)
            with pytest.raises(AttributeError):
                    a.metadata.popitem()
Example #32
0
    def test_metadata_immutability(self, C, string):
        """
        The metadata dict should be best-effort immutable.
        """
        for a in fields(C):
            with pytest.raises(TypeError):
                a.metadata[string] = string
            with pytest.raises(AttributeError):
                a.metadata.update({string: string})
            with pytest.raises(AttributeError):
                a.metadata.clear()
            with pytest.raises(AttributeError):
                a.metadata.setdefault(string, string)

            for k in a.metadata:
                # For some reason, Python 3's MappingProxyType throws an
                # IndexError for deletes on a large integer key.
                with pytest.raises((TypeError, IndexError)):
                    del a.metadata[k]
                with pytest.raises(AttributeError):
                    a.metadata.pop(k)
            with pytest.raises(AttributeError):
                a.metadata.popitem()
Example #33
0
 def test_allow(self, excl, value):
     """
     Return True if class or attribute is not blacklisted.
     """
     e = exclude(*excl)
     assert e(fields(C).a, value) is True
Example #34
0
 def test_allow(self, incl, value):
     """
     Return True if a class or attribute is whitelisted.
     """
     i = include(*incl)
     assert i(fields(C).a, value) is True
Example #35
0
 def test_allow(self, incl, value):
     """
     Return True if a class or attribute is whitelisted.
     """
     i = include(*incl)
     assert i(fields(C).a, value) is True
Example #36
0
 def test_drop_class(self, excl, value):
     """
     Return True on non-blacklisted classes and attributes.
     """
     e = exclude(*excl)
     assert e(fields(C).a, value) is False
Example #37
0
def asjsonld(
    inst,
    recurse=True,
    filter=None,
    dict_factory=dict,
    retain_collection_types=False,
    export_context=True,
):
    """Dump a JSON-LD class to the JSON with generated ``@context`` field."""
    attrs = fields(inst.__class__)
    rv = dict_factory()

    def convert_value(v):
        """Convert special types."""
        if isinstance(v, Path):
            return str(v)
        return v

    for a in attrs:
        v = getattr(inst, a.name)
        # do not export context for containers
        ec = export_context and KEY_CLS not in a.metadata

        if filter is not None and not filter(a, v):
            continue
        if recurse is True:
            if has(v.__class__):
                rv[a.name] = asjsonld(v,
                                      recurse=True,
                                      filter=filter,
                                      dict_factory=dict_factory)
            elif isinstance(v, (tuple, list, set)):
                cf = v.__class__ if retain_collection_types is True else list
                rv[a.name] = cf([
                    asjsonld(
                        i,
                        recurse=True,
                        filter=filter,
                        dict_factory=dict_factory,
                        export_context=ec,
                    ) if has(i.__class__) else i for i in v
                ])
            elif isinstance(v, dict):
                df = dict_factory
                rv[a.name] = df((
                    asjsonld(kk, dict_factory=df) if has(kk.__class__) else kk,
                    asjsonld(vv, dict_factory=df, export_context=ec
                             ) if has(vv.__class__) else vv)
                                for kk, vv in iteritems(v))
            else:
                rv[a.name] = convert_value(v)
        else:
            rv[a.name] = convert_value(v)

    inst_cls = type(inst)

    if export_context:
        rv['@context'] = deepcopy(inst_cls._jsonld_context)

    if inst_cls._jsonld_type:
        rv['@type'] = inst_cls._jsonld_type
    return rv
Example #38
0
def asjsonld(
    inst,
    recurse=True,
    filter=None,
    dict_factory=dict,
    retain_collection_types=False,
    add_context=True,
    use_scoped_type_form=False,
    basedir=None,
):
    """Dump a JSON-LD class to the JSON with generated ``@context`` field."""
    jsonld_fields = inst.__class__._jsonld_fields
    attrs = tuple(
        field
        for field in fields(inst.__class__) if field.name in jsonld_fields
    )
    rv = dict_factory()

    def convert_value(value):
        """Convert non-serializable types."""
        if isinstance(value, Path):
            result = str(value)
            if basedir:
                result = os.path.relpath(result, str(basedir))
            return result

        if isinstance(value, datetime):
            if not value.tzinfo:
                # set timezone to local timezone
                tz = datetime.now(timezone.utc).astimezone().tzinfo
                value = value.replace(tzinfo=tz)
            return value.isoformat()

        return value

    inst_cls = type(inst)

    for a in attrs:
        v = getattr(inst, a.name)
        scoped = a.name in inst_cls._scoped_properties

        # skip proxies
        if isinstance(v, weakref.ReferenceType):
            continue

        if filter is not None and not filter(a, v):
            continue
        if recurse is True:
            if has(v.__class__):
                rv[a.name] = asjsonld(
                    v,
                    recurse=True,
                    filter=filter,
                    dict_factory=dict_factory,
                    add_context=False,
                    use_scoped_type_form=scoped,
                    basedir=basedir,
                )
            elif isinstance(v, (tuple, list, set)):
                cf = v.__class__ if retain_collection_types is True else list
                rv[a.name] = cf([
                    asjsonld(
                        i,
                        recurse=True,
                        filter=filter,
                        dict_factory=dict_factory,
                        add_context=False,
                        use_scoped_type_form=scoped,
                        basedir=basedir,
                    ) if has(i.__class__) else i for i in v
                ])
            elif isinstance(v, dict):
                df = dict_factory
                rv[a.name] = df((
                    asjsonld(
                        kk,
                        dict_factory=df,
                        add_context=False,
                        basedir=basedir,
                    ) if has(kk.__class__) else convert_value(kk),
                    asjsonld(
                        vv,
                        dict_factory=df,
                        add_context=False,
                        basedir=basedir,
                    ) if has(vv.__class__) else vv
                ) for kk, vv in iteritems(v))
            else:
                rv[a.name] = convert_value(v)
        else:
            rv[a.name] = convert_value(v)

    if add_context:
        rv['@context'] = deepcopy(inst_cls._jsonld_context)

    rv_type = []
    if inst_cls._jsonld_type:
        if isinstance(inst_cls._jsonld_type, (list, tuple, set)):
            rv_type.extend(inst_cls._jsonld_type)
        else:
            rv_type.append(inst_cls._jsonld_type)

        if use_scoped_type_form:
            rv_type = [
                '{}_{}'.format(inst_cls._renku_type, t) for t in rv_type
            ]

        rv['@type'] = rv_type[0] if len(rv_type) == 1 else rv_type

    return rv
Example #39
0
 def fix_keys(data):
     """Fix names of keys."""
     for a in fields(cls):
         a_name = a.name.rstrip('_')
         if a_name in data:
             yield a.name, data[a_name]
Example #40
0
def ascwl(
    inst,
    recurse=True,
    filter=None,
    dict_factory=dict,
    retain_collection_types=False,
    basedir=None,
):
    """Return the ``attrs`` attribute values of *inst* as a dict.

    Support ``jsonldPredicate`` in a field metadata for generating
    mappings from lists.

    Adapted from ``attr._funcs``.
    """
    attrs = fields(inst.__class__)
    rv = dict_factory()

    def convert_value(v):
        """Convert special types."""
        if isinstance(v, Path):
            v = str(v)
            return os.path.relpath(v, str(basedir)) if basedir else v
        return v

    for a in attrs:
        if a.name.startswith('__'):
            continue

        a_name = a.name.rstrip('_')
        v = getattr(inst, a.name)
        if filter is not None and not filter(a, v):
            continue
        if recurse is True:
            if has(v.__class__):
                rv[a_name] = ascwl(
                    v,
                    recurse=True,
                    filter=filter,
                    dict_factory=dict_factory,
                    basedir=basedir,
                )

            elif isinstance(v, (tuple, list, set)):
                cf = v.__class__ if retain_collection_types is True else list
                rv[a_name] = cf([
                    ascwl(
                        i,
                        recurse=True,
                        filter=filter,
                        dict_factory=dict_factory,
                        basedir=basedir,
                    ) if has(i.__class__) else i for i in v
                ])

                if 'jsonldPredicate' in a.metadata:
                    k = a.metadata['jsonldPredicate'].get('mapSubject')
                    if k:
                        vv = dict_factory()
                        for i in rv[a_name]:
                            kk = i.pop(k)
                            vv[kk] = i
                        rv[a_name] = vv

            elif isinstance(v, dict):
                df = dict_factory
                rv[a_name] = df((ascwl(
                    kk,
                    dict_factory=df,
                    basedir=basedir,
                ) if has(kk.__class__) else convert_value(kk),
                                 ascwl(
                                     vv,
                                     dict_factory=df,
                                     basedir=basedir,
                                 ) if has(vv.__class__) else vv)
                                for kk, vv in iteritems(v))
            else:
                rv[a_name] = convert_value(v)
        else:
            rv[a_name] = convert_value(v)

    if isinstance(inst, CWLClass):
        rv['class'] = inst.__class__.__name__

    return rv
Example #41
0
def asjsonld(
    inst,
    recurse=True,
    filter=None,
    dict_factory=dict,
    retain_collection_types=False,
    export_context=True,
    basedir=None,
):
    """Dump a JSON-LD class to the JSON with generated ``@context`` field."""
    jsonld_fields = inst.__class__._jsonld_fields
    attrs = tuple(field for field in fields(inst.__class__)
                  if field.name in jsonld_fields)
    rv = dict_factory()

    def convert_value(v):
        """Convert special types."""
        if isinstance(v, Path):
            v = str(v)
            return os.path.relpath(v, str(basedir)) if basedir else v
        return v

    for a in attrs:
        v = getattr(inst, a.name)

        # skip proxies
        if isinstance(v, weakref.ReferenceType):
            continue

        # do not export context for containers
        ec = export_context and KEY_CLS not in a.metadata

        if filter is not None and not filter(a, v):
            continue
        if recurse is True:
            if has(v.__class__):
                rv[a.name] = asjsonld(
                    v,
                    recurse=True,
                    filter=filter,
                    dict_factory=dict_factory,
                    basedir=basedir,
                )
            elif isinstance(v, (tuple, list, set)):
                cf = v.__class__ if retain_collection_types is True else list
                rv[a.name] = cf([
                    asjsonld(
                        i,
                        recurse=True,
                        filter=filter,
                        dict_factory=dict_factory,
                        export_context=ec,
                        basedir=basedir,
                    ) if has(i.__class__) else i for i in v
                ])
            elif isinstance(v, dict):
                df = dict_factory
                rv[a.name] = df((asjsonld(
                    kk,
                    dict_factory=df,
                    basedir=basedir,
                ) if has(kk.__class__) else convert_value(kk),
                                 asjsonld(
                                     vv,
                                     dict_factory=df,
                                     export_context=ec,
                                     basedir=basedir,
                                 ) if has(vv.__class__) else vv)
                                for kk, vv in iteritems(v))
            else:
                rv[a.name] = convert_value(v)
        else:
            rv[a.name] = convert_value(v)

    inst_cls = type(inst)

    if export_context:
        rv['@context'] = deepcopy(inst_cls._jsonld_context)

    if inst_cls._jsonld_type:
        rv['@type'] = inst_cls._jsonld_type
    return rv
Example #42
0
 def test_drop_class(self, excl, value):
     """
     Return True on non-blacklisted classes and attributes.
     """
     e = exclude(*excl)
     assert e(fields(C).a, value) is False
Example #43
0
 def test_fields(self, C):
     """
     Returns a list of `Attribute`a.
     """
     assert all(isinstance(a, Attribute) for a in fields(C))
Example #44
0
 def test_fields_properties(self, C):
     """
     Fields returns a tuple with properties.
     """
     for attribute in fields(C):
         assert getattr(fields(C), attribute.name) is attribute
Example #45
0
 def test_drop_class(self, incl, value):
     """
     Return False on non-whitelisted classes and attributes.
     """
     i = include(*incl)
     assert i(fields(C).a, value) is False
Example #46
0
 def test_fields(self, C):
     """
     Returns a list of `Attribute`a.
     """
     assert all(isinstance(a, Attribute) for a in fields(C))
Example #47
0
 def test_drop_class(self, incl, value):
     """
     Return False on non-whitelisted classes and attributes.
     """
     i = include(*incl)
     assert i(fields(C).a, value) is False
Example #48
0
 def test_allow(self, excl, value):
     """
     Return True if class or attribute is not blacklisted.
     """
     e = exclude(*excl)
     assert e(fields(C).a, value) is True
Example #49
0
 def test_fields_properties(self, C):
     """
     Fields returns a tuple with properties.
     """
     for attribute in fields(C):
         assert getattr(fields(C), attribute.name) is attribute