1

I'm trying to .. autoclass:: a class with instance attribute:

.. autoclass:: synergine.core.Test.Test
   :members:
   :undoc-members:
   :private-members:

of (in file synergine/core/Test.py):

class Test:

    def __init__(self):
        #: A foo bar instance attribute !
        self._foo = 'bar'

But when i make html sphinx raise this error:

/home/bux/Projets/synergine/doc/source/Components.rst:143: WARNING: autodoc: failed to import attribute 'Test._foo' from module 'synergine.core.Test'; the following exception was raised:
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/sphinx/util/inspect.py", line 108, in safe_getattr
    return getattr(obj, name, *defargs)
AttributeError: type object 'Test' has no attribute '_foo'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/sphinx/ext/autodoc.py", line 342, in import_object
    obj = self.get_attr(obj, part)
  File "/usr/local/lib/python3.4/dist-packages/sphinx/ext/autodoc.py", line 241, in get_attr
    return safe_getattr(obj, name, *defargs)
  File "/usr/local/lib/python3.4/dist-packages/sphinx/util/inspect.py", line 114, in safe_getattr
    raise AttributeError(name)
AttributeError: _foo

Why ? What i've to do to document this instance attribute ?

Edit: Seems to be bug reported: https://github.com/sphinx-doc/sphinx/issues/956 . Any way to hack it ?

mzjn
  • 48,958
  • 13
  • 128
  • 248
bux
  • 7,087
  • 11
  • 45
  • 86
  • Seems to be bug reported: https://github.com/sphinx-doc/sphinx/issues/956 . Any way to hack it ? – bux May 18 '15 at 20:59
  • A way to "hack it" that might work is to add `__slots__ = ['_foo']` to the definition of the `Test` class (similar to http://stackoverflow.com/a/11347883/407651). – mzjn May 19 '15 at 09:09
  • Did you try my suggestion in the previous comment? – mzjn Jun 29 '15 at 19:10
  • Not yet, i try when i can and notify you here ;) – bux Jun 29 '15 at 20:55

1 Answers1

0

This issue is still there! I had the issue when I wanted to create an in-house developer documentation. Therefore I also wanted the private-protected variables and class constants be documented.

Example:

class Foo(object):
    #: foo is a list for ...
    __foo = []
    __bar = None
    """
    bar stores ...
    """
    # [...]

Solution:

in sphinx.util.inspect change the function safe_getattr:

def safe_getattr(obj, name, *defargs):
    """A getattr() that turns all exceptions into AttributeErrors."""
    try:
        if name.startswith("__") and not name.endswith("__"): # <-+ these lines
            obj_name = obj.__name__                           #   | have to be
            if "_%s%s"%(obj_name,name) in obj.__dict__:       #   | added
                name = "_%s%s"%(obj_name,name)                # <-+ 
        return getattr(obj, name, *defargs)
    except Exception as error:
        # this is a catch-all for all the weird things that some modules do
        # with attribute access
        if defargs:
            return defargs[0]
        raise AttributeError(name)     

this will remove the error. To remove the internal namespace, of protected class constants in the generated docs, change the function filter_members inside sphinx.ext.autodoc:

def filter_members(self, members, want_all):
    # [...] 
    for (membername, member) in members:
        # [...]
        elif want_all and membername.startswith('_'):
            # ignore members whose name starts with _ by default
            keep = self.options.private_members and \
                        not membername.startswith('_'+namespace) and\  # <- ADD THIS LINE
                        (has_doc or self.options.undoc_members)    
    # [...]
MagSec
  • 346
  • 4
  • 17