Source code for zope.app.apidoc.codemodule.class_

##############################################################################
#
# Copyright (c) 2004 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Class representation for code browser
"""

__docformat__ = 'restructuredtext'

from inspect import isfunction
from inspect import ismethod
from inspect import ismethoddescriptor

from zope.interface import implementer, implementedBy
from zope.security.checker import getCheckerForInstancesOf
from zope.location.interfaces import ILocation

from zope.app.apidoc.classregistry import classRegistry
from zope.app.apidoc.utilities import getInterfaceForAttribute
from zope.app.apidoc.utilities import getPublicAttributes
from zope.app.apidoc.codemodule.interfaces import IClassDocumentation


@implementer(ILocation, IClassDocumentation)
[docs]class Class(object): """This class represents a class declared in the module.""" def __init__(self, module, name, klass): self.__parent__ = module self.__name__ = name self.__klass = klass # Setup interfaces that are implemented by this class. self.__interfaces = tuple(implementedBy(klass)) self.__all_ifaces = tuple(implementedBy(klass).flattened()) # Register the class with the global class registry. classRegistry[self.getPath()] = klass
[docs] def getPath(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return self.__parent__.getPath() + '.' + self.__name__
[docs] def getDocString(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return self.__klass.__doc__
[docs] def getBases(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return self.__klass.__bases__
[docs] def getKnownSubclasses(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return [k for n, k in classRegistry.getSubclassesOf(self.__klass)]
[docs] def getInterfaces(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return self.__interfaces
def _iterAllAttributes(self): for name in getPublicAttributes(self.__klass): iface = getInterfaceForAttribute( name, self.__all_ifaces, asPath=False) yield name, getattr(self.__klass, name), iface if str is bytes: # Python 2 _ismethod = staticmethod(ismethod) else: # On Python 3, there is no unbound method. But we can't treat # things that are simply callable as methods. Things like the # security proxy are callable, but when `permission = # CheckerPublic` (where zope.security.checker.CheckerPublic is # proxied) is a class attribute, that's *not* a method. # Checking if its actually a function gets us much more accurate # results. (We could also check its qualname to see if it "belongs" # to this class, but this seems to do the trick) _ismethod = staticmethod(isfunction)
[docs] def getAttributes(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return [(name, obj, iface) for name, obj, iface in self._iterAllAttributes() if not self._ismethod(obj) and not ismethoddescriptor(obj)]
[docs] def getMethods(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return [(name, obj, iface) for name, obj, iface in self._iterAllAttributes() if self._ismethod(obj)]
def getMethodDescriptors(self): return [(name, obj, iface) for name, obj, iface in self._iterAllAttributes() if ismethoddescriptor(obj)]
[docs] def getSecurityChecker(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" return getCheckerForInstancesOf(self.__klass)
[docs] def getConstructor(self): """See :class:`~zope.app.apidoc.codemodule.interfaces.IClassDocumentation`.""" init = getattr(self.__klass, '__init__', None) if callable(init): return init