diff --git a/attr/_make.py b/attr/_make.py index 2f8f0ad4..72183e78 100644 --- a/attr/_make.py +++ b/attr/_make.py @@ -94,7 +94,7 @@ def attr(default=NOTHING, validator=None, def _transform_attrs(cl, these): """ 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. """ @@ -113,11 +113,11 @@ def _transform_attrs(cl, these): for name, ca in iteritems(these)] - cl.__attrs_attrs__ = super_cls + [ + cl.__attrs_attrs__ = tuple(super_cls + [ Attribute.from_counting_attr(name=attr_name, ca=ca) for attr_name, ca in sorted(ca_list, key=lambda e: e[1].counter) - ] + ]) had_default = False for a in cl.__attrs_attrs__: @@ -357,7 +357,7 @@ def _add_init(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. :type cl: type @@ -365,7 +365,7 @@ def fields(cl): :raise TypeError: If *cl* is not a 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): raise TypeError("Passed object must be a class.") diff --git a/docs/api.rst b/docs/api.rst index 084b3cec..4abc902c 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -56,7 +56,7 @@ Core Instances of this class are frequently used for introspection purposes like: - 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. .. warning:: @@ -119,7 +119,7 @@ Helpers ... x = attr.ib() ... y = attr.ib() >>> 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 diff --git a/tests/test_dark_magic.py b/tests/test_dark_magic.py index 9c80588b..a57a36be 100644 --- a/tests/test_dark_magic.py +++ b/tests/test_dark_magic.py @@ -44,12 +44,12 @@ class TestDarkMagic(object): """ `attr.fields` works. """ - assert [ + assert ( Attribute(name="x", default=foo, validator=None, repr=True, cmp=True, hash=True, init=True), Attribute(name="y", default=attr.Factory(list), validator=None, repr=True, cmp=True, hash=True, init=True), - ] == attr.fields(C2) + ) == attr.fields(C2) def test_asdict(self): """ @@ -87,12 +87,12 @@ class TestDarkMagic(object): `attr.make_class` works. """ PC = attr.make_class("PC", ["a", "b"]) - assert [ + assert ( Attribute(name="a", default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True), Attribute(name="b", default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True), - ] == attr.fields(PC) + ) == attr.fields(PC) def test_subclassing(self): """ diff --git a/tests/test_make.py b/tests/test_make.py index d66fc993..5c824103 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -65,7 +65,7 @@ class TestTransformAttrs(object): _transform_attrs(C, None) - assert [] == C.__attrs_attrs__ + assert () == C.__attrs_attrs__ @pytest.mark.parametrize("attribute", [ "z", @@ -107,9 +107,9 @@ class TestTransformAttrs(object): y = attr() _transform_attrs(C, {"x": attr()}) - assert [ + assert ( simple_attr("x"), - ] == C.__attrs_attrs__ + ) == C.__attrs_attrs__ assert isinstance(C.y, _CountingAttr) def test_recurse(self): @@ -129,10 +129,10 @@ class TestTransformAttrs(object): _transform_attrs(D, None) - assert [ + assert ( simple_attr("x"), simple_attr("y"), - ] == D.__attrs_attrs__ + ) == D.__attrs_attrs__ class TestAttributes(object):