You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
the decorator is also available in earlier Python versions using the official backport in typing_extensions.
What's especially nice about Python's built-in deprecation decorator is that it is recognized statically, so IDEs can tell users not to use the deprecated function from-the-get-go, not once they try to run their code.
Describe the desired outcome
We make typing _extensions a run-time dependency. This is very safe since it’s made by the python core devs for backporting Python’s typing-related features.
We make our own deprecation tools thin wrappers of the ones in base python.
Additional context
We have some additional args, e.g. “since”. typing.deprecated takes the whole message string. We can provide a function deprecation_message that constructs this message identically to how we do it now.
First of all: Does typing_extensions provide nightly wheels? As a required dependency, we need to be able to test against its dev version effectively. Also, is it diligent in providing wheels for unreleased Python in advance?
Secondly: This needs to be discussed more widely over at astropy-dev. This machinery is widely used in the ecosystem. We don't want to break downstream unnecessarily, especially if the API mapping isn't 1-to-1.
First of all: Does typing_extensions provide nightly wheels? As a required dependency, we need to be able to test against its dev version effectively. Also, is it diligent in providing wheels for unreleased Python in advance?
I looked at their release history and they do have release candidates. The package evolves with Python PEPs so it's not a nightly cadence. Also since it's driven by PEPs there's never anything too surprising, I think mostly bugs (they have bug fix patches).
It's a pure python package, and yes can be installed and is tested for upcoming python versions.
Secondly: This needs to be discussed more widely over at astropy-dev. This machinery is widely used in the ecosystem. We don't want to break downstream unnecessarily, especially if the API mapping isn't 1-to-1.
My suggestion is to use typing[_extensions].deprecated (depending on the python version) to deprecate our deprecation decorator! No code breaks, only issues a DeprecationWarning with a message explaining the transition.
Or we move Astropy's deprecated into a module-level __getattr__ in astropy.util.decorators. When a library imports Astropy's deprecated it emits the warning to use typing[_extensions].deprecated instead. This way we aren't emitting a deprecation warning when astropy.utils.decoratos.deprecated is called, but only at startup when it's imported. Much less confusing!
e.g.
def__getattr__(name):
....
ifname=="deprecated":
warning.warn("`astropy.utils.decorators.deprecated` is being phased out in favor of Python's builtin `typing.deprecated` (py3.12+) and backport at `typing_extensions.deprecated` (py3.12-). If you are a library maintainer please go to Astropy's transition document. If you are using a library please open an Issue / PR asking / helping the library to upgrade to `typing.deprecated`.", category=DeprecationWarning)
defastropy_deprecated():
...
returnastropy_deprecated
...
Both our decorator and the new one in python acccept the message argument (we just have the additional stuff like "since", "name", and "alternative"), so we can already make the helper function deprecation_message which take all the extra arguments our function uses to construct the message. The deprecation period of astropy.util.decorators.deprecated can be then
be a full Astropy version, or until py3.12!
fromtypingimportdeprecatedfromastropy.utils.decoratorsimportdeprecation_message# or in a different sub-module@deprecated(deprecation_message(since=..., message=..., name=..., alternative=...),category=AstropyDeprecationWarning, # replaces warning_type and pending (this is optional)stack_level=..., # this is new (and optional))
...
How about just using typing.deprecated under the hood? That ensures there is no API change, yet presumably the IDEs will recognize deprecated functions still since typing.deprecated adds a __deprecated__ attribute. Obviously, this does not preclude deprecating our own decorators, but it separates the concerns.
We can and should do this before deprecating deprecated!
If it doesn't work under the hood, then the transition won't be seamless over-the-hood.
I still think it's good to get rid of our deprecated because typing.deprecated is also recognized statically, while I don't believe ours will be because Astropy is not a statically-typed library and lacks a py.typed.
Lessons learned in #15307: typing.deprecated isn't a 1-to-1 replacement. Our decorator handles classmethod and staticmethod better than does typing.deprecated. Also our decorator modifies the docs where typing.deprecated does not. So we might not want to deprecate our decorator any time soon, just keep on eye on typing.deprecated to see if it ever reaches feature parity.
Can we change our code to set the new __deprecated__ attribute just like typing.deprecated does? I like very much the idea to be warned that one uses a deprecated function/class already in the editor!
Hi @Rekaniry! This is perhaps a challenging Issue to tackle, but you are welcome to try! #15301 (comment) outlines the difficulties.
My suggestion would be to make 3 functions:
make_depr_msg. This should make a deprecation message equivalent to what is currently done in Astropy.
depr_doc. This should modify the decorated function's docstring in the same way that is currently done in Astropy.
deprecate: This is a rewrite of Astropy's implementation, but just does warnings.deprecate(make_depr_msg(), ...)(depr_doc(func))
Then statically-understood deprecations would look like
fromwarningsimportdeprecated@deprecated(make_depr_msg(...)) # static analysis sees the correct function@depr_doc(...) # docs are modified separatelydeffunction(...): ...
And the statically not-understood version would be:
from astropy.utils.decorators import deprecated # static analysis doesn't know this calls warnings.deprecated.
@deprecated(...)
def function(...): ...
Activity
pllim commentedon Sep 9, 2023
First of all: Does
typing_extensionsprovide nightly wheels? As a required dependency, we need to be able to test against its dev version effectively. Also, is it diligent in providing wheels for unreleased Python in advance?Secondly: This needs to be discussed more widely over at astropy-dev. This machinery is widely used in the ecosystem. We don't want to break downstream unnecessarily, especially if the API mapping isn't 1-to-1.
nstarman commentedon Sep 9, 2023
I looked at their release history and they do have release candidates. The package evolves with Python PEPs so it's not a nightly cadence. Also since it's driven by PEPs there's never anything too surprising, I think mostly bugs (they have bug fix patches).
It's a pure python package, and yes can be installed and is tested for upcoming python versions.
My suggestion is to use
typing[_extensions].deprecated(depending on the python version) to deprecate our deprecation decorator! No code breaks, only issues aDeprecationWarningwith a message explaining the transition.pllim commentedon Sep 9, 2023
Deprecating something that is supposed to emit deprecation warning would be too confusing. We might have to batch PR downstream packages.
nstarman commentedon Sep 9, 2023
Or we move Astropy's
deprecatedinto a module-level__getattr__inastropy.util.decorators. When a library imports Astropy'sdeprecatedit emits the warning to usetyping[_extensions].deprecatedinstead. This way we aren't emitting a deprecation warning whenastropy.utils.decoratos.deprecatedis called, but only at startup when it's imported. Much less confusing!e.g.
Both our decorator and the new one in python acccept the
messageargument (we just have the additional stuff like "since", "name", and "alternative"), so we can already make the helper functiondeprecation_messagewhich take all the extra arguments our function uses to construct the message. The deprecation period ofastropy.util.decorators.deprecatedcan be thenbe a full Astropy version, or until py3.12!
The transition process is then approximately
From
To
mhvk commentedon Sep 11, 2023
How about just using
typing.deprecatedunder the hood? That ensures there is no API change, yet presumably the IDEs will recognize deprecated functions still sincetyping.deprecatedadds a__deprecated__attribute. Obviously, this does not preclude deprecating our own decorators, but it separates the concerns.nstarman commentedon Sep 11, 2023
We can and should do this before deprecating
deprecated!If it doesn't work under the hood, then the transition won't be seamless over-the-hood.
I still think it's good to get rid of our
deprecatedbecausetyping.deprecatedis also recognized statically, while I don't believe ours will be because Astropy is not a statically-typed library and lacks apy.typed.nstarman commentedon Sep 12, 2023
Lessons learned in #15307:
typing.deprecatedisn't a 1-to-1 replacement. Our decorator handlesclassmethodandstaticmethodbetter than doestyping.deprecated. Also our decorator modifies the docs wheretyping.deprecateddoes not. So we might not want to deprecate our decorator any time soon, just keep on eye ontyping.deprecatedto see if it ever reaches feature parity.[-]Deprecate our deprecation machinery[/-][+]refactor our deprecation machinery[/+]pllim commentedon Sep 12, 2023
Good to know. Thanks for checking!
mhvk commentedon Sep 12, 2023
Can we change our code to set the new
__deprecated__attribute just liketyping.deprecateddoes? I like very much the idea to be warned that one uses a deprecated function/class already in the editor!pllim commentedon Sep 12, 2023
@mhvk , that sounds reasonable for v6 and should be a separate issue/PR. Thanks!
nstarman commentedon Sep 12, 2023
See #15310 (comment).
I added the attribute
and cherry-picked the initial code cleanup and improvement commits.Rekaniry commentedon Oct 30, 2024
Hello guys, can I try to help on this issue?
nstarman commentedon Oct 30, 2024
Hi @Rekaniry! This is perhaps a challenging Issue to tackle, but you are welcome to try!
#15301 (comment) outlines the difficulties.
My suggestion would be to make 3 functions:
make_depr_msg. This should make a deprecation message equivalent to what is currently done in Astropy.depr_doc. This should modify the decorated function's docstring in the same way that is currently done in Astropy.deprecate: This is a rewrite of Astropy's implementation, but just doeswarnings.deprecate(make_depr_msg(), ...)(depr_doc(func))Then statically-understood deprecations would look like
And the statically not-understood version would be: