zopefoundation/zope.interface

Update __repr__ and __str__ for (at least) Provides and InterfaceClass?

jamadden opened this issue · 2 comments

(Moved from #234 (comment))

Given spec = Provides(AClass, IFoo, IBar), the repr will be something like

<zope.interface.Provides for instances of <class 'some.module.AClass'> providing (<InterfaceClass some.module.interfaces.IFoo>, <InterfaceClass some.module.interfaces.IBar>)>

Informative, but not terse.

Basically none of these objects have a __str__ method.

__repr__ is meant to "look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment)."

In contrast __str__ computes "the 'informal' string representation of an object. This differs from __repr__() in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead. The return value must be a string object."

For Provides, it would be pretty easy to give a repr that actually can be evaluated (in many cases) outputting something like

Provides(AClass, IFoo, IBar)

Similarly, interfaces could have a __str__ that just outputs __module__.__name__.

That would transform reports from

Object <InterfaceClass BTrees.Interfaces.ISet> has different legacy and C3 MROs:
  Legacy RO (len=7)                                  C3 RO (len=7; inconsistent=no)
  ====================================================================================================
    <InterfaceClass BTrees.Interfaces.ISet>            <InterfaceClass BTrees.Interfaces.ISet>
    <InterfaceClass BTrees.Interfaces.IKeySequence>    <InterfaceClass BTrees.Interfaces.IKeySequence>
  - <InterfaceClass BTrees.Interfaces.ISized>
    <InterfaceClass BTrees.Interfaces.ISetMutable>     <InterfaceClass BTrees.Interfaces.ISetMutable>
    <InterfaceClass BTrees.Interfaces.IKeyed>          <InterfaceClass BTrees.Interfaces.IKeyed>
    <InterfaceClass BTrees.Interfaces.ICollection>     <InterfaceClass BTrees.Interfaces.ICollection>
                                                     + <InterfaceClass BTrees.Interfaces.ISized>
    <InterfaceClass zope.interface.Interface>          <InterfaceClass zope.interface.Interface>

to

Object <InterfaceClass BTrees.Interfaces.ISet> has different legacy and C3 MROs:
  Legacy RO (len=7)                                  C3 RO (len=7; inconsistent=no)
  ==================================================================================
    BTrees.Interfaces.ISet            BTrees.Interfaces.ISet
    BTrees.Interfaces.IKeySequence    BTrees.Interfaces.IKeySequence
  - BTrees.Interfaces.ISized
    BTrees.Interfaces.ISetMutable     BTrees.Interfaces.ISetMutable
    BTrees.Interfaces.IKeyed          BTrees.Interfaces.IKeyed
    BTrees.Interfaces.ICollection     BTrees.Interfaces.ICollection
                                    + BTrees.Interfaces.ISized
    zope.interface.Interface          zope.interface.Interface

(With similar benefits when Provides is present.)

Since the changes in Provides in #234 mean that there might have to be doctest updates, and since adding a __str__ mostly shouldn't (but might!) cause doctest updates, this might be a good time (before 5.3) to make such a change.

What do you think?

Pending discussion of this, I'd like to go ahead and publish the trunk to PyPI as zope.interface 5.3.0a1; that will unblock zope.component to move forward (zopefoundation/zope.component#53 and zopefoundation/zope.component#55).

If we decide to go ahead with these changes, I can make the PR, and then we can release that as 5.3.0.

If we decide not to make these changes, I can release 5.3.0 with no changes from 5.3.0a1.

I'll wait at least an hour before taking any action.

I like it.