Skip to content

DOC: Include alternatives to deprecations in the documentation #22038

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

Merged
merged 3 commits into from
Jan 5, 2022

Conversation

StefRe
Copy link
Contributor

@StefRe StefRe commented Dec 22, 2021

PR Summary

There are 90 deprecations currently, for 38 of which alternatives are given in the deprecation warning. These alternatives are not included, however, in the documentation.
The first commit enables inclusion of alternatives along with links in the documentation and the second commit adds links to the documentation for the existing alternatives if they refer to another function or class.

Current:

Documentation: grafik

New:

Documentation: grafik

Include alternatives to deprecations in the documentation

- add `alternative` and `addendum` to the documentation by including
  them in the second argument of the `.. deprecated::` directive
- allow for backticks and optional reference to create links to the
  mentioned alternatives in the documentation
- remove these additional links and backticks in the deprecation
  warning message that is emitted when using a deprecated item

Example:
@_api.deprecated("3.5", alternative="`num2date(e).timestamp() <.num2date>`"
will create the directive

.. deprecated:: 3.5
   Use `num2date(e).timestamp() <.num2date>` instead.

which creates a link to matplotlib.dates.num2date with the caption
num2date(e).timestamp(). The deprecation warning message will read
"... Use num2date(e).timestamp() instead."

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • [N/A] New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • [N/A] API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

@StefRe StefRe marked this pull request as draft December 22, 2021 16:40
@StefRe StefRe force-pushed the enh/doc_deprecation branch from 383d68f to f308421 Compare December 22, 2021 17:24
@StefRe StefRe marked this pull request as ready for review December 22, 2021 18:50
@tacaswell tacaswell added this to the v3.6.0 milestone Dec 22, 2021
@tacaswell
Copy link
Member

I think this is 💯 from a functionality point of view, but I am a bit worried about inventing a new link markup scheme and the re-writing to rst.

Can we just say "this is standard rst that will be rendered" and let the rst leak out to the in-line error message? If we think that is unacceptable, I would rather add another argument to the deprecation tools to allow what shows up in the documentation to be customized (rather than just dropping the value of alternative in). Text processing is hard in general and in my experience text-processing via regex can be very brittle, accepting a bit of duplication in code that is explicitly going to be deleted is probably less work overall than understanding some (admittedly clever) text mutation rules.

@StefRe
Copy link
Contributor Author

StefRe commented Dec 23, 2021

Maybe I should have better described the PR as "Allow rst in alternative for documentation and retrieve plain text from that rst for warnings".

inventing a new link markup scheme and the re-writing to rst

There is no new scheme or any re-writing to rst, everything is standard rst. The alternative is just added as is to the second argument of .. deprecated:: (which used to be just message), only the words Use and instead are prepended/appended for readability:

        second_arg = ' '.join([t.strip() for t in
                               (message, f"Use {alternative} instead."
                                if alternative else "", addendum) if t])


text-processing via regex can be very brittle

This is certainly true and I didn't mean to cover all possible corner cases when converting the rst into plain text for the warning. Complex rst expressions with nested and escaped `, < and > chars or malformed rst expressions will not be correctly handled by the regex, but what will happen: if it's a malformed rst expression, sphinx will issue a warning or an error when building the docs and the error should be fixed. If the rst is valid but too complex for the regex, some garbled text will be included in the warning message and, hopefully, someone will open an issue here (btw, I can't think of any case where such complex rst would be needed for an alternative, but it could happen of course; the three standard cases are covered by the test, I could add more exotic cases to the test). There won't be any runtime error or anything affecting the functionality of matplotlib.

Possible alternatives:

  1. show the rst as-is in the warning

    • if its just a backticked link to another function it's not a big deal, rst where link and caption are different looks a bit strange
  2. disallow usage of rst in alternative

    • documentation would be plain text only without links (and not to use rst can't be enforced anyway)
    • of course this is better than having no documentation of the alternative at all, but why not using the means provided by sphinx
  3. add a new parameter alternative_rst to _api.deprecated etc.

    • quick and easy at the cost of writing the alternative two times
    • saves two lines of code: if alternative: alternative = re.sub(r"`([^`]*?) *<.*?>`|`\.?(.+?)`", r"\1\2", alternative)
    • API change

@StefRe StefRe force-pushed the enh/doc_deprecation branch from f308421 to c97c41f Compare December 23, 2021 11:34
@StefRe
Copy link
Contributor Author

StefRe commented Dec 23, 2021

I just saw that the space between the caption and the link is optional (even not recommended although the examples in the rst spec contain spaces), so I changed the wording in the docs, the regex and the alternatives with separate captions accordingly. I also changed the test a bit to make it easier to read.

@tacaswell
Copy link
Member

There is no new scheme or any re-writing to rst,

I misunderstood what was going on 🐑 . I thought that the transform was on the way into the rst not on the way into the warning text. I stand by my logic, but it is not relevant to this PR.


I do not think option 1 is terrible as even though it might look a bit funny, it does give more information about what is going on (by pointing to the class / method of interest). We have had some issues in the past where the alternative made perfect sense to us when we reviewed the PR (because we had the context of what class was being edited), it made no sense to users (because the class the method that was suggested as an alternative was on was not clear). It would be a shame to have that information in the source and documentation, but not visible at run time.

@StefRe StefRe force-pushed the enh/doc_deprecation branch from c97c41f to fcbc73f Compare December 24, 2021 07:06
@dstansby
Copy link
Member

This is amazing! I'm very pro overall.

I'm also on the side of option 1 from #22038 (comment). I think the RST formatted text (at least in all the cases and types used in this PR) is parseable as plain text, and the removal of the RST markup isn't worth the hassle of maintaining a rather complex regular expression substitutuion.

@StefRe
Copy link
Contributor Author

StefRe commented Dec 29, 2021

I removed the rst text processing and pushed it as a separate commit (so it could be reverted easily in case someone complains about strange deprecation warning messages).

Copy link
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably didn't need to bother with the 3.4 deprecations as they're about to be (or already) deleted.

@StefRe StefRe force-pushed the enh/doc_deprecation branch from 9b4ade5 to 40580ac Compare January 5, 2022 12:22
StefRe added 3 commits January 5, 2022 13:25
- add `alternative` and `addendum` to the documentation by including
  them in the second argument of the `.. deprecated::` directive
- allow for backticks and optional reference to create links to the
  mentioned alternatives in the documentation
- remove these additional links and backticks in the deprecation
  warning message that is emitted when using a deprecated item

Example:
@_api.deprecated("3.5", alternative="`num2date(e).timestamp()<.num2date>`"
will create the directive

.. deprecated:: 3.5
   Use `num2date(e).timestamp()<.num2date>` instead.

which creates a link to matplotlib.dates.num2date with the caption
num2date(e).timestamp(). The deprecation warning message will read
"... Use num2date(e).timestamp() instead."
to convert rst to plain text for warnings. This reverts the rst text
processing of commmit "Include alternatives to deprecations in the
documentation" as it was considered to be too complex to maintain
or potentially error prone.
@StefRe StefRe force-pushed the enh/doc_deprecation branch from 40580ac to baa99d3 Compare January 5, 2022 12:32
@StefRe StefRe requested a review from QuLogic January 5, 2022 15:14
@tacaswell tacaswell merged commit 1675a04 into matplotlib:main Jan 5, 2022
@tacaswell
Copy link
Member

Thank you @StefRe !

@StefRe StefRe deleted the enh/doc_deprecation branch January 6, 2022 07:07
@jklymak
Copy link
Member

jklymak commented Jan 7, 2022

OK, so this breaks the docs build if I have:

@_api.deprecated(
         "3.6", alternative="figure.get_layout_engine().set(**kwargs)")
    def set_constrained_layout_pads(self, **kwargs):

With WARNING: Inline strong start-string without end-string. Anything to be done here? Could just remove **kwargs...

@timhoffm
Copy link
Member

timhoffm commented Jan 7, 2022

You may try \*\*kwargs as a workaround.

@jklymak
Copy link
Member

jklymak commented Jan 7, 2022

But that looks terrible in the actual warning?

@StefRe
Copy link
Contributor Author

StefRe commented Jan 7, 2022

@jklymak I think enclosing it in backticks "`figure.get_layout_engine().set(**kwargs)`"should be enough to silence the warning . This will also neatly format the alternative as code in the docs. If you want to link to the set method of the layout engine as well, you could write "`figure.get_layout_engine().set(**kwargs)<Layout_engine.set>`" (given that get_layout_engine returns a Layout_engine object).

@oscargus
Copy link
Member

oscargus commented Mar 1, 2022

@meeseeksdev backport to 3.5.x

@lumberbot-app
Copy link

lumberbot-app bot commented Mar 1, 2022

Something went wrong ... Please have a look at my logs.

It seems that the branch you are trying to backport to does not exist.

@oscargus
Copy link
Member

oscargus commented Mar 1, 2022

@meeseeksdev backport to v3.5.x

meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Mar 1, 2022
tacaswell added a commit that referenced this pull request Mar 1, 2022
…038-on-v3.5.x

Backport PR #22038 on branch v3.5.x (DOC: Include alternatives to deprecations in the documentation)
@QuLogic QuLogic modified the milestones: v3.6.0, v3.5.2 Mar 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants