attrs icon indicating copy to clipboard operation
attrs copied to clipboard

Self documentation - current state

Open Nicholas-Autio-Mitchell opened this issue 6 years ago • 17 comments

@hynek @chadrik

I've tried following this and other threads and reading the current docs, but can't see if/how one best produces any documentation directly from the attr.ib() definitions.

If it does not exist, would something like argparse be a good example? I suppose the type annotation (e.g. using attr.s(auto_attribs=True) is a step in the direction I am thinking/hoping for. I don't know the details, but Emacs does a good job of self-documenting, which is especially useful with the type annotation, as that provides at least some information for each argument.

Could someone point me in the right direction, please?

Nicholas-Autio-Mitchell avatar Mar 15 '18 10:03 Nicholas-Autio-Mitchell

I am also looking at a way to produce documentation, possibly in some json-schema format for my JSON serialization of attrs objects.

The key for me is honing on a proper way to add a description or help or doc to an attribute as per @manishtomar in #104 and also to an object (and eventually to nested objects like in @Tinche cattrs) .

This could use metadata alright for attr.ib, but at least there should be a convention that we can all agree for this?

From then I could introspect my objects to generate some docs.

Another helper to me would be @toumorokoshi jsonschema-extractor most likely. It does not handle any doc/help/description though.

pombredanne avatar Apr 03 '18 16:04 pombredanne

I'd be up for adding functionality into jsonschema-extractor to extract docstring data. I like the example of:

@attr.s
class Foo:
    x = attr.ib(doc="this is a variable")

toumorokoshi avatar Apr 05 '18 03:04 toumorokoshi

It might be nice to collect the use cases for this feature before start talking API?

hynek avatar Apr 09 '18 09:04 hynek

As one of the use case for me, I maintain this tool https://github.com/nexB/scancode-toolkit. At a high level the tool returns structured data in a file (formatted as JSON): the format needs to be properly documented. This documentation could include generated json schema(s).

Internally, this is for now a messy mish-mash of plain objects, plain data structures, namedtuples, attr objects and schematics objects. I would like to move it all to attr and have a not too complicated path to generate sphynx doc, custom docs and json-schema.

Having a description attached to a field or object is quite important for any documentation to be meaningful to me.

pombredanne avatar Apr 09 '18 10:04 pombredanne

@manishtomar @Nicholas-Mitchell any more input so we can make this move forward?

pombredanne avatar May 07 '18 08:05 pombredanne

I would like to move it all to attr and have a not too complicated path to generate sphynx doc

@pombredanne My original intent was exactly this. Also it makes the code more readable.

manishtomar avatar May 07 '18 16:05 manishtomar

Interface-wise, added a doc argument to the attribute definition would be a clean and simple way to add the functionality on the front-end, leaving and clever parts behind the scenes, perhaps controlled by other keyword arguments argument, e.g. x = attr.ib(doc='a variable of some kind, **kwargs)-->x = attr.ib(doc='a variable of some kind, doc_backend='sphynx'), etc.

Perhaps the following will inherently be covered by a Sphynx-type solution, but I will mention it just in case it sparks other ideas.

Another type of functionality in which I am most interested is interactive use of the documentation; usually via docstrings in either (1) the interactive prompt, (2) a Jupyter notebook or (3) an IDE. I do this extensively whilst coding, preferring that to finding leaving eh coding environment to find a website with the docs.

As I integrate attrs, I am still writing the docstrings myself (this follows the general concentions of NumPy):

class NormalClass:
    """An class that uses attrs to do interesting stuff.

    Parameters
    ----------
    x : {int, float}
        a vector - some more useful information
    """
    def __init__(self, x):
        self.x = x

    if not isinstance(x, (int, float)):
        # raise an error

This could become:

@attr.s
def AttrsClass:
    """An class that uses attrs to do interesting stuff.
    """
    x = attr.ib(default=None, validator=attr.validators.instance_of((int, float)),
                doc='a vector - some more useful information')

Then I would end up doing something like this is in an ipython prompt: AttrsClass? in order to read the documentation.

a = AttrsClass(x=23.5)

# Have a look at the docstring for the class
a?

This could then be extended, using the suggested approach of a doc argument, to work like this for individual attributes:

a.x.doc
 
# Even perhaps using the ipython helper: ?
a.x?

Current functionality of the last line would show information about the type of x (in this case an int).

Maybe these things could be incorporated into the __repr__ functions somehow, so the new doc info is nicely printed with the class.

Nicholas-Autio-Mitchell avatar May 08 '18 09:05 Nicholas-Autio-Mitchell

So for extracting information by other tools, you can already use metadata={"doc": "whatever"} so I think the really interesting part here is the expansion of the class’ __doc__.

For those who really want that right now, I’m pretty sure you can build yourself a decorator that does the same thing and patches the class’ __doc__.

The open questions are:

  1. where will the type information come from (I’m gonna say type since it can be set both using annotations and attr.ib(type=x).
  2. how is __doc__ supposed to be formatted?

2 Seems more complicated than it sounds and I’m not 100% confident we can achieve a solution that is good for everyone. 🤔 Most flexible idea from the top of my head would be to allow for a {attrs_ivar_docs} I suppose?

hynek avatar Jun 16 '18 07:06 hynek

@hynek: agreed. Perhaps attr.s could take a doc_formatter argument which is an object of a given shape that can generate the documentation for attributes? Then one could eventually write formatters for different styles?

wsanchez avatar Jun 16 '18 13:06 wsanchez

All seem like good ideas, @hynek @wsanchez

Your suggested doc-formatter argument to attr.s could also just be an option from a (probably short) list of available common formatting styles. So the actual implementation of a formatter wouldn't be left to the user without at least offering something that just works. This would mean the user must then write docstrings that correspond to the available formatters, but as attrs is generally about making life easier, I find that a nice trade-off.

Nicholas-Autio-Mitchell avatar Jun 27 '18 17:06 Nicholas-Autio-Mitchell

Any news on this one?

AlmogCohen avatar Apr 30 '19 00:04 AlmogCohen

Perhaps a Sphinx extension could pull attributes off the attr.fields(cls) to help with the formatting for API docs. Of course, that doesn't address help(cls).

energizah avatar Aug 08 '19 21:08 energizah

Note that https://docs.python.org/3/whatsnew/3.8.html#inspect allows __slots__ to now have documentation in Python 3.8 (you make it a dict). This might be quite useful for a doc= on an attribute of a slots class (where this currently would be a bit more challenging to do).

henryiii avatar Mar 24 '20 21:03 henryiii

Example:

class A:
    __slots__ = {"one": "one doc"}
help(A.one)

Python 3.7:

Help on member descriptor __main__.A.one:

one

Python 3.8:

Help on member descriptor __main__.A.one:

one
    one doc

henryiii avatar Mar 24 '20 21:03 henryiii

One use case I would like in attrs (although that might make more sense as a plugin than as part of the core) is to have an independent JSON Schema (or Ion, or protobuf, or whatever) defining the structure, and then be able to construct an attrs class from it automatically -- essentially an attrs-based equivalent of warlock.

berislavlopac avatar Jan 18 '21 13:01 berislavlopac

I don't think there is one format of __doc__ that is good for everyone. Some people are only interested in Sphinx format while some find it too ugly and want something easier to read like Google's. It's obvious to me that attrs should keep doc string of class and attributes and any related metadata in a dict of some sort. And then users can provide a DocFormatter to write the doc string that they desire.

My use case is to write doc string once for individual attributes and then programmatically display them in command-line arguments and also to generate Sphinx documentation.

pckhoi avatar Jan 08 '22 01:01 pckhoi

🤔 maybe typing.Annotated can be useful here? https://docs.python.org/3/library/typing.html#typing.Annotated

it would basically move the problem outside the attrs api altogether:

attrs.define
class A:
    b: Annotated[str, "b for 🍌"]
    c: Annotated[str, "c is for 🍪, of course!"]

wbolster avatar Apr 07 '22 19:04 wbolster