Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BF: reverse MRO as well if we are reversing the attrs at the end #299

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 8 additions & 10 deletions src/attr/_make.py
Expand Up @@ -279,27 +279,25 @@ def _transform_attrs(cls, these, auto_attribs):
# redefinitions deeper in the hierarchy.
super_attrs = []
taken_attr_names = {a.name: a for a in non_super_attrs}
for super_cls in cls.__mro__[1:-1]:
for super_cls in cls.__mro__[1:]:

This comment was marked as spam.

sub_attrs = getattr(super_cls, "__attrs_attrs__", None)
if sub_attrs is not None:
# We iterate over sub_attrs backwards so we can reverse the whole
# list in the end and get all attributes in the order they have
# been defined.
for a in reversed(sub_attrs):
# We iterate over sub_attrs forward and populate them as soon
# as we see it
for a in sub_attrs:
prev_a = taken_attr_names.get(a.name)
if prev_a is None:
super_attrs.append(a)
taken_attr_names[a.name] = a
elif prev_a == a:
# This happens thru multiple inheritance. We don't want
# This happens through multiple inheritance. We don't want
# to favor attributes that are further down in the tree
# so we move them to the back.
super_attrs.remove(a)
super_attrs.append(a)
# so we ... skip them altogether
continue

# Now reverse the list, such that the attributes are sorted by *descending*
# age. IOW: the oldest attribute definition is at the head of the list.
super_attrs.reverse()
# super_attrs.reverse()

attr_names = [a.name for a in super_attrs + non_super_attrs]

Expand Down
29 changes: 29 additions & 0 deletions tests/test_dark_magic.py
Expand Up @@ -380,3 +380,32 @@ class E(D):
z = attr.ib(default=4)

assert "E(c=100, b=23, a=42, x=2, d=3.14, y=3, z=4)" == repr(E())
assert "E(c=100, b=23, a=42, x=2, d=3.14, y=3, z=4)" == repr(E(100, 23, 42, 2, 3.14, 3, 4))

def test_multiple_inheritance2(self):

@attr.s
class A(object):
a = attr.ib()

@attr.s
class B(A):
b = attr.ib()

@attr.s
class C(object):
c = attr.ib()

@attr.s
class D(B, C):
d = attr.ib()

assert "D(a=1, b=2, c=3, d=4)" == repr(D(1, 2, 3, 4))

# overload c
@attr.s
class D2(B, C):
d = attr.ib()
c = attr.ib()

assert "D2(a=1, b=2, d=3, c=4)" == repr(D2(1, 2, 3, 4))
4 changes: 2 additions & 2 deletions tests/test_make.py
Expand Up @@ -240,8 +240,8 @@ class E(D, C):
e2 = attr.ib(default="e2")

assert (
"E(a1='a1', a2='a2', b1='b1', b2='b2', c1='c1', c2='c2', d1='d1', "
"d2='d2', e1='e1', e2='e2')"
"E(a1='a1', a2='a2', d1='d1', d2='d2', b1='b1', b2='b2', "
"c1='c1', c2='c2', e1='e1', e2='e2')"

This comment was marked as spam.

This comment was marked as spam.

) == repr(E())


Expand Down