summaryrefslogtreecommitdiff
path: root/src/zope/interface
diff options
context:
space:
mode:
Diffstat (limited to 'src/zope/interface')
-rw-r--r--src/zope/interface/declarations.py130
-rw-r--r--src/zope/interface/interface.py22
-rw-r--r--src/zope/interface/tests/test_declarations.py307
-rw-r--r--src/zope/interface/tests/test_exceptions.py10
-rw-r--r--src/zope/interface/tests/test_ro.py20
5 files changed, 413 insertions, 76 deletions
diff --git a/src/zope/interface/declarations.py b/src/zope/interface/declarations.py
index 45d2998..935b026 100644
--- a/src/zope/interface/declarations.py
+++ b/src/zope/interface/declarations.py
@@ -144,6 +144,43 @@ class Declaration(Specification):
])
return interfaces + (implemented_by_cls,)
+ @staticmethod
+ def _argument_names_for_repr(interfaces):
+ # These don't actually have to be interfaces, they could be other
+ # Specification objects like Implements. Also, the first
+ # one is typically/nominally the cls.
+ ordered_names = []
+ names = set()
+ for iface in interfaces:
+ duplicate_transform = repr
+ if isinstance(iface, InterfaceClass):
+ # Special case to get 'foo.bar.IFace'
+ # instead of '<InterfaceClass foo.bar.IFace>'
+ this_name = iface.__name__
+ duplicate_transform = str
+ elif isinstance(iface, type):
+ # Likewise for types. (Ignoring legacy old-style
+ # classes.)
+ this_name = iface.__name__
+ duplicate_transform = _implements_name
+ elif (isinstance(iface, Implements)
+ and not iface.declared
+ and iface.inherit in interfaces):
+ # If nothing is declared, there's no need to even print this;
+ # it would just show as ``classImplements(Class)``, and the
+ # ``Class`` has typically already.
+ continue
+ else:
+ this_name = repr(iface)
+
+ already_seen = this_name in names
+ names.add(this_name)
+ if already_seen:
+ this_name = duplicate_transform(iface)
+
+ ordered_names.append(this_name)
+ return ', '.join(ordered_names)
+
class _ImmutableDeclaration(Declaration):
# A Declaration that is immutable. Used as a singleton to
@@ -286,7 +323,14 @@ class Implements(NameAndModuleComparisonMixin,
return super(Implements, self).changed(originally_changed)
def __repr__(self):
- return '<implementedBy %s>' % (self.__name__)
+ if self.inherit:
+ name = getattr(self.inherit, '__name__', None) or _implements_name(self.inherit)
+ else:
+ name = self.__name__
+ declared_names = self._argument_names_for_repr(self.declared)
+ if declared_names:
+ declared_names = ', ' + declared_names
+ return 'classImplements(%s%s)' % (name, declared_names)
def __reduce__(self):
return implementedBy, (self.inherit, )
@@ -762,15 +806,44 @@ class Provides(Declaration): # Really named ProvidesClass
self._cls = cls
Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, cls))
+ # Added to by ``moduleProvides``, et al
+ _v_module_names = ()
+
def __repr__(self):
- return "<%s.%s for instances of %s providing %s>" % (
- self.__class__.__module__,
- self.__class__.__name__,
- self._cls,
- self.__args[1:],
+ # The typical way to create instances of this
+ # object is via calling ``directlyProvides(...)`` or ``alsoProvides()``,
+ # but that's not the only way. Proxies, for example,
+ # directly use the ``Provides(...)`` function (which is the
+ # more generic method, and what we pickle as). We're after the most
+ # readable, useful repr in the common case, so we use the most
+ # common name.
+ #
+ # We also cooperate with ``moduleProvides`` to attempt to do the
+ # right thing for that API. See it for details.
+ function_name = 'directlyProvides'
+ if self._cls is ModuleType and self._v_module_names:
+ # See notes in ``moduleProvides``/``directlyProvides``
+ providing_on_module = True
+ interfaces = self.__args[1:]
+ else:
+ providing_on_module = False
+ interfaces = (self._cls,) + self.__bases__
+ ordered_names = self._argument_names_for_repr(interfaces)
+ if providing_on_module:
+ mod_names = self._v_module_names
+ if len(mod_names) == 1:
+ mod_names = "sys.modules[%r]" % mod_names[0]
+ ordered_names = (
+ '%s, ' % (mod_names,)
+ ) + ordered_names
+ return "%s(%s)" % (
+ function_name,
+ ordered_names,
)
def __reduce__(self):
+ # This reduces to the Provides *function*, not
+ # this class.
return Provides, self.__args
__module__ = 'zope.interface'
@@ -841,7 +914,11 @@ def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin
# that provides some extra caching
object.__provides__ = ClassProvides(object, cls, *interfaces)
else:
- object.__provides__ = Provides(cls, *interfaces)
+ provides = object.__provides__ = Provides(cls, *interfaces)
+ # See notes in ``moduleProvides``.
+ if issubclass(cls, ModuleType) and hasattr(object, '__name__'):
+ provides._v_module_names += (object.__name__,)
+
def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin
@@ -907,11 +984,19 @@ class ClassProvides(Declaration, ClassProvidesBase):
Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, metacls))
def __repr__(self):
- return "<%s.%s for %s>" % (
- self.__class__.__module__,
- self.__class__.__name__,
- self._cls,
- )
+ # There are two common ways to get instances of this object:
+ # The most interesting way is calling ``@provider(..)`` as a decorator
+ # of a class; this is the same as calling ``directlyProvides(cls, ...)``.
+ #
+ # The other way is by default: anything that invokes ``implementedBy(x)``
+ # will wind up putting an instance in ``type(x).__provides__``; this includes
+ # the ``@implementer(...)`` decorator. Those instances won't have any
+ # interfaces.
+ #
+ # Thus, as our repr, we go with the ``directlyProvides()`` syntax.
+ interfaces = (self._cls, ) + self.__args[2:]
+ ordered_names = self._argument_names_for_repr(interfaces)
+ return "directlyProvides(%s)" % (ordered_names,)
def __reduce__(self):
return self.__class__, self.__args
@@ -1026,7 +1111,7 @@ def moduleProvides(*interfaces):
This function is provided for convenience. It provides a more convenient
way to call directlyProvides. For example::
- moduleImplements(I1)
+ moduleProvides(I1)
is equivalent to::
@@ -1035,7 +1120,7 @@ def moduleProvides(*interfaces):
frame = sys._getframe(1) # pylint:disable=protected-access
locals = frame.f_locals # pylint:disable=redefined-builtin
- # Try to make sure we were called from a class def
+ # Try to make sure we were called from a module body
if (locals is not frame.f_globals) or ('__name__' not in locals):
raise TypeError(
"moduleProvides can only be used from a module definition.")
@@ -1044,8 +1129,21 @@ def moduleProvides(*interfaces):
raise TypeError(
"moduleProvides can only be used once in a module definition.")
- locals["__provides__"] = Provides(ModuleType,
- *_normalizeargs(interfaces))
+ # Note: This is cached based on the key ``(ModuleType, *interfaces)``;
+ # One consequence is that any module that provides the same interfaces
+ # gets the same ``__repr__``, meaning that you can't tell what module
+ # such a declaration came from. Adding the module name to ``_v_module_names``
+ # attempts to correct for this; it works in some common situations, but fails
+ # (1) after pickling (the data is lost) and (2) if declarations are
+ # actually shared and (3) if the alternate spelling of ``directlyProvides()``
+ # is used. Problem (3) is fixed by cooperating with ``directlyProvides``
+ # to maintain this information, and problem (2) is worked around by
+ # printing all the names, but (1) is unsolvable without introducing
+ # new classes or changing the stored data...but it doesn't actually matter,
+ # because ``ModuleType`` can't be pickled!
+ p = locals["__provides__"] = Provides(ModuleType,
+ *_normalizeargs(interfaces))
+ p._v_module_names += (locals['__name__'],)
##############################################################################
diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py
index 53049e2..7447641 100644
--- a/src/zope/interface/interface.py
+++ b/src/zope/interface/interface.py
@@ -890,10 +890,10 @@ class InterfaceClass(_InterfaceClassBase):
try:
invariant(obj)
except Invalid as error:
- if errors is not None:
- errors.append(error)
- else:
- raise
+ if errors is not None:
+ errors.append(error)
+ else:
+ raise
if errors:
raise Invalid(errors)
@@ -925,18 +925,22 @@ class InterfaceClass(_InterfaceClassBase):
keys.update(base.getDirectTaggedValueTags())
return keys
- def __repr__(self): # pragma: no cover
+ def __repr__(self):
try:
return self._v_repr
except AttributeError:
- name = self.__name__
- m = self.__ibmodule__
- if m:
- name = '%s.%s' % (m, name)
+ name = str(self)
r = "<%s %s>" % (self.__class__.__name__, name)
self._v_repr = r # pylint:disable=attribute-defined-outside-init
return r
+ def __str__(self):
+ name = self.__name__
+ m = self.__ibmodule__
+ if m:
+ name = '%s.%s' % (m, name)
+ return name
+
def _call_conform(self, conform):
try:
return conform(self)
diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py
index 0c21b8c..8efe2d8 100644
--- a/src/zope/interface/tests/test_declarations.py
+++ b/src/zope/interface/tests/test_declarations.py
@@ -384,7 +384,7 @@ class TestImplements(NameAndModuleComparisonTestsMixin,
def test___repr__(self):
impl = self._makeOne()
impl.__name__ = 'Testing'
- self.assertEqual(repr(impl), '<implementedBy Testing>')
+ self.assertEqual(repr(impl), 'classImplements(Testing)')
def test___reduce__(self):
from zope.interface.declarations import implementedBy
@@ -544,7 +544,6 @@ class Test_implementedByFallback(unittest.TestCase):
def test_builtins_added_to_cache(self):
from zope.interface import declarations
from zope.interface.declarations import Implements
- from zope.interface._compat import _BUILTINS
with _MonkeyDict(declarations,
'BuiltinImplementationSpecifications') as specs:
self.assertEqual(list(self._callFUT(tuple)), [])
@@ -554,8 +553,8 @@ class Test_implementedByFallback(unittest.TestCase):
spec = specs[typ]
self.assertIsInstance(spec, Implements)
self.assertEqual(repr(spec),
- '<implementedBy %s.%s>'
- % (_BUILTINS, typ.__name__))
+ 'classImplements(%s)'
+ % (typ.__name__,))
def test_builtins_w_existing_cache(self):
from zope.interface import declarations
@@ -1304,25 +1303,6 @@ class ProvidesClassTests(unittest.TestCase):
return foo.__provides__
self.assertRaises(AttributeError, _test)
- def test__repr__(self):
- from zope.interface.interface import InterfaceClass
- IFoo = InterfaceClass("IFoo")
- assert IFoo.__name__ == 'IFoo'
- assert IFoo.__module__ == __name__
- assert repr(IFoo) == '<InterfaceClass %s.IFoo>' % (__name__,)
-
- IBar = InterfaceClass("IBar")
-
- inst = self._makeOne(type(self), IFoo, IBar)
- self.assertEqual(
- repr(inst),
- "<zope.interface.Provides "
- "for instances of <class '%(mod)s.ProvidesClassTests'> "
- "providing (<InterfaceClass %(mod)s.IFoo>, <InterfaceClass %(mod)s.IBar>)>" % {
- 'mod': __name__,
- }
- )
-
class ProvidesClassStrictTests(ProvidesClassTests):
# Tests that require the strict C3 resolution order.
@@ -1334,9 +1314,6 @@ class ProvidesClassStrictTests(ProvidesClassTests):
return ProvidesClass._do_calculate_ro(self, base_mros=base_mros, strict=True)
return StrictProvides
- def test__repr__(self):
- self.skipTest("Not useful for the subclass.")
-
def test_overlapping_interfaces_corrected(self):
# Giving Provides(cls, IFace), where IFace is already
# provided by cls, doesn't produce invalid resolution orders.
@@ -1361,6 +1338,195 @@ class ProvidesClassStrictTests(ProvidesClassTests):
))
+class TestProvidesClassRepr(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ProvidesClass
+ return ProvidesClass
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test__repr__(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ assert IFoo.__name__ == 'IFoo'
+ assert IFoo.__module__ == __name__
+ assert repr(IFoo) == '<InterfaceClass %s.IFoo>' % (__name__,)
+
+ IBar = InterfaceClass("IBar")
+
+ inst = self._makeOne(type(self), IFoo, IBar)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestProvidesClassRepr, IFoo, IBar)"
+ )
+
+ def test__repr__module_provides_typical_use(self):
+ # as created through a ``moduleProvides()`` statement
+ # in a module body
+ from zope.interface.tests import dummy
+ provides = dummy.__provides__ # pylint:disable=no-member
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(sys.modules['zope.interface.tests.dummy'], IDummyModule)"
+ )
+
+ def test__repr__module_after_pickle(self):
+ # It doesn't matter, these objects can't be pickled.
+ import pickle
+ from zope.interface.tests import dummy
+ provides = dummy.__provides__ # pylint:disable=no-member
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.assertRaises(pickle.PicklingError):
+ pickle.dumps(provides, proto)
+
+ def test__repr__directlyProvides_module(self):
+ import sys
+ from zope.interface.tests import dummy
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import alsoProvides
+ from zope.interface.interface import InterfaceClass
+
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+
+ orig_provides = dummy.__provides__ # pylint:disable=no-member
+ del dummy.__provides__ # pylint:disable=no-member
+ self.addCleanup(setattr, dummy, '__provides__', orig_provides)
+
+ directlyProvides(dummy, IFoo)
+ provides = dummy.__provides__ # pylint:disable=no-member
+
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(sys.modules['zope.interface.tests.dummy'], IFoo)"
+ )
+
+ alsoProvides(dummy, IBar)
+ provides = dummy.__provides__ # pylint:disable=no-member
+
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(sys.modules['zope.interface.tests.dummy'], IFoo, IBar)"
+ )
+
+ # If we make this module also provide IFoo and IBar, then the repr
+ # lists both names.
+ my_module = sys.modules[__name__]
+ assert not hasattr(my_module, '__provides__')
+
+ directlyProvides(my_module, IFoo, IBar)
+ self.addCleanup(delattr, my_module, '__provides__')
+ self.assertIs(my_module.__provides__, provides)
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(('zope.interface.tests.dummy', "
+ "'zope.interface.tests.test_declarations'), "
+ "IFoo, IBar)"
+ )
+
+ def test__repr__module_provides_cached_shared(self):
+ from zope.interface.interface import InterfaceClass
+ from zope.interface.declarations import ModuleType
+ IFoo = InterfaceClass("IFoo")
+
+ inst = self._makeOne(ModuleType, IFoo)
+ inst._v_module_names += ('some.module',)
+ inst._v_module_names += ('another.module',)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(('some.module', 'another.module'), IFoo)"
+ )
+
+ def test__repr__duplicate_names(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo", __module__='mod1')
+ IFoo2 = InterfaceClass("IFoo", __module__='mod2')
+ IBaz = InterfaceClass("IBaz")
+
+ inst = self._makeOne(type(self), IFoo, IBaz, IFoo2)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestProvidesClassRepr, IFoo, IBaz, mod2.IFoo)"
+ )
+
+ def test__repr__implementedBy_in_interfaces(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ class IFoo(Interface):
+ "Does nothing"
+
+ class Bar(object):
+ "Does nothing"
+
+ impl = implementedBy(type(self))
+
+ inst = self._makeOne(Bar, IFoo, impl)
+ self.assertEqual(
+ repr(inst),
+ 'directlyProvides(Bar, IFoo, classImplements(TestProvidesClassRepr))'
+ )
+
+ def test__repr__empty_interfaces(self):
+ inst = self._makeOne(type(self))
+ self.assertEqual(
+ repr(inst),
+ 'directlyProvides(TestProvidesClassRepr)',
+ )
+
+ def test__repr__non_class(self):
+ class Object(object):
+ __bases__ = ()
+ __str__ = lambda _: self.fail("Should not call str")
+
+ def __repr__(self):
+ return '<Object>'
+ inst = self._makeOne(Object())
+ self.assertEqual(
+ repr(inst),
+ 'directlyProvides(<Object>)',
+ )
+
+ def test__repr__providedBy_from_class(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import providedBy
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ inst = providedBy(Foo())
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(Foo, IFoo)'
+ )
+
+ def test__repr__providedBy_alsoProvides(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import providedBy
+ from zope.interface.declarations import alsoProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ foo = Foo()
+ alsoProvides(foo, IBar)
+
+ inst = providedBy(foo)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(Foo, IBar, classImplements(Foo, IFoo))"
+ )
+
+
+
class Test_Provides(unittest.TestCase):
def _callFUT(self, *args, **kw):
@@ -1631,13 +1797,6 @@ class ClassProvidesTests(unittest.TestCase):
self.assertEqual(cp.__reduce__(),
(type(cp), (Foo, type(Foo), IBar)))
- def test__repr__(self):
- inst = self._makeOne(type(self), type)
- self.assertEqual(
- repr(inst),
- "<zope.interface.declarations.ClassProvides for %r>" % type(self)
- )
-
class ClassProvidesStrictTests(ClassProvidesTests):
# Tests that require the strict C3 resolution order.
@@ -1649,9 +1808,6 @@ class ClassProvidesStrictTests(ClassProvidesTests):
return ClassProvides._do_calculate_ro(self, base_mros=base_mros, strict=True)
return StrictClassProvides
- def test__repr__(self):
- self.skipTest("Not useful for the subclass.")
-
def test_overlapping_interfaces_corrected(self):
# Giving ClassProvides(cls, metaclass, IFace), where IFace is already
# provided by metacls, doesn't produce invalid resolution orders.
@@ -1682,6 +1838,85 @@ class ClassProvidesStrictTests(ClassProvidesTests):
Interface
))
+
+class TestClassProvidesRepr(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ClassProvides
+ return ClassProvides
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test__repr__empty(self):
+ inst = self._makeOne(type(self), type)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestClassProvidesRepr)"
+ )
+
+ def test__repr__providing_one(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ "Does nothing"
+
+ inst = self._makeOne(type(self), type, IFoo)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestClassProvidesRepr, IFoo)"
+ )
+
+ def test__repr__duplicate_names(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo", __module__='mod1')
+ IFoo2 = InterfaceClass("IFoo", __module__='mod2')
+ IBaz = InterfaceClass("IBaz")
+
+ inst = self._makeOne(type(self), type, IFoo, IBaz, IFoo2)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestClassProvidesRepr, IFoo, IBaz, mod2.IFoo)"
+ )
+
+ def test__repr__implementedBy(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import implementedBy
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ inst = implementedBy(Foo)
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(Foo, IFoo)'
+ )
+
+ def test__repr__implementedBy_generic_callable(self):
+ from zope.interface.declarations import implementedBy
+ # We can't get a __name__ by default, so we get a
+ # module name and a question mark
+ class Callable(object):
+ def __call__(self):
+ return self
+
+ inst = implementedBy(Callable())
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(%s.?)' % (__name__,)
+ )
+
+ c = Callable()
+ c.__name__ = 'Callable'
+ inst = implementedBy(c)
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(Callable)'
+ )
+
+
class Test_directlyProvidedBy(unittest.TestCase):
def _callFUT(self, *args, **kw):
diff --git a/src/zope/interface/tests/test_exceptions.py b/src/zope/interface/tests/test_exceptions.py
index a55f522..ecebf91 100644
--- a/src/zope/interface/tests/test_exceptions.py
+++ b/src/zope/interface/tests/test_exceptions.py
@@ -36,7 +36,7 @@ class DoesNotImplementTests(unittest.TestCase):
self.assertEqual(
str(dni),
"An object has failed to implement interface "
- "<InterfaceClass zope.interface.tests.test_exceptions.IDummy>: "
+ "zope.interface.tests.test_exceptions.IDummy: "
"Does not declaratively implement the interface."
)
@@ -45,7 +45,7 @@ class DoesNotImplementTests(unittest.TestCase):
self.assertEqual(
str(dni),
"The object 'candidate' has failed to implement interface "
- "<InterfaceClass zope.interface.tests.test_exceptions.IDummy>: "
+ "zope.interface.tests.test_exceptions.IDummy: "
"Does not declaratively implement the interface."
)
@@ -65,7 +65,7 @@ class BrokenImplementationTests(unittest.TestCase):
self.assertEqual(
str(dni),
'An object has failed to implement interface '
- '<InterfaceClass zope.interface.tests.test_exceptions.IDummy>: '
+ 'zope.interface.tests.test_exceptions.IDummy: '
"The 'missing' attribute was not provided.")
def test___str__w_candidate(self):
@@ -73,7 +73,7 @@ class BrokenImplementationTests(unittest.TestCase):
self.assertEqual(
str(dni),
'The object \'candidate\' has failed to implement interface '
- '<InterfaceClass zope.interface.tests.test_exceptions.IDummy>: '
+ 'zope.interface.tests.test_exceptions.IDummy: '
"The 'missing' attribute was not provided.")
@@ -161,7 +161,7 @@ class MultipleInvalidTests(unittest.TestCase):
self.assertEqual(
str(dni),
"The object 'target' has failed to implement interface "
- "<InterfaceClass zope.interface.tests.test_exceptions.IDummy>:\n"
+ "zope.interface.tests.test_exceptions.IDummy:\n"
" The contract of 'aMethod' is violated because I said so\n"
" Regular exception"
)
diff --git a/src/zope/interface/tests/test_ro.py b/src/zope/interface/tests/test_ro.py
index 61f92b6..5542d28 100644
--- a/src/zope/interface/tests/test_ro.py
+++ b/src/zope/interface/tests/test_ro.py
@@ -259,16 +259,16 @@ class Test_c3_ro(Test_ro):
self.assertEqual('\n'.join(l.rstrip() for l in record.getMessage().splitlines()), """\
Object <InterfaceClass zope.interface.tests.test_ro.A> has different legacy and C3 MROs:
- Legacy RO (len=7) C3 RO (len=7; inconsistent=no)
- ====================================================================================================
- <InterfaceClass zope.interface.tests.test_ro.A> <InterfaceClass zope.interface.tests.test_ro.A>
- <InterfaceClass zope.interface.tests.test_ro.B> <InterfaceClass zope.interface.tests.test_ro.B>
- - <InterfaceClass zope.interface.tests.test_ro.E>
- <InterfaceClass zope.interface.tests.test_ro.C> <InterfaceClass zope.interface.tests.test_ro.C>
- <InterfaceClass zope.interface.tests.test_ro.D> <InterfaceClass zope.interface.tests.test_ro.D>
- + <InterfaceClass zope.interface.tests.test_ro.E>
- <InterfaceClass zope.interface.tests.test_ro.F> <InterfaceClass zope.interface.tests.test_ro.F>
- <InterfaceClass zope.interface.Interface> <InterfaceClass zope.interface.Interface>""")
+ Legacy RO (len=7) C3 RO (len=7; inconsistent=no)
+ ==================================================================
+ zope.interface.tests.test_ro.A zope.interface.tests.test_ro.A
+ zope.interface.tests.test_ro.B zope.interface.tests.test_ro.B
+ - zope.interface.tests.test_ro.E
+ zope.interface.tests.test_ro.C zope.interface.tests.test_ro.C
+ zope.interface.tests.test_ro.D zope.interface.tests.test_ro.D
+ + zope.interface.tests.test_ro.E
+ zope.interface.tests.test_ro.F zope.interface.tests.test_ro.F
+ zope.interface.Interface zope.interface.Interface""")
def test_ExtendedPathIndex_implement_thing_implementedby_super(self):
# See https://github.com/zopefoundation/zope.interface/pull/182#issuecomment-598754056