From 45c97ab85d86c867df1ed1d3f813c8fc7fad2649 Mon Sep 17 00:00:00 2001 From: Jason Madden Date: Wed, 17 Mar 2021 10:01:49 -0500 Subject: [PATCH 1/2] Update documentation and Provides repr for better debugging. Fixes #229. Replaces #232 --- CHANGES.rst | 4 ++++ src/zope/interface/declarations.py | 3 ++- src/zope/interface/ro.py | 23 +++++++++++++++++++ src/zope/interface/tests/test_declarations.py | 10 ++++++-- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index c791f505..02d72c29 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,10 @@ 5.3.0 (unreleased) ================== +- Improve the repr of ``zope.interface.Provides`` to remove ambiguity + about what is being provided. This is especially helpful diagnosing + IRO issues. + - Allow subclasses of ``BaseAdapterRegistry`` (including ``AdapterRegistry`` and ``VerifyingAdapterRegistry``) to have control over the data structures. This allows persistent diff --git a/src/zope/interface/declarations.py b/src/zope/interface/declarations.py index ec67eee3..45d29980 100644 --- a/src/zope/interface/declarations.py +++ b/src/zope/interface/declarations.py @@ -763,10 +763,11 @@ def __init__(self, cls, *interfaces): Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, cls)) def __repr__(self): - return "<%s.%s for %s>" % ( + return "<%s.%s for instances of %s providing %s>" % ( self.__class__.__module__, self.__class__.__name__, self._cls, + self.__args[1:], ) def __reduce__(self): diff --git a/src/zope/interface/ro.py b/src/zope/interface/ro.py index 20338ed9..89dde679 100644 --- a/src/zope/interface/ro.py +++ b/src/zope/interface/ro.py @@ -45,6 +45,10 @@ If this is set to "1", any attempt to use :func:`ro` that would produce a non-C3 ordering will fail by raising :class:`InconsistentResolutionOrderError`. +.. important:: + + ``ZOPE_INTERFACE_STRICT_IRO`` is intended to become the default in the future. + There are two environment variables that are independent. ZOPE_INTERFACE_LOG_CHANGED_IRO @@ -56,6 +60,25 @@ legacy IRO will be used instead. This is a temporary measure and will be removed in the future. It is intended to help during the transition. It implies ``ZOPE_INTERFACE_LOG_CHANGED_IRO``. + +.. rubric:: Debugging Behaviour Changes in zope.interface 5 + +Most behaviour changes from zope.interface 4 to 5 are related to +inconsistent resolution orders. ``ZOPE_INTERFACE_STRICT_IRO`` is the +most effective tool to find such inconsistent resolution orders, and +we recommend running your code with this variable set if at all +possible. Doing so will ensure that all interface resolution orders +are consistent, and if they're not, will immediately point the way to +where this is violated. + +Occasionally, however, this may not be enough. This is because in some +cases, a C3 ordering can be found (the resolution order is fully +consistent) that is substantially different from the ad-hoc legacy +ordering. In such cases, you may find that you get an unexpected value +returned when adapting one or more objects to an interface. To debug +this, *also* enable ``ZOPE_INTERFACE_LOG_CHANGED_IRO`` and examine the +output. The main thing to look for is changes in the relative +positions of interfaces for which there are registered adapters. """ from __future__ import print_function __docformat__ = 'restructuredtext' diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py index 29b75e9c..f4354fe0 100644 --- a/src/zope/interface/tests/test_declarations.py +++ b/src/zope/interface/tests/test_declarations.py @@ -1305,10 +1305,16 @@ def _test(): self.assertRaises(AttributeError, _test) def test__repr__(self): - inst = self._makeOne(type(self)) + from zope.interface.interface import InterfaceClass + IFoo = InterfaceClass("IFoo") + + inst = self._makeOne(type(self), IFoo) self.assertEqual( repr(inst), - "" % type(self) + "" % ( + type(self), + (IFoo,) + ) ) From f46bc4f788dd573e655899c8d7943e031e90286d Mon Sep 17 00:00:00 2001 From: Jason Madden Date: Thu, 18 Mar 2021 06:00:14 -0500 Subject: [PATCH 2/2] Improve the tests for ProvidesClass.__repr__. --- src/zope/interface/tests/test_declarations.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py index f4354fe0..0c21b8ce 100644 --- a/src/zope/interface/tests/test_declarations.py +++ b/src/zope/interface/tests/test_declarations.py @@ -1307,14 +1307,20 @@ def _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) == '' % (__name__,) - inst = self._makeOne(type(self), IFoo) + IBar = InterfaceClass("IBar") + + inst = self._makeOne(type(self), IFoo, IBar) self.assertEqual( repr(inst), - "" % ( - type(self), - (IFoo,) - ) + " " + "providing (, )>" % { + 'mod': __name__, + } )