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

deprecate abstract method #72

Open
bertsky opened this issue Jun 10, 2024 · 2 comments
Open

deprecate abstract method #72

bertsky opened this issue Jun 10, 2024 · 2 comments

Comments

@bertsky
Copy link

bertsky commented Jun 10, 2024

This is a feature request (I think): I would like deprecated to be able to yield warnings on a method call, even when overriding the implementation in a subclass. In particular, I would like to be able to deprecate abstract methods.

Expected Behavior

Running…

from deprecated import deprecated

class Parent:
    @deprecated(reason='try not to laugh')
    def fun(self, arg):
        raise NotImplementedError()

class Child(Parent):
    def fun(self, arg):
        print(arg)
        print('yaye!')

some = Child()
some.fun('whoops')

…I would like to see…

DeprecationWarning: Call to deprecated method fun. (try not to laugh)
  some.fun('whoops')
whoops
yaye!

Actual Behavior

However, since the method is overriden, I can see no warning:

whoops
yaye!

Environment

  • Python version: 3.9
  • Deprecated version: 1.2.14
@bertsky
Copy link
Author

bertsky commented Jun 10, 2024

To elaborate: the use-case is quite simple: I have a library with an abstract method, which gets deprecated at some point. Inheriting code (not under my control) should see the deprecation warning when their implemented method gets called.

As a workaround, of course I can place the following in the superclass' constructor:

class Parent:
    def __init__(self, ...)
        ...
        setattr(self, 'fun', deprecated(reason='try not to laugh')(getattr(self, 'fun')))

But of course it would be much nicer if deprecated would offer something along those lines itself.

@laurent-laporte-pro
Copy link
Owner

laurent-laporte-pro commented Nov 14, 2024

You're correct; the previous solution won't work here. When a subclass overrides an abstract method, it completely replaces it, so the decorated parent method (with the deprecation warning) is never actually called. The decorator only issues a warning if the decorated method itself is called, which doesn’t happen with overridden abstract methods.

Possible Approach: Introspection with __mro__

To emit a warning when calling the overridden method in the subclass, one option is to add introspection logic to the decorator. This would involve checking the class's Method Resolution Order (__mro__) each time the method is called, to see if any superclass has a deprecated method with the same name. The __mro__ attribute lists the method resolution path in Python, allowing the decorator to detect deprecated methods up the inheritance chain.

This approach introduces extra processing time, as each method call would require scanning the __mro__ for a deprecated method in the parent classes.

Currently, there isn’t a straightforward way to make deprecated warnings propagate to overridden abstract methods in subclasses, as the subclass method bypasses the parent method entirely. An introspective approach could work but would add significant overhead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants