========================= Code Documentation Module ========================= The code documentation module package >>> from zope.app.apidoc import codemodule provides systematic and autogenerated documentation about the content of your Zope 3 related Python packages. The code module can be created like this: >>> cm = codemodule.codemodule.CodeModule() >>> cm.getDocString() u'Zope 3 root.' This object extends the `codemodule.module.Module` class, since it can be seen as some sort of root package. However, its sementacs are obviously a bit different: >>> cm.getFileName() '' >>> cm.getPath() '' >>> cm.keys() [] Module ------ The `Module` class represents a Python module or package in the documentation tree. It can be easily setup by simply passing the parent module, the module name (not the entire Python path) and the Python module instance itself: >>> import zope.app.apidoc >>> module = codemodule.module.Module(None, 'apidoc', zope.app.apidoc) We can now get some of the common module attributes via accessor methods: >>> module.getDocString() is None True >>> fname = module.getFileName() >>> fname = fname.replace('\\', '/') # Fix for Windows users >>> 'zope/app/apidoc/__init__.py' in fname True >>> module.getPath() 'zope.app.apidoc' The setup for creating the sub module and class tree is automatically called during initialization, so that the sub-objects are available as soon as you have the object: >>> keys = module.keys() >>> 'codemodule' in keys True >>> 'meta.zcml' in keys True >>> import zope.app.apidoc.browser >>> print module['browser'].getPath() zope.app.apidoc.browser Now, the ``get(key, default=None)`` is actually much smarter than you might originally suspect, since it can actually get to more objects than it promises. If a key is not found in the module's children, it tries to import the key as a module relative to this module. For example, while `tests` directories are not added to the module and classes hierarchy (since they do not provide or implement any API), we can still get to them: >>> import zope.app.apidoc.tests >>> print module['tests'].getPath() zope.app.apidoc.tests >>> names = module['tests'].keys() >>> names.sort() >>> names ['Root', 'rootLocation', 'setUp', 'tearDown', 'test_suite'] Classes ------- Setting up a class for documentation is not much harder. You only need to provide an object providing `IModule` as a parent, the name and the klass itself: >>> import zope.app.apidoc.apidoc >>> module = codemodule.module.Module( ... None, 'apidoc', zope.app.apidoc.apidoc) >>> klass = codemodule.class_.Class(module, 'APIDocumentation', ... zope.app.apidoc.apidoc.APIDocumentation) This class provides data about the class in an accessible format. The Python path and doc string are easily retrieved using:: >>> klass.getPath() 'zope.app.apidoc.apidoc.APIDocumentation' >>> klass.getDocString()[:41] 'Represent the complete API Documentation.' A list of base classes can also be retrieved. The list only includes direct bases, so if we have class `Blah`, which extends `Bar`, which extends `Foo`, then the base of `Blah` is just `Bar`. In our example this looks like this: >>> klass.getBases() (,) In the other direction, you can get a list of known subclasses. The list only includes those subclasses that are registered with the global `classRegistry` dictionary. In our example: >>> class APIDocSubclass(zope.app.apidoc.apidoc.APIDocumentation): ... pass >>> klass2 = codemodule.class_.Class(module, 'APIDocSubclass', APIDocSubclass) >>> klass.getKnownSubclasses() [] For a more detailed analysis, you can also retrieve the public attributes and methods of this class:: >>> klass.getAttributes() [] >>> klass.getMethods()[0] #doctest:+NORMALIZE_WHITESPACE ('get', , ) Let's have a closer look at the `getAttributes()` method. First we create an interface called `IBlah` that is implemented by the class `Blah`: >>> import zope.interface >>> class IBlie(zope.interface.Interface): ... bli = zope.interface.Attribute('Blie') >>> class IBlah(IBlie): ... foo = zope.interface.Attribute('Foo') >>> class Blah(object): ... zope.interface.implements(IBlah) ... foo = 'f' ... bar = 'b' ... bli = 'i' ... _blah = 'l' The `Blah` class also implements a public and private attribute that is not listed in the interface. Now we create the class documentation wrapper: >>> klass = codemodule.class_.Class(module, 'Blah', Blah) >>> pprint(klass.getAttributes()) [('bar', 'b', None), ('bli', 'i', ), ('foo', 'f', )] So, the function returns a list of tuples of the form (name, value, interface), where the interface is the interface in which the attribute was declared. The interface is `None`, if the attribute was not declared. Also note that attributes starting with an underscore are ignored. Let's now have a look at how methods are looked up returned. So we create a new `IBlah` interface, this time describing methods, and then its implementation `Blah`, which has some other additional methods: >>> class IBlah(zope.interface.Interface): ... def foo(): pass >>> class Blah(object): ... zope.interface.implements(IBlah) ... ... def foo(self): ... pass ... def bar(self): ... pass ... def _blah(self): ... pass Now we create the class documentation wrapper: >>> klass = codemodule.class_.Class(module, 'Blah', Blah) and get the method documenation: >>> pprint(klass.getMethods()) [('bar', , None), ('foo', , )] Function -------- Function are pretty much documented in the same way as all other code documentation objects and provides a similar API to the classes. A function documenation object is quickly created: >>> func = codemodule.function.Function( ... module, 'handleNamespace', ... zope.app.apidoc.apidoc.handleNamespace) This class provides data about the function in an accessible format. The Python path, signature and doc string are easily retrieved using: >>> func.getPath() 'zope.app.apidoc.apidoc.handleNamespace' >>> func.getSignature() '(ob, name)' >>> func.getDocString() 'Used to traverse to an API Documentation.' For a more detailed analysis, you can also retrieve the attributes of the function >>> func.getAttributes() [] but this function has none as most functions. So let's create a new function >>> def foo(bar=1): ... pass >>> func = codemodule.function.Function(module, 'foo', foo) which originally does not have any attributes >>> func.getAttributes() [] but if we add an attribute, it will be listed: >>> foo.blah = 1 >>> func.getAttributes() [('blah', 1)] Text File --------- Text files represent plain-text documentation files like this one. Once we have a text file documentation object >>> import os >>> path = os.path.join(os.path.dirname(codemodule.__file__), 'README.txt') >>> readme = codemodule.text.TextFile(path, 'README.txt', module) we can ask it for the content of the file: >>> print readme.getContent()[:77] ========================= Code Documentation Module ========================= ZCML File --------- ZCML file documentation objects present configuration files and parse the file content to provide some advanced markup. The object is easily instantiated: >>> path = os.path.join(os.path.dirname(codemodule.__file__), ... 'configure.zcml') >>> module = codemodule.module.Module(None, 'zope.app.apidoc.codemodule', ... zope.app.apidoc.codemodule) >>> zcml = codemodule.zcml.ZCMLFile(path, module) The interesting attribute of the object is the `rootElement`, since it contains the root XML element and thus the entire XML tree. The `rootElement` attribute is a lazy property, so that it is not loaded until accessed for the first time: >>> root = zcml.rootElement >>> root A directive component has some interesting atrributes, such as the name, >>> root.name (u'http://namespaces.zope.org/zope', u'configure') the schema that describes the directive, >>> root.schema the attributes of the XML element, >>> dict(root.attrs) {} the configuration context for the directive, which can be used to resolve objects and/or generate absolute paths of files, >>> root.context #doctest:+ELLIPSIS the parser info object, >>> info = `root.info` # Windows fix >>> info = info.replace('\\', '/') >>> print info #doctest:+ELLIPSIS File ".../zope/app/apidoc/codemodule/configure.zcml", line 1.0-53.0 the sub-directives, >>> root.subs[:2] [, ] and finally a list of all prefixes. >>> pprint(root.prefixes) {u'http://namespaces.zope.org/apidoc': u'apidoc', u'http://namespaces.zope.org/browser': u'browser', u'http://namespaces.zope.org/zope': None}