zopeext for Sphinx#

author:

Michael McNeil Forbes <mforbes@alum.mit.edu>

This extension provides an autointerface directive for Zope interfaces.

Requirements#

Usage#

In the build configuration file (the conf.py in your Sphinx documentation directory) add sphinxcontrib.zopeext.autointerface to your extensions list:

extensions = [..., 'sphinxcontrib.zopeext.autointerface', ...]

Then, in your documentation, use autointerface as you would use autoclass. You can refer to the interface with the :py:interface: role example.IMyInterface as you would use the :py:class: role to refer to the implementation example.MyImplementation.

Here is an example produced by the following code:

.. automodule:: example
   :show-inheritance:
   :inherited-members:
   :noindex:

Note

We have included the autointerface.css which simply adds the following rule to give a green background for the interface:

dl.interface > dt { background-color: #33FF33; }

One can also limit which members are displayed, just as you would with .. autoclass:

.. autointerface:: example.IMyInterface
   :members: x, equals
.. autoclass:: example.MyImplementation
   :members: x, equals

ChangeLog#

This file describes user-visible changes between the extension versions.

Version 0.4.3 (2024-01-17)#

  • Support Sphinx up to 7.2.6 (tested) and Python up to 3.12.

  • Fixed some bugs with python 3.7 and 3.8.

  • Resolves issue #10

Version 0.4.2 (2023-04-19)#

  • Actually add the namespace package!

  • Working GitHub CI and ReadTheDocs.

Version 0.4.0 (2023-04-18)#

  • Drop support for Python 3.6

  • Drop support for Sphinx 3 (minimum version is now 4.5.0)

  • Resolves issue #9: No upper bounds on versions. (Using PDM instead of Poetry.)

Version 0.3.3 (2022-09-04)#

  • Resolves issue #7, support for Sphinx 5.x. (Thanks to Jerry James @jamesjer).

  • Better test coverage for different version combinations.

Version 0.3.2 (2022-01-05)#

  • Resolves issue #5 by removing sphinxcontrib/__init__.py which could be installed by different sphinxcontrb packages like sphinxcontrib-asyncio.

Version 0.3.1 (2022-01-05)#

  • Resolves issue #3 (bug when missing members were requested).

  • Added more extensive testing following Sphinx’s examples.

Version 0.3.0 (2021-12-22)#

  • Major restructuring of code to work with poetry rather than setuptools.

  • Update and simplification of code to work with Sphinx >= 3.4.2. Prior versions relied on some private behaviour which is deprecated. The new version can now use the public API.

  • Resolves issue #1 by inserting a small javascript snippet that changes class="py interface" to class="py interface class" so that themes which don’t provide support for styling interface (most of them) will fallback to using the same format as a class.

Version 0.2.4 (2020-03-15)#

  • Fixed issue with :members: requesting ALL members.

Version 0.2.3 (2019-11-01)#

  • Fixed some Python 3 errors and Sphinx deprecation warnings.

Version 0.2.2 (2017-07-26)#

  • Removed stripping of cls, and self from signatures. It is an error to include these arguments in an Interface as they are not part of the public interface of the object. Interfaces with these will not validate properly.

  • Do not include constructor in interface - add docstring (if it is provided) to the class documentation.

Version 0.2.1 (2013-05-01)#

  • Removed automatic import of autointerface to facilitate setup. New code must now import sphinxcontrib.zopeext.autointerface explicitly.

Version 0.2 (2012-07-24)#

  • Added website.

  • Added documentation.

  • Added to PyPi.

  • Added example.py

Version 0.1 (2010-05-20)#

  • Initial version.

Details#

autointerface#

This Sphinx extension adds an autointerface directive, which can be used like autoclass to document zope interfaces. Interfaces are intended to be very different beasts than regular python classes, and as a result require customized access to documentation, signatures etc.

.. autointerface::#

The autointerface directive has the same form and option as the autoclass directive:

.. autointerface:: IClass
   ...

Note

This extension also serves as a simple example of using the sphinx version 0.6 sphinx.ext.autodoc refactoring. Mostly this was straight forward, but I stumbled across one “gotcha”:

The objtype attribute of the documenters needs to be unique. Thus, for example, InterfaceMethodDocumenter.objtype cannot be ‘method’ because this would overwrite the entry in AutoDirective._registry used to choose the correct documenter.

Implementation Details#

interface_getattr(*v)

Behaves like getattr but for zope Interface objects which hide the attributes.

interface_format_args(obj)

Return the signature of an interface method or of an interface.

InterfaceDocumenter(*args)

A Documenter for zope.interface.Interface interfaces.

InterfaceAttributeDocumenter(directive, name)

A Documenter for zope.interface.interface.Attribute interface attributes.

InterfaceMethodDocumenter(directive, name[, ...])

A Documenter for zope.interface.interface.Method interface attributes.

InterfaceDirective(name, arguments, options, ...)

An 'interface' directive.

setup(app)

class sphinxcontrib.zopeext.autointerface.InterfaceAttributeDocumenter(directive: DocumenterBridge, name: str, indent: str = '')[source]#

A Documenter for zope.interface.interface.Attribute interface attributes.

add_content(more_content)[source]#

Add content from docstrings, attribute documentation and user.

add_directive_header(sig: str) None[source]#

Add the directive header and options to the generated content.

classmethod can_document_member(member, membername, isattr, parent)[source]#

Called to see if a member can be documented by this Documenter.

generate(*v, **kw)[source]#

Generate reST for the object given by self.name, and possibly for its members.

If more_content is given, include that content. If real_modname is given, use that module name to find attribute docs. If check_module is True, only generate if the object is defined in the module name it is imported from. If all_members is True, document all members.

isslotsattribute() bool[source]#

Check the subject is an attribute in __slots__.

member_order = 60#

order if autodoc_member_order is set to ‘groupwise’

objtype = 'interfaceattribute'#

name by which the directive is called (auto…) and the default generated directive name

priority = 110#

priority if multiple documenters return True from can_document_member

class sphinxcontrib.zopeext.autointerface.InterfaceDirective(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]#

An ‘interface’ directive.

get_index_text(modname, name_cls)[source]#

Return the text for the index entry of the object.

class sphinxcontrib.zopeext.autointerface.InterfaceDocumenter(*args: Any)[source]#

A Documenter for zope.interface.Interface interfaces.

add_directive_header(sig: str) None[source]#

Add the directive header and options to the generated content.

static autodoc_process_docstring(app, what, name, obj, options, lines)[source]#

Hook that adds the constructor to the object so it can be found.

classmethod can_document_member(member: Any, membername: str, isattr: bool, parent: Any) bool[source]#

Called to see if a member can be documented by this Documenter.

format_args() str[source]#

Format the argument signature of self.object.

Should return None if the object does not have a signature.

get_object_members(want_all: bool) Tuple[bool, List[ObjectMember] | List[Tuple[str, Any]]][source]#

Return (members_check_module, members) where members is a list of (membername, member) pairs of the members of self.object.

If want_all is True, return all members. Else, only return those members given by self.options.members (which may also be None).

objtype = 'interface'#

name by which the directive is called (auto…) and the default generated directive name

priority = 115#

priority if multiple documenters return True from can_document_member

class sphinxcontrib.zopeext.autointerface.InterfaceMethodDocumenter(directive: DocumenterBridge, name: str, indent: str = '')[source]#

A Documenter for zope.interface.interface.Method interface attributes.

classmethod can_document_member(member, membername, isattr, parent)[source]#

Called to see if a member can be documented by this Documenter.

format_args()[source]#

Format the argument signature of self.object.

Should return None if the object does not have a signature.

member_order = 70#

order if autodoc_member_order is set to ‘groupwise’

objtype = 'interfacemethod'#

name by which the directive is called (auto…) and the default generated directive name

priority = 101#

priority if multiple documenters return True from can_document_member

sphinxcontrib.zopeext.autointerface.interface_format_args(obj)[source]#

Return the signature of an interface method or of an interface.

sphinxcontrib.zopeext.autointerface.interface_getattr(*v)[source]#

Behaves like getattr but for zope Interface objects which hide the attributes.

Note

Originally I simply tried to override InterfaceDocumenter.special_attrgetter() to deal with the special access needs of Interface objects, but found that this is not intended to be overwritten. Instead one should register the special accessor using app.add_autodoc_attrgetter().

License#

Copyright 2021 Michael McNeil Forbes

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of
   conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list
   of conditions and the following disclaimer in the documentation and/or other materials
   provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.