Make __attrs_attrs__ a tuple

Having a mutable and rather heavy data structure for something that is supposed
to be immutable doesn't seem to make sense.
This commit is contained in:
Hynek Schlawack 2015-03-23 09:16:43 +01:00
parent 46cbd75411
commit d964845899
4 changed files with 16 additions and 16 deletions

View File

@ -94,7 +94,7 @@ def attr(default=NOTHING, validator=None,
def _transform_attrs(cl, these): def _transform_attrs(cl, these):
""" """
Transforms all `_CountingAttr`s on a class into `Attribute`s and saves the Transforms all `_CountingAttr`s on a class into `Attribute`s and saves the
list in `__attrs_attrs__`. list as a tuple in `__attrs_attrs__`.
If *these* is passed, use that and don't look for them on the class. If *these* is passed, use that and don't look for them on the class.
""" """
@ -113,11 +113,11 @@ def _transform_attrs(cl, these):
for name, ca for name, ca
in iteritems(these)] in iteritems(these)]
cl.__attrs_attrs__ = super_cls + [ cl.__attrs_attrs__ = tuple(super_cls + [
Attribute.from_counting_attr(name=attr_name, ca=ca) Attribute.from_counting_attr(name=attr_name, ca=ca)
for attr_name, ca for attr_name, ca
in sorted(ca_list, key=lambda e: e[1].counter) in sorted(ca_list, key=lambda e: e[1].counter)
] ])
had_default = False had_default = False
for a in cl.__attrs_attrs__: for a in cl.__attrs_attrs__:
@ -357,7 +357,7 @@ def _add_init(cl):
def fields(cl): def fields(cl):
""" """
Returns the list of ``attrs`` attributes for a class. Returns the tuple of ``attrs`` attributes for a class.
:param cl: Class to introspect. :param cl: Class to introspect.
:type cl: type :type cl: type
@ -365,7 +365,7 @@ def fields(cl):
:raise TypeError: If *cl* is not a class. :raise TypeError: If *cl* is not a class.
:raise ValueError: If *cl* is not an ``attrs`` class. :raise ValueError: If *cl* is not an ``attrs`` class.
:rtype: :class:`list` of :class:`attr.Attribute` :rtype: tuple of :class:`attr.Attribute`
""" """
if not isinstance(cl, type): if not isinstance(cl, type):
raise TypeError("Passed object must be a class.") raise TypeError("Passed object must be a class.")

View File

@ -56,7 +56,7 @@ Core
Instances of this class are frequently used for introspection purposes like: Instances of this class are frequently used for introspection purposes like:
- Class attributes on ``attrs``-decorated classes *after* ``@attr.s`` has been applied. - Class attributes on ``attrs``-decorated classes *after* ``@attr.s`` has been applied.
- :func:`fields` returns a list of them. - :func:`fields` returns a tuple of them.
- Validators get them passed as the first argument. - Validators get them passed as the first argument.
.. warning:: .. warning::
@ -119,7 +119,7 @@ Helpers
... x = attr.ib() ... x = attr.ib()
... y = attr.ib() ... y = attr.ib()
>>> attr.fields(C) >>> attr.fields(C)
[Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True), Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True)] (Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True), Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True))
.. autofunction:: attr.has .. autofunction:: attr.has

View File

@ -44,12 +44,12 @@ class TestDarkMagic(object):
""" """
`attr.fields` works. `attr.fields` works.
""" """
assert [ assert (
Attribute(name="x", default=foo, validator=None, Attribute(name="x", default=foo, validator=None,
repr=True, cmp=True, hash=True, init=True), repr=True, cmp=True, hash=True, init=True),
Attribute(name="y", default=attr.Factory(list), validator=None, Attribute(name="y", default=attr.Factory(list), validator=None,
repr=True, cmp=True, hash=True, init=True), repr=True, cmp=True, hash=True, init=True),
] == attr.fields(C2) ) == attr.fields(C2)
def test_asdict(self): def test_asdict(self):
""" """
@ -87,12 +87,12 @@ class TestDarkMagic(object):
`attr.make_class` works. `attr.make_class` works.
""" """
PC = attr.make_class("PC", ["a", "b"]) PC = attr.make_class("PC", ["a", "b"])
assert [ assert (
Attribute(name="a", default=NOTHING, validator=None, Attribute(name="a", default=NOTHING, validator=None,
repr=True, cmp=True, hash=True, init=True), repr=True, cmp=True, hash=True, init=True),
Attribute(name="b", default=NOTHING, validator=None, Attribute(name="b", default=NOTHING, validator=None,
repr=True, cmp=True, hash=True, init=True), repr=True, cmp=True, hash=True, init=True),
] == attr.fields(PC) ) == attr.fields(PC)
def test_subclassing(self): def test_subclassing(self):
""" """

View File

@ -65,7 +65,7 @@ class TestTransformAttrs(object):
_transform_attrs(C, None) _transform_attrs(C, None)
assert [] == C.__attrs_attrs__ assert () == C.__attrs_attrs__
@pytest.mark.parametrize("attribute", [ @pytest.mark.parametrize("attribute", [
"z", "z",
@ -107,9 +107,9 @@ class TestTransformAttrs(object):
y = attr() y = attr()
_transform_attrs(C, {"x": attr()}) _transform_attrs(C, {"x": attr()})
assert [ assert (
simple_attr("x"), simple_attr("x"),
] == C.__attrs_attrs__ ) == C.__attrs_attrs__
assert isinstance(C.y, _CountingAttr) assert isinstance(C.y, _CountingAttr)
def test_recurse(self): def test_recurse(self):
@ -129,10 +129,10 @@ class TestTransformAttrs(object):
_transform_attrs(D, None) _transform_attrs(D, None)
assert [ assert (
simple_attr("x"), simple_attr("x"),
simple_attr("y"), simple_attr("y"),
] == D.__attrs_attrs__ ) == D.__attrs_attrs__
class TestAttributes(object): class TestAttributes(object):