Python attr.fields() Examples

The following are 30 code examples of attr.fields(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module attr , or try the search function .
Example #1
Source File: _type_validation.py    From attrs-strict with Apache License 2.0 7 votes vote down vote up
def resolve_types(cls, global_ns=None, local_ns=None):
    """
    Resolve any strings and forward annotations in type annotations.

    :param type cls: Class to resolve.
    :param globalns: Dictionary containing global variables, if needed.
    :param localns: Dictionary containing local variables, if needed.
    :raise TypeError: If *cls* is not a class.
    :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
           class.
    :raise NameError: If types cannot be resolved because of missing variables.

    """
    hints = typing.get_type_hints(cls, globalns=global_ns, localns=local_ns)
    for field in attr.fields(cls):
        if field.name in hints:
            # Since fields have been frozen we must work around it.
            object.__setattr__(field, "type", hints[field.name]) 
Example #2
Source File: test_annotations.py    From attrs with MIT License 6 votes vote down vote up
def test_basic_annotations(self):
        """
        Sets the `Attribute.type` attr from basic type annotations.
        """

        @attr.s
        class C:
            x: int = attr.ib()
            y = attr.ib(type=str)
            z = attr.ib()

        assert int is attr.fields(C).x.type
        assert str is attr.fields(C).y.type
        assert None is attr.fields(C).z.type
        assert C.__init__.__annotations__ == {
            "x": int,
            "y": str,
            "return": None,
        } 
Example #3
Source File: test_disambigutors.py    From cattrs with MIT License 6 votes vote down vote up
def test_fallback(cl_and_vals):
    """The fallback case works."""
    cl, vals = cl_and_vals

    assume(attr.fields(cl))  # At least one field.

    @attr.s
    class A(object):
        pass

    fn = create_uniq_field_dis_func(A, cl)

    assert fn({}) is A
    assert fn(attr.asdict(cl(*vals))) is cl

    attr_names = {a.name for a in attr.fields(cl)}

    if "xyz" not in attr_names:
        fn({"xyz": 1}) is A  # Uses the fallback. 
Example #4
Source File: computation_types.py    From federated with Apache License 2.0 6 votes vote down vote up
def _to_type_from_attrs(spec) -> Type:
  """Converts an `attr.s` class or instance to a `tff.Type`."""
  if isinstance(spec, type):
    # attrs class type, introspect the attributes for their type annotations.
    elements = [(a.name, a.type) for a in attr.fields(spec)]
    missing_types = [n for (n, t) in elements if not t]
    if missing_types:
      raise TypeError((
          "Cannot infer tff.Type for attr.s class '{}' because some attributes "
          'were missing type specifications: {}').format(
              spec.__name__, missing_types))
    the_type = spec
  else:
    # attrs class instance, inspect the field values for instances convertible
    # to types.
    elements = attr.asdict(
        spec, dict_factory=collections.OrderedDict, recurse=False)
    the_type = type(spec)

  return NamedTupleTypeWithPyContainerType(elements, the_type) 
Example #5
Source File: test_structure_attrs.py    From cattrs with MIT License 6 votes vote down vote up
def test_structure_simple_from_dict_default(converter, cl_and_vals, data):
    """Test structuring non-nested attrs classes with default value."""
    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 #6
Source File: test_structure_attrs.py    From cattrs with MIT License 6 votes vote down vote up
def test_structure_union_none(converter, cl_and_vals_a, cl_and_vals_b):
    """Structuring of automatically-disambiguable unions works."""
    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, None])
        assert isinstance(res, cl_a)
        assert obj == res

    assert converter.structure(None, Union[cl_a, cl_b, None]) is None 
Example #7
Source File: test_structure_attrs.py    From cattrs with MIT License 6 votes vote down vote up
def test_structure_union(converter, cl_and_vals_a, cl_and_vals_b):
    """Structuring of automatically-disambiguable unions works."""
    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 #8
Source File: test_disambigutors.py    From cattrs with MIT License 6 votes vote down vote up
def test_disambiguation(cl_and_vals_a, cl_and_vals_b):
    """Disambiguation should work when there are unique fields."""
    cl_a, vals_a = cl_and_vals_a
    cl_b, vals_b = cl_and_vals_b

    req_a = {a.name for a in attr.fields(cl_a)}
    req_b = {a.name for a in attr.fields(cl_b)}

    assume(len(req_a))
    assume(len(req_b))

    assume((req_a - req_b) or (req_b - req_a))

    fn = create_uniq_field_dis_func(cl_a, cl_b)

    assert fn(attr.asdict(cl_a(*vals_a))) is cl_a 
Example #9
Source File: test_config.py    From corrscope with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def test_unit_suffix():
    class Foo(DumpableAttrs):
        xs: int = with_units("xs")
        ys: int = with_units("ys", default=2)
        no_unit: int = 3

    # Assert class constructor works.
    foo = Foo(1, 2, 3)
    foo_default = Foo(1)

    # Assert units work.
    foo_fields = attr.fields(Foo)
    assert get_units(foo_fields.xs) == " xs"
    assert get_units(foo_fields.ys) == " ys"
    assert get_units(foo_fields.no_unit) == ""


# Dataclass dump testing 
Example #10
Source File: _environ_config.py    From environ-config with Apache License 2.0 6 votes vote down vote up
def _to_config(config_cls, default_get, environ, prefix):
    vals = {}
    for a in attr.fields(config_cls):
        try:
            ce = a.metadata[CNF_KEY]
        except KeyError:
            continue
        if ce.sub_cls is None:
            get = ce.callback or default_get
            val = get(environ, a.metadata, prefix, a.name)
        else:
            val = _to_config(
                ce.sub_cls,
                default_get,
                environ,
                prefix + ((a.name if prefix else a.name),),
            )

        vals[a.name] = val
    return config_cls(**vals) 
Example #11
Source File: _environ_config.py    From requirementslib with MIT License 6 votes vote down vote up
def _to_config(config_cls, default_get, environ, prefix):
    vals = {}
    for a in attr.fields(config_cls):
        try:
            ce = a.metadata[CNF_KEY]
        except KeyError:
            continue
        if ce.sub_cls is None:
            get = ce.callback or default_get
            val = get(environ, a.metadata, prefix, a.name)
        else:
            val = _to_config(
                ce.sub_cls, default_get, environ,
                prefix + ((a.name if prefix else a.name),)
            )

        vals[a.name] = val
    return config_cls(**vals) 
Example #12
Source File: requirements.py    From requirementslib with MIT License 6 votes vote down vote up
def from_pipfile(cls, name, pipfile):
        # type: (S, TPIPFILE) -> NamedRequirement
        creation_args = {}  # type: TPIPFILE
        if hasattr(pipfile, "keys"):
            attr_fields = [field.name for field in attr.fields(cls)]
            creation_args = {
                k: v for k, v in pipfile.items() if k in attr_fields
            }  # type: ignore
        creation_args["name"] = name
        version = get_version(pipfile)  # type: Optional[STRING_TYPE]
        extras = creation_args.get("extras", None)
        creation_args["version"] = version  # type: ignore
        req = init_requirement("{0}{1}".format(name, version))
        if req and extras and req.extras and isinstance(req.extras, tuple):
            if isinstance(extras, six.string_types):
                req.extras = (extras) + tuple(["{0}".format(xtra) for xtra in req.extras])
            elif isinstance(extras, (tuple, list)):
                req.extras += tuple(extras)
        creation_args["req"] = req
        return cls(**creation_args)  # type: ignore 
Example #13
Source File: test_config.py    From corrscope with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def test_load_post_init():
    """ yaml.load() does not natively call __init__.
    So DumpableAttrs modifies __setstate__ to call __attrs_post_init__. """

    class Foo(DumpableAttrs):
        foo: int

        def __attrs_post_init__(self):
            self.foo = 99

    s = """\
!Foo
foo: 0
"""
    assert yaml.load(s) == Foo(99)


# Test handling of _prefix fields, or init=False 
Example #14
Source File: test_annotations.py    From attrs with MIT License 6 votes vote down vote up
def test_typing_annotations(self):
        """
        Sets the `Attribute.type` attr from typing annotations.
        """

        @attr.s
        class C:
            x: typing.List[int] = attr.ib()
            y = attr.ib(type=typing.Optional[str])

        assert typing.List[int] is attr.fields(C).x.type
        assert typing.Optional[str] is attr.fields(C).y.type
        assert C.__init__.__annotations__ == {
            "x": typing.List[int],
            "y": typing.Optional[str],
            "return": None,
        } 
Example #15
Source File: test_make.py    From attrs with MIT License 6 votes vote down vote up
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 #16
Source File: test_make.py    From attrs with MIT License 6 votes vote down vote up
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 #17
Source File: test_funcs.py    From attrs with MIT License 6 votes vote down vote up
def test_recurse_property(self, cls, tuple_class):
        """
        Property tests for recursive astuple.
        """
        obj = cls()
        obj_tuple = astuple(obj, tuple_factory=tuple_class)

        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])

        assert_proper_tuple_class(obj, obj_tuple) 
Example #18
Source File: test_funcs.py    From attrs with MIT License 6 votes vote down vote up
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}

        with pytest.deprecated_call():
            changed = assoc(original, **change_dict)

        for k, v in change_dict.items():
            assert getattr(changed, k) == v 
Example #19
Source File: test_funcs.py    From attrs with MIT License 6 votes vote down vote up
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)))
        # We pay special attention to private attributes, they should behave
        # like in `__init__`.
        change_dict = {
            name.replace("_", ""): data.draw(st.integers())
            for name in chosen_names
        }
        changed = evolve(original, **change_dict)
        for name in chosen_names:
            assert getattr(changed, name) == change_dict[name.replace("_", "")] 
Example #20
Source File: strategy.py    From poker with MIT License 6 votes vote down vote up
def __init__(self, strategy, source="<string>"):
        self._config = ConfigParser(default_section="strategy", interpolation=None)
        self._config.read_string(strategy, source)

        self._situations = dict()
        for name in self._config.sections():
            # configparser set non-specified values to '', we want default to None
            attr_names = [a.name for a in attr.fields(_Situation)]
            values = dict.fromkeys(attr_names, None)
            for key, val in self._config[name].items():
                # filter out fields not implemented, otherwise it would
                # cause TypeError for _Situation constructor
                if (not val) or (key not in attr_names):
                    continue
                elif key in _POSITIONS:
                    values[key] = Range(val)
                else:
                    values[key] = val
            self._situations[name] = _Situation(**values)

        self._tuple = tuple(self._situations.values()) 
Example #21
Source File: markers.py    From requirementslib with MIT License 6 votes vote down vote up
def from_pipfile(cls, name, pipfile):
        attr_fields = [field.name for field in attr.fields(cls)]
        found_keys = [k for k in pipfile.keys() if k in attr_fields]
        marker_strings = ["{0} {1}".format(k, pipfile[k]) for k in found_keys]
        if pipfile.get("markers"):
            marker_strings.append(pipfile.get("markers"))
        markers = set()
        for marker in marker_strings:
            markers.add(marker)
        combined_marker = None
        try:
            combined_marker = cls.make_marker(" and ".join(sorted(markers)))
        except RequirementError:
            pass
        else:
            return combined_marker 
Example #22
Source File: test_config.py    From corrscope with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def test_dump_load_ignored():
    """ Ensure loading `xx=Ignored` works.
    Does not check constructor `Config(xx=1)`.
    """

    class Config(DumpableAttrs):
        xx = Ignored

    # Test dumping
    assert len(attr.fields(Config)) == 0
    cfg = Config()
    s = yaml.dump(cfg)
    assert (
        s
        == """\
!Config {}
"""
    )
    assert yaml.load(s) == cfg

    # Test loading
    s = """\
!Config
xx: 1
"""
    assert yaml.load(s) == Config() 
Example #23
Source File: test_funcs.py    From attrs with MIT License 5 votes vote down vote up
def test_recurse_property(self, cls, dict_class):
        """
        Property tests for recursive asdict.
        """
        obj = cls()
        obj_dict = asdict(obj, dict_factory=dict_class)

        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[field.name][key]
                            )

        assert_proper_dict_class(obj, obj_dict) 
Example #24
Source File: test_annotations.py    From attrs with MIT License 5 votes vote down vote up
def test_only_attrs_annotations_collected(self):
        """
        Annotations that aren't set to an attr.ib are ignored.
        """

        @attr.s
        class C:
            x: typing.List[int] = attr.ib()
            y: int

        assert 1 == len(attr.fields(C))
        assert C.__init__.__annotations__ == {
            "x": typing.List[int],
            "return": None,
        } 
Example #25
Source File: test_filters.py    From attrs with MIT License 5 votes vote down vote up
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 #26
Source File: test_filters.py    From attrs with MIT License 5 votes vote down vote up
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 #27
Source File: test_filters.py    From attrs with MIT License 5 votes vote down vote up
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 #28
Source File: test_config.py    From corrscope with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def test_exclude_dump():
    """
    Test that the exclude="" parameter can remove fields from always_dump="*".
    """

    class Config(DumpableAttrs, always_dump="*", exclude="b"):
        a: int = 1
        b: int = 2

    s = yaml.dump(Config())
    assert (
        s
        == """\
!Config
a: 1
"""
    )

    class Special(Config, exclude="d"):
        c: int = 3
        d: int = 4

    s = yaml.dump(Special())
    assert (
        s
        == """\
!Special
a: 1
c: 3
"""
    )


# Dataclass load testing 
Example #29
Source File: test_config.py    From corrscope with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def test_ignore_unrecognized_fields():
    """Ensure unrecognized fields yield warning, not exception."""

    class Foo(DumpableAttrs):
        foo: int

    s = """\
!Foo
foo: 1
bar: 2
"""
    with pytest.warns(CorrWarning):
        assert yaml.load(s) == Foo(1) 
Example #30
Source File: test_functional.py    From attrs with MIT License 5 votes vote down vote up
def test_fields(self, cls):
        """
        `attr.fields` works.
        """
        assert (
            Attribute(
                name="x",
                default=foo,
                validator=None,
                repr=True,
                cmp=None,
                eq=True,
                order=True,
                hash=None,
                init=True,
                inherited=False,
            ),
            Attribute(
                name="y",
                default=attr.Factory(list),
                validator=None,
                repr=True,
                cmp=None,
                eq=True,
                order=True,
                hash=None,
                init=True,
                inherited=False,
            ),
        ) == attr.fields(cls)