Source code for zope.app.apidoc.classregistry

##############################################################################
#
# 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 Registry
"""
__docformat__ = 'restructuredtext'

__import_unknown_modules__ = False

# List of modules that should never be imported.
# TODO: List hard-coded for now.
IGNORE_MODULES = ['twisted']

import operator
import sys
from six import iteritems

_pathgetter = operator.itemgetter(0)

[docs]class ClassRegistry(dict): """A simple registry for classes.""" # This is not a WeakValueDictionary; the classes in here # are kept alive almost certainly by the codemodule.class_.Class object, # which in turn is kept alive by a codemodule.module.Module chain going # all the way back to the APIDocumentation object registered with the # global site manager. So they can't go away without clearing all that, # which happens (usually only) with test tear downs.
[docs] def getClassesThatImplement(self, iface): """Return all class items that implement iface. Methods returns a sorted list of 2-tuples of the form (path, class). """ return sorted(((path, klass) for path, klass in iteritems(self) if iface.implementedBy(klass)), key=_pathgetter)
[docs] def getSubclassesOf(self, klass): """Return all class items that are proper subclasses of klass. Methods returns a sorted list of 2-tuples of the form (path, class). """ return sorted(((path, klass2) for path, klass2 in iteritems(self) if issubclass(klass2, klass) and klass2 is not klass), key=_pathgetter)
#: The global class registry object. Cleaned up #: in tests by :mod:`zope.testing.cleanup`. classRegistry = ClassRegistry() def cleanUp(): classRegistry.clear() from zope.testing.cleanup import addCleanUp addCleanUp(cleanUp)
[docs]def safe_import(path, default=None): """Import a given path as efficiently as possible and without failure.""" module = sys.modules.get(path, default) for exclude_name in IGNORE_MODULES: if path.startswith(exclude_name): return default if module is default and __import_unknown_modules__: try: module = __import__(path, {}, {}, ('*',)) # Some software, we cannot control, might raise all sorts of errors; # thus catch all exceptions and return the default. except Exception: return default return module