PEP 702: Marking deprecations using the type system
I just posted PEP 702, Marking deprecations using the type system: https://peps.python.org/pep-0702/. The PEP proposes adding an @typing.deprecated() decorator to mark classes, methods, and functions as deprecated. Type checkers will leverage this decorator to inform users about their usage of deprecated features. I welcome feedback on any aspect of the proposal. However, two main points came up in initial discussions: - The proposal specifies that the decorator does not raise any runtime DeprecationWarning. Should we change this, perhaps with an opt-in flag? - The proposal allows users to mark classes, functions, and overloads as deprecated, but there are other things that may want deprecation. Should we add support for deprecating modules, or variables, or parameters? Happy New Year!
Thanks for writing this up! It's somewhat unfortunate to not issue a runtime warning, especially since I imagine most users would ideally want one. The SC has also indicated they'd like static typing to feel more cohesive with the runtime, so we should try harder to find something that works for both. As we discussed and you mention here, an opt-in kwarg (a la Protocol's runtime_checkable) seems like a promising solution. In fact, thinking about it more, I think it's feasible for runtime warning to be opt-out. Walking through the cases in a little bit more detail:
When the decorator is applied to a class or an overload, the warning would not be raised as expected.
Users may want to control the warn call in more detail (e.g., changing
I think there are reasonable possible semantics for decorating a class. https://pypi.org/project/Deprecated/ is very popular (in the top 200 on PyPI) and it warns on instantiation: https://deprecated.readthedocs.io/en/latest/tutorial.html#deprecated-class This seems to me a reasonable default; users can opt-out if they need something different. Overloads are trickier. However, I think it's reasonable that type checkers could provide an error if a deprecated overload isn't opted out of the runtime warning (if we have an opt-in flag, type checkers would probably also want such a check). If we feel like that's not sufficient, it seems feasible to detect this situation at runtime and error out. the warning class). Having the option allows users full control. I think opt-out is the right default here.
typing.py generally aims to avoid affecting runtime behavior.
This is true, but what we often really want to avoid is runtime type checking, and this isn't really runtime type checking. I really do believe that most users will want some runtime warning here. Absent specific reasons to avoid affecting runtime behaviour, I'm not sure how much stock I put in this as a general guideline, given SC feedback about wanting a more cohesive language. On Sun, 1 Jan 2023 at 16:13, Jelle Zijlstra <jelle.zijlstra@gmail.com> wrote:
I just posted PEP 702, Marking deprecations using the type system: https://peps.python.org/pep-0702/.
The PEP proposes adding an @typing.deprecated() decorator to mark classes, methods, and functions as deprecated. Type checkers will leverage this decorator to inform users about their usage of deprecated features.
I welcome feedback on any aspect of the proposal. However, two main points came up in initial discussions:
- The proposal specifies that the decorator does not raise any runtime DeprecationWarning. Should we change this, perhaps with an opt-in flag? - The proposal allows users to mark classes, functions, and overloads as deprecated, but there are other things that may want deprecation. Should we add support for deprecating modules, or variables, or parameters?
Happy New Year! _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: hauntsaninja@gmail.com
Thanks for writing this proposal. This fills an important gap. I like the simplicity of your proposed approach. Adding additional complexity to support deprecation of global variables and type aliases would be a mistake, IMO. You mentioned protocol implementations. I think the same applies to classes that implement an ABC. It looks like the most popular third-party library for deprecation is https://pypi.org/project/Deprecated/. It's downloaded almost 6M times each week. It might be worth considering adopting its interface. It provides separate named parameters for "reason" and "version". -- Eric Traut Contributor to Pyright & Pylance Microsoft
Seems awesome! Even though I'm conflicted on using the type system for depracations, I like the idea of having an official way to staticly mark depracations. Couple of points: 1. Why not supporting deprecating variables in general? Personally, I could use the ability to depracate class attributes/module constants and it seems like this funcitonallity could be reused if `deprecated` was not solely a decorator: `CONST = deprecated("value")` 2. As more features are added, it seems like the typing system becomes less of a "typing system" and more of a "static proccessing system". Unless there is some kind of a vision to change the term "typing system" to something more general, I think changes like this can cause quite an amount of confusion over time.
I agree with Nir Schulman, I also don't think that producing a runtime warning is something that the type system should be responsible for. I would never expect a decorator from `typing` to produce a warning. As Eric Taut mentioned, there is a fairly popular library called 'Deprecated', that's already capable of handling this, and it's doing so quite well. I do get that people might not love the idea for having to use 2 decorators on all deprecations though. For that reason, I think it'd be great if we could do something like: T = typing.TypeVar("T", bound=Callable) def deprecate(func: T) -> typing.deprecated(T): ... or the much more natural, though currently declined idea of going with typing.Deprecated[T]. This would allow the 'Deprecated' library to add any runtime functionality to the decorator, and the typing system to easily recognize that any decorated function is now deprecated. On top of that, it allows users to handle deprecation decorator implementations on their own, which could be quite useful, as someone might prefer something like: deprecated("Use X instead", date=datetime(2023, 5, 10)) rather than a version based deprecation. If needed, runtime support could then be added outside of the typing module, with something like warnings.deprecated, which would be defined like in my example above, but I don't think it's a good idea to introduce too much runtime logic into typing features. I'm also very much for supporting variable deprecations, as currently, typed libraries that define some type aliases as a part of the public API are forced to make changes that simply can not currently be deprecated in any way. Allowing users that are importing these type aliases to see a deprecation warning from a type-checker would finally allow such libraries to properly handle deprecations. I wrote a bit more about this here: https://mail.python.org/archives/list/typing-sig@python.org/thread/E3BUVIKOD...
Thanks everyone for the replies! I'm going to reply to all of the suggested changes here: 1. Issue a runtime warning (Shantanu) I'm still not sold on this as it will make the implementation more complex and break some user expectations (see ItsDrike's message). I'm going to move this to "Open Issues" and ask for additional opinions on discuss.python. 2. Deprecating variables (ItsDrike, Nir) I can see merit in this but it also adds significant complexity, and we can always add it later in a separate PEP. 3. Why not put it in warnings? (Nikita) As long as the decorator doesn't raise a warning, it definitely doesn't fit the `warnings` module. If we do add a warning, I could see this changing, but the primary purpose of the decorator will remain communicating with type checkers. 4. Add version argument/sync the interface with the `Deprecated` library (Eric) I would consider this, but it would be confusing if there is a `version` argument that is ignored by static type checkers. We don't currently expect static type checkers to know what version of a third-party library is being used. El dom, 1 ene 2023 a las 16:12, Jelle Zijlstra (<jelle.zijlstra@gmail.com>) escribió:
I just posted PEP 702, Marking deprecations using the type system: https://peps.python.org/pep-0702/.
The PEP proposes adding an @typing.deprecated() decorator to mark classes, methods, and functions as deprecated. Type checkers will leverage this decorator to inform users about their usage of deprecated features.
I welcome feedback on any aspect of the proposal. However, two main points came up in initial discussions:
- The proposal specifies that the decorator does not raise any runtime DeprecationWarning. Should we change this, perhaps with an opt-in flag? - The proposal allows users to mark classes, functions, and overloads as deprecated, but there are other things that may want deprecation. Should we add support for deprecating modules, or variables, or parameters?
Happy New Year!
participants (5)
-
Eric Traut
-
Jelle Zijlstra
-
me@itsdrike.com
-
Nir Schulman
-
Shantanu Jain