[Migrating from https://bugs.python.org/issue44701] Would it be interesting to create a @deprecated decorator to avoid adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body? Using the decorator approach to indicate depreciation would make the methods cleaner (leaving only their responsibilities in the body) and would be easier to identify, as the cue would be close to the method signature and not mixed with the logic inside the body. in some cases it will still be necessary to put warnings.warn (..) inside the body of functions/methods because of some message display condition, or we could also express the message display condition in the decorator in @deprecated itself. But it would be interesting to have the possibility of not putting this inside the method body. Even the decorator can come from the notices module. Example: (Before) def check_metadata(self): """Deprecated API.""" warn("distutils.command.register.check_metadata is deprecated, \ use the check command instead", PendingDeprecationWarning) check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run() (after) @deprecated("distutils.command.register.check_metadata is deprecated, \ use the check command instead") def check_metadata(self): """Deprecated API.""" check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
Hi, I've been using https://pypi.org/project/Deprecated/ for quite some time and I recommend it. S. On Thu, Jul 29, 2021 at 4:39 PM Leonardo Freua < leonardo.batista.freua@gmail.com> wrote:
[Migrating from https://bugs.python.org/issue44701]
Would it be interesting to create a @deprecated decorator to avoid adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body?
Using the decorator approach to indicate depreciation would make the methods cleaner (leaving only their responsibilities in the body) and would be easier to identify, as the cue would be close to the method signature and not mixed with the logic inside the body.
in some cases it will still be necessary to put warnings.warn (..) inside the body of functions/methods because of some message display condition, or we could also express the message display condition in the decorator in @deprecated itself. But it would be interesting to have the possibility of not putting this inside the method body. Even the decorator can come from the notices module.
Example:
(Before)
def check_metadata(self): """Deprecated API.""" warn("distutils.command.register.check_metadata is deprecated, \ use the check command instead", PendingDeprecationWarning) check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
(after)
@deprecated("distutils.command.register.check_metadata is deprecated, \ use the check command instead") def check_metadata(self): """Deprecated API.""" check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run() _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/62CTVN... Code of Conduct: http://python.org/psf/codeofconduct/
-- Stefane Fermigier - http://fermigier.com/ - http://twitter.com/sfermigier - http://linkedin.com/in/sfermigier Founder & CEO, Abilian - Enterprise Social Software - http://www.abilian.com/ Chairman, National Council for Free & Open Source Software (CNLL) - http://cnll.fr/ Founder & Organiser, PyParis & PyData Paris - http://pyparis.org/ & http://pydata.fr/
This is a good example of how using a decorator to express depreciation is much better and less polluting the method, as the depreciation message doesn't need to be in the method body. In my view, it would be interesting for Python to natively have the ability to annotate deprecated methods.
I'm +1 on deprecation decorator, with some way to represent it so that it can be determined at runtime (e.g. dunder). On Thu, 2021-07-29 at 20:52 +0000, Leonardo Freua wrote:
This is a good example of how using a decorator to express depreciation is much better and less polluting the method, as the depreciation message doesn't need to be in the method body.
In my view, it would be interesting for Python to natively have the ability to annotate deprecated methods. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/BVYHXK... Code of Conduct: http://python.org/psf/codeofconduct/
I'd like to be able to specificy @deprecate on only some @overloads On Thu, 29 Jul 2021, 21:59 Paul Bryan, <pbryan@anode.ca> wrote:
I'm +1 on deprecation decorator, with some way to represent it so that it can be determined at runtime (e.g. dunder).
On Thu, 2021-07-29 at 20:52 +0000, Leonardo Freua wrote:
This is a good example of how using a decorator to express depreciation is much better and less polluting the method, as the depreciation message doesn't need to be in the method body.
In my view, it would be interesting for Python to natively have the ability to annotate deprecated methods. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/BVYHXK... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/OSR6OA... Code of Conduct: http://python.org/psf/codeofconduct/
Specially I'd like to be able to deprecate the `Callable[..., Iterable[T]]` type of contextlib.contextmanager See https://github.com/python/typeshed/pull/2773#issuecomment-458872741 On Thu, 29 Jul 2021, 22:00 Thomas Grainger, <tagrain@gmail.com> wrote:
I'd like to be able to specificy @deprecate on only some @overloads
On Thu, 29 Jul 2021, 21:59 Paul Bryan, <pbryan@anode.ca> wrote:
I'm +1 on deprecation decorator, with some way to represent it so that it can be determined at runtime (e.g. dunder).
On Thu, 2021-07-29 at 20:52 +0000, Leonardo Freua wrote:
This is a good example of how using a decorator to express depreciation is much better and less polluting the method, as the depreciation message doesn't need to be in the method body.
In my view, it would be interesting for Python to natively have the ability to annotate deprecated methods. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/BVYHXK... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/OSR6OA... Code of Conduct: http://python.org/psf/codeofconduct/
On Thu, 29 Jul 2021 at 15:39, Leonardo Freua <leonardo.batista.freua@gmail.com> wrote:
Would it be interesting to create a @deprecated decorator to avoid adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body?
I don't see the value personally.
Using the decorator approach to indicate depreciation would make the methods cleaner (leaving only their responsibilities in the body) and would be easier to identify, as the cue would be close to the method signature and not mixed with the logic inside the body.
First line of the body vs line before the declaration doesn't feel like it makes much difference to me.
in some cases it will still be necessary to put warnings.warn (..) inside the body of functions/methods because of some message display condition, or we could also express the message display condition in the decorator in @deprecated itself. But it would be interesting to have the possibility of not putting this inside the method body. Even the decorator can come from the notices module.
Why would it be "interesting"? I don't see any practical advantage, and as soon as you need any form of logic you have to rewrite, so why bother? If you want this to get support, I think you need to argue the benefits far more than you have so far...
Example:
(Before)
def check_metadata(self): """Deprecated API.""" warn("distutils.command.register.check_metadata is deprecated, \ use the check command instead", PendingDeprecationWarning) check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
(after)
@deprecated("distutils.command.register.check_metadata is deprecated, \ use the check command instead") def check_metadata(self): """Deprecated API.""" check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
TBH, the decorator version makes it harder to see the function signature. -1 from me, I'm afraid. Disclaimer: I've never actually deprecated an API in my own code, so my objections are mainly theoretical. Paul
Why would it be "interesting"? I don't see any practical advantage, and as soon as you need any form of logic you have to rewrite, so why bother?
The advantage of having a declarative API for deprecations is tooling support. It is much easier to detect decorator application than to reliably infer whether a function/class emits (or raises) a DeprecationWarning. I started a similar thread [*] a few weeks ago, but have had no chance to reply properly since. Sergei [*]: https://mail.python.org/archives/list/python-ideas@python.org/thread/EABCXCA... On Thu, Jul 29, 2021 at 3:59 PM Paul Moore <p.f.moore@gmail.com> wrote:
On Thu, 29 Jul 2021 at 15:39, Leonardo Freua <leonardo.batista.freua@gmail.com> wrote:
Would it be interesting to create a @deprecated decorator to avoid
adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body?
I don't see the value personally.
Using the decorator approach to indicate depreciation would make the methods cleaner (leaving only their responsibilities in the body) and would be easier to identify, as the cue would be close to the method signature and not mixed with the logic inside the body.
First line of the body vs line before the declaration doesn't feel like it makes much difference to me.
in some cases it will still be necessary to put warnings.warn (..) inside the body of functions/methods because of some message display condition, or we could also express the message display condition in the decorator in @deprecated itself. But it would be interesting to have the possibility of not putting this inside the method body. Even the decorator can come from the notices module.
Why would it be "interesting"? I don't see any practical advantage, and as soon as you need any form of logic you have to rewrite, so why bother?
If you want this to get support, I think you need to argue the benefits far more than you have so far...
Example:
(Before)
def check_metadata(self): """Deprecated API.""" warn("distutils.command.register.check_metadata is deprecated, \ use the check command instead", PendingDeprecationWarning) check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
(after)
@deprecated("distutils.command.register.check_metadata is deprecated, \ use the check command instead") def check_metadata(self): """Deprecated API.""" check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
TBH, the decorator version makes it harder to see the function signature.
-1 from me, I'm afraid.
Disclaimer: I've never actually deprecated an API in my own code, so my objections are mainly theoretical.
Paul _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/6O7WJ3... Code of Conduct: http://python.org/psf/codeofconduct/
Perhaps another approach would be to make a more general purpose warning decorator, that would give a warning when invoking a function or instantiating a class. It could be used for deprecation notices, of course, but has the potential for tooling to give other types of warnings, such as using a thread unsafe call in a threading context. On Thu, Jul 29, 2021 at 14:26 Sergei Lebedev <sergei.a.lebedev@gmail.com> wrote:
Why would it be "interesting"? I don't see any practical advantage, and as soon as you need any form of logic you have to rewrite, so why bother?
The advantage of having a declarative API for deprecations is tooling support. It is much easier to detect decorator application than to reliably infer whether a function/class emits (or raises) a DeprecationWarning.
I started a similar thread [*] a few weeks ago, but have had no chance to reply properly since.
Sergei
[*]: https://mail.python.org/archives/list/python-ideas@python.org/thread/EABCXCA...
On Thu, Jul 29, 2021 at 3:59 PM Paul Moore <p.f.moore@gmail.com> wrote:
On Thu, 29 Jul 2021 at 15:39, Leonardo Freua <leonardo.batista.freua@gmail.com> wrote:
Would it be interesting to create a @deprecated decorator to avoid
adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body?
I don't see the value personally.
Using the decorator approach to indicate depreciation would make the methods cleaner (leaving only their responsibilities in the body) and would be easier to identify, as the cue would be close to the method signature and not mixed with the logic inside the body.
First line of the body vs line before the declaration doesn't feel like it makes much difference to me.
in some cases it will still be necessary to put warnings.warn (..) inside the body of functions/methods because of some message display condition, or we could also express the message display condition in the decorator in @deprecated itself. But it would be interesting to have the possibility of not putting this inside the method body. Even the decorator can come from the notices module.
Why would it be "interesting"? I don't see any practical advantage, and as soon as you need any form of logic you have to rewrite, so why bother?
If you want this to get support, I think you need to argue the benefits far more than you have so far...
Example:
(Before)
def check_metadata(self): """Deprecated API.""" warn("distutils.command.register.check_metadata is deprecated, \ use the check command instead", PendingDeprecationWarning) check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
(after)
@deprecated("distutils.command.register.check_metadata is deprecated, \ use the check command instead") def check_metadata(self): """Deprecated API.""" check = self.distribution.get_command_obj('check') check.ensure_finalized() check.strict = self.strict check.restructuredtext = 1 check.run()
TBH, the decorator version makes it harder to see the function signature.
-1 from me, I'm afraid.
Disclaimer: I've never actually deprecated an API in my own code, so my objections are mainly theoretical.
Paul _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/6O7WJ3... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/YAI2Y5... Code of Conduct: http://python.org/psf/codeofconduct/
Hi Sergei, I really thought your proposal was very good, in fact, it's quite complete with examples in libraries that I didn't even know implement a depreciation API. Thanks for the contribution.
Perhaps another approach would be to make a more general purpose warning decorator, that would give a warning when invoking a function or instantiating a class. It could be used for deprecation notices, of course, but has the potential for tooling to give other types of warnings, such as using a thread unsafe call in a threading context.
What about "mark" import mark @mark.deprecated @mark.slow @mark.thread_unsafe @mark.insecure On Thu, Jul 29, 2021, 5:26 PM Leonardo Freua < leonardo.batista.freua@gmail.com> wrote:
Hi Sergei, I really thought your proposal was very good, in fact, it's quite complete with examples in libraries that I didn't even know implement a depreciation API.
Thanks for the contribution. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/TGQVDH... Code of Conduct: http://python.org/psf/codeofconduct/
Recently I needed to do just that on an API and went with the decorator approach. Having this on the stdlib would be nice, and we can make it more powerful than just raising a warning. For instance, we could attach a `deprecated = True` to the function object so that framework authors can use that to handle depreciation as well - think flask endpoints. Another option is to have an `alternative` optional kwarg in the decorator, something like def new_function(): .... @deprecated(alternative=new_function) def old_function(): ... This would raise a warning stating that `new_function` should be used in the place of `old_function` [image: --] *Felipe* Bidu *(Felipe Rodrigues)* [image: https://]*https://felipevr.com* <https://felipevr.com> On Fri, Jul 30, 2021 at 9:22 AM Jack DeVries <jdevries3133@gmail.com> wrote:
Perhaps another approach would be to make a more general purpose warning decorator, that would give a warning when invoking a function or instantiating a class. It could be used for deprecation notices, of course, but has the potential for tooling to give other types of warnings, such as using a thread unsafe call in a threading context.
What about "mark"
import mark
@mark.deprecated @mark.slow @mark.thread_unsafe @mark.insecure
On Thu, Jul 29, 2021, 5:26 PM Leonardo Freua < leonardo.batista.freua@gmail.com> wrote:
Hi Sergei, I really thought your proposal was very good, in fact, it's quite complete with examples in libraries that I didn't even know implement a depreciation API.
Thanks for the contribution. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/TGQVDH... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7WCBL5... Code of Conduct: http://python.org/psf/codeofconduct/
First line of the body vs line before the declaration doesn't feel like it makes much difference to me.
Usually, decorators or annotations are placed near the method signature, that is, at the beginning where any reading begins, because it's easier to see that method is deprecated or anything else that needs a decorator. Putting this information inside the method body, you end up putting information that is not the method's responsibility to provide, this ends up mixing with what the method actually does, it's more information to read in a debug or in maintenance that the method will need to receive. Not to mention the fact that sometimes depreciation messages can be longer than 2 lines. Most programming languages have some way of expressing depreciation, and it's usually close to the method signature. I'm not proposing to do away with the way it is done today, but rather to expand the possibilities. There are times when the existence of just one decorator would make the code cleaner than inserting more information into the body of the method/function. Ps.: Relax Paul, you don't need to be afraid, this is just a proposal. Thanks for the contribution, good points raised.
On Fri, Jul 30, 2021 at 7:11 AM Leonardo Freua <leonardo.batista.freua@gmail.com> wrote:
First line of the body vs line before the declaration doesn't feel like it makes much difference to me.
Usually, decorators or annotations are placed near the method signature, that is, at the beginning where any reading begins, because it's easier to see that method is deprecated or anything else that needs a decorator.
Putting this information inside the method body, you end up putting information that is not the method's responsibility to provide, this ends up mixing with what the method actually does, it's more information to read in a debug or in maintenance that the method will need to receive. Not to mention the fact that sometimes depreciation messages can be longer than 2 lines.
Most programming languages have some way of expressing depreciation, and it's usually close to the method signature.
One advantage of language support for deprecation can be an "entry point only" warning - if a regular function calls a deprecated function, there's a warning, but if a deprecated function calls another deprecated function, there won't be. Whether this is worth implementing here is a separate question, but it would certainly be easier to do with a decorator than an explicit warn() call. ChrisA
On Thu, 29 Jul 2021 at 16:00, Paul Moore <p.f.moore@gmail.com> wrote:
On Thu, 29 Jul 2021 at 15:39, Leonardo Freua <leonardo.batista.freua@gmail.com> wrote:
Would it be interesting to create a @deprecated decorator to avoid adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body?
I don't see the value personally.
I do see the value. Many projects use this kind of functionality and end up reinventing something along these lines e.g.: https://github.com/scipy/scipy/blob/6bc0b7297aaca7c7c1b4854d421b20d35172222c... Actually deprecating functions and methods is probably the easiest part. You can either emit a warning from inside the function or use a deprecator to do the same when the function is called. That does mean though that there's no programmatic way to know without calling the function that it is deprecated. Other cases are deprecating e.g. a class, or a particular instance/object or a module. If a module is deprecated you can trigger a warning on import but of course import caching means that subsequent imports won't see the warning (maybe that's okay...). For an object you might want to use __getattr__ to trigger the warning. Then difficulty comes if introspective tools use getattr, dir etc so users end up seeing the warning even though nothing is actually using the deprecated functionality: https://github.com/sympy/sympy/issues/9371 This is the kind of thing that is on the edge of being worth a PyPI dependency: do you really want to have an external dependency just to give out warnings for stuff that you wish wasn't in your codebase in the first place? Not needing to reinvent the wheel in many projects is useful but actually the real advantages of standardising deprecation as I see it are things like: 1. If there is a standardised attribute like __deprecated__ then introspective tools can avoid triggering the warning. 2. Static/introspective analysis could determine if deprecated functionality is potentially being used even if e.g. the function does not happen to be called during the test suite. 3. The attribute could expose useful information in a standardised way like version_deprecated, version_will_be_removed, use_instead, url_for_more_information etc so that smart editors and other tooling can check this (perhaps in tandem with checking a requirements.txt or something). -- Oscar
@Deprecated is used in Java and I find it very easy to use. Remember you can also use parameters in decorators.....
On 29Jul2021 15:58, Paul Moore <p.f.moore@gmail.com> wrote:
On Thu, 29 Jul 2021 at 15:39, Leonardo Freua <leonardo.batista.freua@gmail.com> wrote:
Would it be interesting to create a @deprecated decorator to avoid adding warnings.warn("deprecation message", DeprecationWarning, stacklevel=2) in methods body?
I don't see the value personally.
I do. Like various others here I wrote myself such a decorator long ago. It was named @OBSOLETE and was by no means as complete as, say, the Deprecated PyPI module. But the use case was the same: @OBSOLETE def old_func(): A decorator is concise and right up front in the code. As others have mentioned, it becomes easy for tooling to see or use. (Not mine, it is a miracle of crudity, just issuing warning() calls when the function is first called from some place - it does at least say where the call was made from.) [...]
Why would it be "interesting"? I don't see any practical advantage, and as soon as you need any form of logic you have to rewrite, so why bother?
That's the case for any presupplied convenience. But it covers off a lot of the common cases to my mind. The idea's a definite +1 from me. Cheers, Cameron Simpson <cs@cskk.id.au>
participants (13)
-
Cameron Simpson
-
Chris Angelico
-
Felipe Rodrigues
-
Jack DeVries
-
Leonardo Freua
-
Marco Sulla
-
Michael Smith
-
Oscar Benjamin
-
Paul Bryan
-
Paul Moore
-
Sergei Lebedev
-
Stéfane Fermigier
-
Thomas Grainger