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

Generate attribute documentation #104

Closed
manishtomar opened this issue Oct 5, 2016 · 12 comments
Closed

Generate attribute documentation #104

manishtomar opened this issue Oct 5, 2016 · 12 comments

Comments

@manishtomar
Copy link

It would nice if sphinx based documentation can be automatically generated from validators when possible. For example, following class

@attr.s
class SelfHeal(object):
    """
    A class that triggers convergence on all the groups over a time range.

    :ivar clock: Reactor providing timing APIs
    :vartype: :obj:`IReactorTime`
    :ivar dispatcher: Effect dispatcher to perform all effects
        (ZK, CASS, log, etc)
    :vartype dispatcher: Either :obj:`ComposedDispatcher` or
        :obj:`TypeDispatcher`
    :ivar callable config_func: Callable used when calling
        :func:`tenant_is_enabled`
    :ivar float time_range: Seconds over which convergence triggerring will be
        spread evenly
    :ivar log: :obj:`BoundLog` object used to log messages
    :ivar list _calls: List of :obj:`IDelayedCall` objects. Each object
        represents scheduled call to trigger convergence on a group
    """

    clock = attr.ib(validator=attr.validators.provides(IReactorTime), 
)
    dispatcher = attr.ib(
        validator=attr.validators.instance_of((ComposedDispatcher,
                                               TypeDispatcher)))
    config_func = attr.ib()
    time_range = attr.ib(validator=attr.validators.instance_of(float),
                         convert=float)
    log = attr.ib(
        validator=attr.validators.instance_of(BoundLog),
        convert=lambda l: l.bind(otter_service="selfheal"),
        cmp=False)
    _calls = attr.ib(default=attr.Factory(list))

could be simplified by

@attr.s(doc=True)
class SelfHeal(object):
    """
    A class that triggers convergence on all the groups over a time range.
    """

    clock = attr.ib(validator=attr.validators.provides(IReactorTime), 
                    doc="Reactor providing timing APIs")
    dispatcher = attr.ib(
        validator=attr.validators.instance_of((ComposedDispatcher,
                                               TypeDispatcher)),
        doc="Effect dispatcher to perform all effects")
    config_func = attr.ib(doc="Callable used when calling :func:`tenant_is_enabled`")
    time_range = attr.ib(
        validator=attr.validators.instance_of(float), convert=float,
        doc="Seconds over which convergence triggerring will be spread evenly")
    log = attr.ib(
        validator=attr.validators.instance_of(BoundLog),
        convert=lambda l: l.bind(otter_service="selfheal"),
        cmp=False, doc="Object used to log messages")
    _calls = attr.ib(
        default=attr.Factory(list),
        doc=("Each object represents scheduled call to trigger convergence "
             "on a group"))

Since the docs are next to attribute definition it makes the docs more comprehensible.

@hynek
Copy link
Member

hynek commented Oct 5, 2016

Um do you have any idea on how to achieve that? :)

@manishtomar
Copy link
Author

It might be easier to generate the type if attr has explicit type information based on #97 as part of the doc. If not, one can still do some good based on the validators chosen. So an attribute with instance_of(float) can generate type doc as :param float attr since float is built-in type function. It should be possible for custom types by looking at its class name like for log in the example above. However, I am not sure if it's possible to get FQCN from the type. Docs for types that cannot be clearly inferred can be skipped.

@jtf621
Copy link

jtf621 commented Feb 16, 2017

I think adding a doc keyword to attr.ib would be very helpful. I am looking to have the interactive help command give more details/a better doc string for the init function in addition to the sphinx docs.

Is there agreement that this is a useful feature to add? Are there any plans to implement this?

@manishtomar
Copy link
Author

Is there agreement that this is a useful feature to add?

Will need @hynek 's executive approval :)

Are there any plans to implement this?

I can try to implement over a few weekends. I am super slammed on weekdays and also some weekends :( unless someone else would like contribute before that.

@Tinche
Copy link
Member

Tinche commented Feb 16, 2017

Why don't you make an addon library. This doesn't have to go into attrs itself at first.

def docattr(docstring, *args, **kwargs):
    kwargs['metadata'] = {'doc': docstring}
    return attr.ib(*args, **kwargs)

@attr_doc
@attr.s
class A:
     a = docattr('This is a.')

The implementation of @attr_doc left as an exercise to the reader, but not that complicated.

@jtf621
Copy link

jtf621 commented Feb 18, 2017

@manishtomar thanks for the insight. If @hynek can weight in on wheter this fits into attrs or not would be helpful.

I do think that a simple way to inject a doc string into the attr.ib call will make the code more self documenting in the realm where I am using attrs.

If not, the addon approach that @Tinche suggested might be the way to go.

@hynek
Copy link
Member

hynek commented Feb 18, 2017

My original question was kind of how to achieve the complete autodoc?

IOW how do you want to go from:

@attr.s
class C:
    """This is class C."""
    x = attr.ib(doc="This is attribute x.")

to a docstring like:

This is class C.

:ivar x: This is attribute x.

Do you want attrs to generate the ivar block for you and append it or what’s the plan?

I guess my overall question is: what do you want to do with the doc string that warrants to add it rather than go Tin’s suggestion of metadata?

@manishtomar
Copy link
Author

Do you want attrs to generate the ivar block for you and append it

Yes.

what do you want to do with the doc string that warrants to add it rather than go Tin’s suggestion of metadata?

I just want attribute's documentation to live next to its definition and have it generate the ivar block. I am fine with either of suggestion. Although having in attrs seems nicer.

@hynek
Copy link
Member

hynek commented Feb 20, 2017

I guess we could add it optionally? Something like @attr.s(add_ivar_docstrings=True)?

@manishtomar
Copy link
Author

I guess we could add it optionally?

Oh yes. My intention was always it being optional.

Something like @attr.s(add_ivar_docstrings=True)?

I was thinking more like attr.s(doc=True) to make it terse. But I am fine with any of the names.

@pombredanne
Copy link
Contributor

@hynek do you prefer to track the requirement for documentation in this ticket or in #357 or may be these two tickets are different?

@hynek
Copy link
Member

hynek commented Apr 9, 2018

I think they are very much the same. Let’s use #357 since it’s more discoverable atm.

@hynek hynek closed this as completed Apr 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants