deprecated icon indicating copy to clipboard operation
deprecated copied to clipboard

Deprecated names?

Open AstraLuma opened this issue 3 years ago • 5 comments

(Feature request)

I would like to see a way to move a class, function, or method from one name to another, deprecating the old name.

So you could say:

class NewName:
    ...

OldName = deprecated_name(NewName)

I would say that it should raise a warning on direct use (ideally when the code referring to it is compiled, but implementing that would be unacceptably magical).

  • Functions, methods: When called
  • Classes: When subclassed or directly instantiated (maybe when a class-level attribute is accessed as well?)

AstraLuma avatar Mar 27 '21 20:03 AstraLuma

Thank you for your question.

Actually, you can already have a old function which is a deprecated version of a new function name, here is how you can do that:

from deprecated import deprecated


def new_function():
    pass


old_function = deprecated(reason=u"Use new_function() instead", version="2.3.0")(new_function)

if __name__ == '__main__':
    old_function()
    new_function()

You'll have a warning message only if you use the old function:

demo.py:12: DeprecationWarning: Call to deprecated function (or staticmethod) new_function. (Use new_function() instead) -- Deprecated since version 2.3.0.
  old_function()

For classes, it's another story because this is the __new__ method which is actually decorated. So, this is not the right way to do that. You may need module-level deprecation, which is a modern feature only available for Python 3.7+ (see: PEP 562 -- Module __getattr__ and __dir__.

I'll try to given you a workaround later.

tantale avatar Mar 28 '21 10:03 tantale

A workaround for classes could be designed as follow: the "old" class can be redefined and inherit the "new" class. Then you need to implement a __new__ method which will receive the deprecation warning:

from deprecated import deprecated


class NewClass(object):
    pass


@deprecated(reason=u"Use NewClass instead", version="2.3.0")
class OldClass(NewClass):
    @classmethod
    def __new__(cls, *args, **kwargs):
        return super(OldClass, cls).__new__(cls)
        # or, if ``NewClass.__new__`` is defined:
        # return super(OldClass, cls).__new__(cls, *args, **kwargs)


if __name__ == '__main__':
    old_obj = OldClass()
    new_obj = NewClass()

You get:

demo.py:19: DeprecationWarning: Call to deprecated class OldClass. (Use NewClass instead) -- Deprecated since version 2.3.0.
  old_obj = OldClass()

tantale avatar Mar 28 '21 13:03 tantale

I will leave this issue opened until I implement module-level deprecation.

tantale avatar Mar 28 '21 13:03 tantale

Module-level depreciation is currently being developed. Stay tune.

tantale avatar May 27 '23 16:05 tantale

Adding these examples to the docs would be good too

benjamin-kirkbride avatar Aug 08 '23 01:08 benjamin-kirkbride