Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self documentation - current state #357

Open
Nicholas-Autio-Mitchell opened this issue Mar 15, 2018 · 17 comments
Open

Self documentation - current state #357

Nicholas-Autio-Mitchell opened this issue Mar 15, 2018 · 17 comments
Labels

Comments

@Nicholas-Autio-Mitchell

@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?

@pombredanne
Copy link
Contributor

pombredanne commented Apr 3, 2018

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.

@toumorokoshi
Copy link

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")

@hynek
Copy link
Member

hynek commented Apr 9, 2018

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

@pombredanne
Copy link
Contributor

pombredanne commented Apr 9, 2018

As one of the use case for me, I maintain this tool https:/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
Copy link
Contributor

@manishtomar @nicholas-mitchell any more input so we can make this move forward?

@manishtomar
Copy link

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.

@Nicholas-Autio-Mitchell
Copy link
Author

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.

@hynek
Copy link
Member

hynek commented Jun 16, 2018

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?

@wsanchez
Copy link

@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?

@Nicholas-Autio-Mitchell
Copy link
Author

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.

@AlmogCohen
Copy link

Any news on this one?

@energizah
Copy link

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).

@henryiii
Copy link

henryiii commented Mar 24, 2020

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
Copy link

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

@berislavlopac
Copy link

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.

@pckhoi
Copy link

pckhoi commented Jan 8, 2022

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.

@wbolster
Copy link
Member

wbolster commented Apr 7, 2022

🤔 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!"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests