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

[WAIT TO MERGE] Store deprecation metadata on functions for docs generation #9611

Closed

Conversation

Eric-Arellano
Copy link
Collaborator

@Eric-Arellano Eric-Arellano commented Feb 17, 2023

Summary

Rework of #8600 and part of #1680.

Our goal is to start putting .. deprecated :: directives in our docs. But, we don't want to ask developers to manually put those in the docstring, as that would duplicate the @deprecated_* decorators we already have for runtime warnings.

So, we keep the decorators, but have them now store structured metadata by adding a __qiskit_deprecations__ attribute to relevant function objects. Then, the Sphinx extension from #1680 will look for this attribute and add the documentation.

Details and comments

Why not take the approach of #8600, where we dynamically change the __doc__ of each class to have the deprecation block inside it? It resulted in too much of a performance hit at runtime.

Why store the data in __qiskit_deprecations__, rather than Sphinx learning how to parse the decorators? a) It would be harder to get the parsing code working, and b) it is too brittle, e.g. not working with us adding future decorators or how Nature has its own decorators. Instead, we have a standardized and structured way for anyone to set this metadata.

@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Feb 17, 2023

Pull Request Test Coverage Report for Build 4283174916

  • 28 of 29 (96.55%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.005%) to 85.346%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/utils/deprecation.py 28 29 96.55%
Totals Coverage Status
Change from base Build 4283043370: 0.005%
Covered Lines: 67544
Relevant Lines: 79141

💛 - Coveralls

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

This definitely looks like the most sensible way of going about this, thanks for taking it on.

qiskit/utils/deprecation.py Outdated Show resolved Hide resolved
qiskit/utils/deprecation.py Outdated Show resolved Hide resolved
@jakelishman
Copy link
Member

I forgot the full context: does this need a rebase over #9616, or was it a partial attempt that we decided to go a different way on?

@Eric-Arellano Eric-Arellano changed the title [wip] Store deprecation metadata on functions for docs generation Store deprecation metadata on functions for docs generation Feb 24, 2023
@Eric-Arellano
Copy link
Collaborator Author

I forgot the full context: does this need a rebase over #9616

Fixed now. I do this pattern a lot: "prework PRs", where I separate out refactors from the actual feature change. It makes reviews smaller and easier to understand, and reduces risk if we need to revert something.

This is now ready to land, so long as we are okay with the approach taken in #1680 with how to handle deprecated arguments, which Luciano and I weren't sure about at first. But him and I reached consensus. See the details of that PR description.

@Eric-Arellano Eric-Arellano marked this pull request as ready for review February 24, 2023 14:17
@Eric-Arellano Eric-Arellano added the Changelog: None Do not include in changelog label Feb 24, 2023
@HuangJunye HuangJunye self-assigned this Feb 27, 2023
Comment on lines +42 to +50
func_name = func.__name__
old_kwarg_to_msg = {}
for old_arg, new_arg in kwarg_map.items():
msg_suffix = (
"will in the future be removed." if new_arg is None else f"replaced with {new_arg}."
)
old_kwarg_to_msg[
old_arg
] = f"{func_name} keyword argument {old_arg} is deprecated and {msg_suffix}"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This logic needs to live here, rather than the helper function _rename_kwargs, because we need to call _DeprecationMetadataEntry().store_on_function() on the wrapper rather than the inner func

category: Type[Warning] = DeprecationWarning,
) -> None:
for old_arg, new_arg in kwarg_map.items():
if old_arg in kwargs:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I inverted the conditional to early return via continue if this is False. It results in less nesting.

Copy link
Collaborator

@HuangJunye HuangJunye left a comment

Choose a reason for hiding this comment

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

I like the overall approach. Thanks a lot for working on this! I just left some in line comments. They are more questions for checking my understandings than really comments.

Comment on lines +37 to +38
del old_arg
del new_arg
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are these lines added here in order to pass linting?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Exactly. Pylint is overly pedantic

del new_arg

self.assertEqual(
getattr(my_func, _DeprecationMetadataEntry.dunder_name),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Will this return the whole list of deprecation metadata associated with the deprecated function and deprecated arguments?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, the attribute __qiskit_deprecations__ stores a List[_DeprecationMetadataEntry] on the function object. This is key, it allows us to store >1 deprecation on a function, e.g. if multiple args have been deprecated.

@Eric-Arellano Eric-Arellano changed the title Store deprecation metadata on functions for docs generation [WAIT TO MERGE] Store deprecation metadata on functions for docs generation Feb 28, 2023
@Eric-Arellano
Copy link
Collaborator Author

Superseded by #9685.

@Eric-Arellano Eric-Arellano deleted the store-deprecation-metadata branch February 28, 2023 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: None Do not include in changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants