-
-
Notifications
You must be signed in to change notification settings - Fork 18.3k
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
DOC: add guide on shared docstrings #20016
DOC: add guide on shared docstrings #20016
Conversation
Oh, I put this in contributing, but it should go in the docs file once that's ready. |
Thanks!
Ah, yes, that's something I didn't think about. But, as long as the templates are used in classes that are never exposed to users (like NDFrame and IndexOpsMixin), then this is not a problem. But should check that we also don't use the system in actual user classes (eg I think base Index also has shared docstrings that are substituted in the index subclasses) |
Codecov Report
@@ Coverage Diff @@
## master #20016 +/- ##
==========================================
- Coverage 91.85% 91.84% -0.01%
==========================================
Files 152 152
Lines 49249 49236 -13
==========================================
- Hits 45237 45223 -14
- Misses 4012 4013 +1
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looked at the doc guide now as well, looks good.
Maybe worth to mention that often Appender
is used to inherit a docstring from partent class, also when no substitution is done (for Index this is eg the majority of the cases)
doc/source/contributing.rst
Outdated
for the user reading. It comes at the cost of some complexity when writing. | ||
|
||
Each shared docstring will have a base template with variables, like | ||
``%(klass)s``. The variables filled in later on using the ``Substitution`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filled -> are filled
doc/source/contributing.rst
Outdated
where ``template`` may come from a module-level ``_shared_docs`` dictionary | ||
mapping function names to docstrings. Wherever possible, we prefer using | ||
``Appender`` and ``Substitution``, since the docstring-writing processes is | ||
slightly closer to normal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't fully understand this reasoning (both with using %
or Substitution
you can write a normal docstring and append it with baseclass.method.__doc__
?)
@TomAugspurger I made a PR doing such a clean-up for Index (as this is one where we don't have always a non-user exposed base class where it is no problem to have non-substituted values): #20022 |
this is just the guide which is codifying current practice which is good maybe add something about actually putting functions in Series/Frame that render the doc strings (while the actual doc string itself is in generic.py) |
no, it is not exactly codifying the current practice, but a slight variation of it (without There is one example in this PR (see for fillna in the diff, or #20022 for a bigger example) |
my only comment is actually on your other PR #20022. Should clarify when should be using _shared_docs, I agree in Index subclasses we should prob try not to use it as much as its cumbersome. Though it is nice to have the correct return class rather than Index as the generic return value. Its more informative. |
Can you then comment there?
The proposal is to never use it, at least if there is a base class that can hold the template docstrings (like NDFrame). For classes like Index (where the base class is already user exposed), we might discuss further. But I show in the PR #20022 that at least currently we don't actually do this much (4 times for all Index methods). |
@jreback for NDFrame, we certainly still use the substitution with shared_kwargs, so are you ok with the approach in this PR for that part of the codebase? (use |
oh I c now what you did. yes I much prefer that, its way more explict. |
I know that this approach is based on the current one, and may be it's too ambitious to define a brand-new one, but given that we'll be working in most of the docstrings, I think it's worth suggesting. Correct me if I'm wrong, but if the general case it's to reuse the docstring of the parent class as a template, why doesn't the decorator get it for us by default? Also, if Then, I'm sure you're already use to it, but I think naming the decorator So, with the next example:
I think the decorator should be able to automatically do the right thing. And for special cases, the next syntax could also be supported:
or
Also, may be it's a good time to use the new formatting syntax I think this adds a bit of complexity to the decorator, but the code mode clear, so I think it's worth. Am I missing something? |
Agreed here, I think "AppendDocstring" or "AddDocstring" (or lower case) would already be more explicit (it is used for more than inheriting docstrings, so "reuse_parent_docstring" might also be confusing in certain cases).
I have thought about this as well, but the problem is that there are many parent classes, for example for Series it are in order: IndexOpsMixin, NDFrame, PandasObject, etc. So already in this case, it would not work out of the box for Series, as the majority of the methods needs to inherit from NDFrame, and not IndexOpsMixin. For DatetimeIndex there are even 5 parent classes before getting to
The problem is that this does not work with strings where you also want to use { itself (for example for parameter type description listing the possibilities). It would also be annoying to have to do |
A few things:
Use method-style when the parent class, where the template is written, is not public. This include NDFrame and I think much of IndexOpsMixin. I haven't looked at the groupby ones.
If people are ok with that policy I'll add it to this PR. |
The groupby ones mostly just use variables holding a template (without storing it in a dict), which I think is good. And IndexOpsMixin can all use the method-style (as this is not public). |
doc/source/contributing.rst
Outdated
@@ -1077,5 +1077,78 @@ The branch will still exist on GitHub, so to delete it there do:: | |||
|
|||
git push origin --delete shiny-new-feature | |||
|
|||
Sharing Docstrings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a ref here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do. Going to wait till the docstring guide is merged and I move it to that document so that the name makes sense.
doc/source/contributing.rst
Outdated
|
||
Each shared docstring will have a base template with variables, like | ||
``%(klass)s``. The variables filled in later on using the ``Substitution`` | ||
decorator. Finally, docstrings can be appended to with the ``Appender`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we reference the Substituion/Appender via links to the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, there isn't a good way to link to a specific function. I think you can only do a specific line (with or without a commit). If we pin the commit things may go out of date. If don't do a specific commit then the line number will become incorrect.
doc/source/contributing.rst
Outdated
decorator. | ||
|
||
In this example, we'll create a parent docstring normally (this is like | ||
``pandas.core.generic.NDFrame``. Then we'll have two children (like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we'll -> we will, don't use contractions :>
doc/source/contributing.rst
Outdated
In this example, we'll create a parent docstring normally (this is like | ||
``pandas.core.generic.NDFrame``. Then we'll have two children (like | ||
``pandas.core.series.Series`` and ``pandas.core.frame.DataFrame``). We'll | ||
substitute the children's class names in this docstring. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
childrens'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Children is a plural noun not ending in "s", so children's is the correct plural possessive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, yeah never get these right :>. We'll -> we will
doc/source/contributing.rst
Outdated
|
||
Notice two things: | ||
|
||
1. We "append" the parent docstring to the children docstrings, which are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we use *
rather than numbering generally (though this is slightly more clear)
doc/source/contributing.rst
Outdated
|
||
1. We "append" the parent docstring to the children docstrings, which are | ||
initially empty. | ||
2. Python decorators are applied inside out. So the order is Append then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double backticks on Append/Substitution
doc/source/contributing.rst
Outdated
``Appender`` and ``Substitution``, since the docstring-writing processes is | ||
slightly closer to normal. | ||
|
||
See ``pandas.core.generic.NDFrame.fillna`` for an example template, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you point to actual code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue with linking specific lines / commits, though maybe this one is OK, since we're giving an example.
But unfortunately I can't link to the correct version, since the correction is in this PR :)
doc/source/contributing.rst
Outdated
@@ -1077,5 +1077,78 @@ The branch will still exist on GitHub, so to delete it there do:: | |||
|
|||
git push origin --delete shiny-new-feature | |||
|
|||
Sharing Docstrings | |||
================== | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this line is not long enough
doc/source/contributing.rst
Outdated
In this example, we'll create a parent docstring normally (this is like | ||
``pandas.core.generic.NDFrame``. Then we'll have two children (like | ||
``pandas.core.series.Series`` and ``pandas.core.frame.DataFrame``). We'll | ||
substitute the children's class names in this docstring. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, yeah never get these right :>. We'll -> we will
Moved to the docstring guide now that it's in master. |
@jorisvandenbossche @datapythonista |
Not sure, it is linked too from contributing.rst part about documentation. I am fine with adding it to the main index.rst, it's already a disaster anyhow :-) |
|
||
See ``pandas.core.generic.NDFrame.fillna`` for an example template, and | ||
``pandas.core.series.Series.fillna`` and ``pandas.core.generic.frame.fillna`` | ||
for the filled versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fillna is actually not a really good example, as it has an example section only targetting DataFrame .. (but anyhow, that is another issue :))
I linked |
Yes I’m happy with it being split.
Sphinx warns if there’s source files that aren’t in a toctree. But it’ll be a bit before our doc build is warning free.
…________________________________
From: Marc Garcia <[email protected]>
Sent: Monday, March 12, 2018 5:34:59 PM
To: pandas-dev/pandas
Cc: Tom Augspurger; Mention
Subject: Re: [pandas-dev/pandas] Shared doc guide (#20016)
I linked contributing_docstring.rst from contributing.rst. Personally I think contributing.rst is long enough to be splited. If that sounds good, we can probably leave it out of any toctree until then. I'm happy to take a looks at it when I find some time.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<#20016 (comment)>, or mute the thread<https://github.com/notifications/unsubscribe-auth/ABQHIpabu5aMRchc4nXOpMTCjQQgDa4Iks5tdvgTgaJpZM4SfCTh>.
|
Anything else you'd like to see here? |
@TomAugspurger can you update with master? |
Done. |
Thanks! |
closes #16446
xref #19932
cc @jorisvandenbossche
The main change in best practices here is the recommendation is that
Appender
is only for appending.Substitution
should be used for substituting values.See the changes to
fillna
that this policy requires. Personally, I find the new way clearer than the old way.Appender(NDFrame.method.__doc__)
better thanAppender(_shared_docs['name'] % kwargs)
Substitution(**kwargs)
better than%
formatting.The downsides is that we don't have the template in a dictionary anymore and the docstring in
NDFrame
has to be the template, it can't have its variables substituted. I think that's OK.