Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions documentation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ Python 2 and 3.
pass
MyClass = add_metaclass(Meta)(MyClass)

This technique works by re-building MyClass from the indicated metaclass,
but in the rare case where the parent has a metaclass that is a
superclass of the metaclass used with the decorator, this approach will
fail with a TypeError. See `issue 127
<https://github.com/benjaminp/six/issues/127>`_ for details.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I have wondered about this myself. I've never actually encountered the scenario directly but I had considered it. This is worth warning about.



Binary and text data
>>>>>>>>>>>>>>>>>>>>
Expand Down
24 changes: 24 additions & 0 deletions test_six.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,30 @@ class MySlotsWeakref(object):
assert type(MySlotsWeakref) is Meta


def test_add_metaclass_child_meta():
"""
Capture the known failure in the rare case where the parent
has a metaclass that is a superclass of the metaclass used
with the decorator (#127).
"""
class MetaA(type): pass
class MetaB(type): pass

class A(object): pass
A = six.add_metaclass(MetaA)(A)

class B(object): pass
B = six.add_metaclass(MetaB)(B)

class MetaC(MetaA, MetaB): pass

with py.test.raises(TypeError) as exc:
class C(A, B): pass
C = six.add_metaclass(MetaC)(C)

assert 'metaclass conflict' in str(exc.value)


@py.test.mark.skipif("sys.version_info[:2] < (2, 7) or sys.version_info[:2] in ((3, 0), (3, 1))")
def test_assertCountEqual():
class TestAssertCountEqual(unittest.TestCase):
Expand Down