I'm working on a Python project where I'm using decorators to wrap functions and methods with some logic. However, I've encountered an issue where inspect
identifies the decorated methods as functions instead of methods.
Here's a simplified version of my code:
from functools import update_wrapper, wraps
import inspect
from typing import Any, Callable, Optional
def my_decorator(func: Optional[Callable] = None, **decorator_kwargs):
def decorate(func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
if inspect.isfunction(func):
print(f"{func.__name__} is a function")
elif inspect.ismethod(func):
print(f"{func.__name__} is a method")
else:
raise Exception(f"{func.__name__} is neither a function nor a method")
return func(*args, **kwargs)
return wrapper
if func:
update_wrapper(decorate, func)
return decorate(func)
return decorate
class TestClass:
def __init__(self, value: Any):
self.value = value
@my_decorator(foo="bar")
def print_value(self, second_value: str):
print(f"Printing Value {self.value}, {second_value}")
return self.value
def main():
test_class = TestClass(45)
test_class.print_value("spam")
if __name__ == "__main__":
main()
In this code, I've used a decorator to wrap the print_value
method of the TestClass
class. Despite using functools.wraps
to preserve the original method's metadata, inspect
still identifies print_value
as a function.
How can I correctly identify decorated methods as methods using the inspect
module? Is there a specific approach or modification needed to ensure the correct identification of methods?
Additional Information:
functools.wraps
to preserve the metadata, but it didn't work.decorate
function, but it didn't work.print_value
is a function. It's used (via the descriptor protocol) to produce a method
object when it is accessed via an instance of TestClass
.
>>> TestClass.print_value
<function TestClass.print_value at 0x105af0900>
>>> TestClass(5).print_value
<bound method TestClass.print_value of <__main__.TestClass object at 0x105c49810>>
Generally speaking, you should avoid trying to treat functions intended as methods differently from other functions.