Mad Physicist
Mad Physicist

Reputation: 114588

Modify data representation in Sphinx

I have the following module:

"""
This is a test.
"""

class Test(dict):
    """ Should always appear empty in the docs. """
    def __repr__(self): return '{}'
    def __str__(self): return '{}'
    def __format__(self, *args): return '{}'

#: This is a dictionary that appears appears to be empty in the docs, but isn't
#: really. Enjoy!
test = Test()
test['a'] = 1
test['b'] = 2

I document the module with

.. automodule:: test
   :members:

Everything compiles just fine. However, when I look at the documentation of test.test, I see

test.test = {'a': 1, 'b': 2}

How does sphinx autodoc get the representation of the data object, and how can I override it? The whole point of the Test class is to make the following output:

test.test = {}

Upvotes: 1

Views: 596

Answers (2)

Mad Physicist
Mad Physicist

Reputation: 114588

Based on @mzjn's comment, I came up with an incredibly hacky solution that actually works in my very specific case, but I would not recommend to anyone else.

The trick is in the following lines in the object_description function:

if isinstance(object, dict):
    try:
        sorted_keys = sorted(object)
    except Exception:
        pass # Cannot sort dict keys, fall back to generic repr
    ...

If sorted fails, the description defaults over to repr. The easiest way to make sorted fail is to make my class Test non-iterable:

def __iter__(self):
    raise TypeError('no!') 

While this is extremely non-recommended for general purpose dictionary extensions, it works fine for my Test class, and produces the expected result.

Upvotes: 1

mzjn
mzjn

Reputation: 51082

The dictionary value is created in the object_description function in this Python file: https://github.com/sphinx-doc/sphinx/blob/master/sphinx/util/inspect.py. The function provides "a repr() implementation that returns text safe to use in reST context".

The representation created by Sphinx can be overridden by using the autodata directive with the annotation option.

.. automodule:: test
   :members:
   :exclude-members: test

.. autodata:: test.test
   :annotation: = {}

Upvotes: 2

Related Questions