[TriZPUG] Getting inherited classes from interfaces

Chris Calloway cbc at unc.edu
Wed Apr 21 22:13:12 CEST 2010


On 4/21/2010 10:36 AM, César Muñoz wrote:
> Hello,
> I'm trying to get a list of the classes that inherit from an interface.
> Something like:
> 
> class A(InterfaceA):
> ...
> 
> class B(InterfaceA):
> ...
> 
> InterfaceA.getAllClasses()
> [A, B]
> 
> I've tried using implementedBy and providedBy, as well as some other
> functions from the API, but so far I've not been able to solve this issue.
> Any ideas?

César,

I assume this is a Zope Component Architecture question. If so, these 
lists will probably have more answers:

https://mail.zope.org/mailman/listinfo/zope3-users
http://mail.python.org/mailman/listinfo/tutor

The list to which you have written is a user group list local to the 
Triangle area of North Carolina.

(TriZPUGers, César is writing from Geneva.)

But to attempt to answer your question, a superclass is not the same 
thing as a Zope interface. Iinterfaces aren't inherited. They are 
implemented and provided.

See:

http://svn.zope.org/zope.interface/trunk/src/zope/interface/README.txt?view=markup
http://docs.zope.org/zope3/Book/ifaceschema/interface/show.html
http://www.muthukadan.net/docs/zca.html
http://pypi.python.org/pypi/zope.interface

The implementedBy method can tell you if a particular class has 
implemented a particular interface:

   >>> import zope.interface
   >>> class IFoo(zope.interface.Interface):
   ...    """Foo blah blah"""
   ...
   ...    x = zope.interface.Attribute("""X blah blah""")
   ...
   ...    def bar(q, r=None):
   ...        """bar blah blah"""
   ...
   >>> class Foo(object):
   ...     zope.interface.implements(IFoo)
   ...
   ...     def __init__(self, x=None):
   ...         self.x = x
   ...
   ...     def bar(self, q, r=None):
   ...         return q, r, self.x
   ...
   ...     def __repr__(self):
   ...         return "Foo(%s)" % self.x
   ...
   >>> IFoo.implementedBy(Foo)
   True
   >>>

The providedBy method can tell you if a particular instance provides a 
particular interface:

   >>> foo = Foo()
   >>> IFoo.providedBy(foo)
   True
   >>>

These methods can also tell about all interfaces implemented by a class 
or provided by an instance:

   >>> list(zope.interface.implementedBy(Foo))
   [<InterfaceClass __main__.IFoo>]
   >>> list(zope.interface.providedBy(foo))
   [<InterfaceClass __main__.IFoo>]
   >>>

zope.interface does not provide a method to return all the classes which 
implement or instances which provide an interface. If you were to create 
  a function which did, you would need to supply it with a namespace to 
search. For example (code guaranteed not be be robust as there are no 
test cases supplied):

 >>> def get_implementations(interface, namespace=None):
...     result = []
...     try:
...         if not namespace:
...            namespace = __import__('__main__')
...         objs = namespace.__dict__.values()
...     except:
...         objs = []
...     for obj in objs:
...         try:
...             if interface.implementedBy(obj):
...                 result.append(obj)
...         except:
...             pass
...     return result
...
 >>> get_implementations(IFoo)
[<class '__main__.Foo'>]
 >>>

A documentation tool used by the Twisted community called pydoctor 
purports to do this:

http://codespeak.net/~mwh/pydoctor/

If you use ZCML to register interfaces, implementations, and providers, 
then you can parse the ZCML to determine implementations and providers 
of interfaces.

ZCML is good because it moves all the declarative business of who 
implements or provides what out of Python and into configuration files 
where it belongs, keeping the code dynamic.

Similarly, if you are interested in what classes are subclasses of a 
particular subclass, you would also need to search a particular 
namespace and test each of the class objects found with the builtin 
function issubclass:

 >>> def get_subclasses(classinfo, namespace=None):
...     result = []
...     try:
...         if not namespace:
...            namespace = __import__('__main__')
...         objs = namespace.__dict__.values()
...     except:
...         objs = []
...     for obj in objs:
...         try:
...             if issubclass(obj,classinfo):
...                 result.append(obj)
...         except:
...             pass
...     return result
 >>> get_subclasses(Foo)
[<class '__main__.Foo'>]
 >>>

(Classes are always subclasses of themselves.)

 >>> get_subclasses(Exception,__builtins__)
[<type 'exceptions.IndexError'>, <type 'exceptions.SyntaxError'>,
...snip long list of Exception subtypes...
]
 >>>

-- 
Sincerely,

Chris Calloway
office: 332 Chapman Hall   phone: (919) 599-3530
mail: Campus Box #3300, UNC-CH, Chapel Hill, NC 27599


More information about the TriZPUG mailing list