Added utility function to get the defining class of a method.

This commit is contained in:
Fabio Manganiello 2023-10-10 01:35:01 +02:00
parent 2af304f478
commit 5726c6985f
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -1,6 +1,7 @@
import ast import ast
import contextlib import contextlib
import datetime import datetime
import functools
import hashlib import hashlib
import importlib import importlib
import inspect import inspect
@ -705,4 +706,36 @@ def import_file(path: str, name: Optional[str] = None):
return mod return mod
def get_defining_class(meth) -> Optional[type]:
"""
See https://stackoverflow.com/a/25959545/622364.
This is the best way I could find of answering the question "given a bound
method, get the class that defined it",
"""
if isinstance(meth, functools.partial):
return get_defining_class(meth.func)
if inspect.ismethod(meth) or (
inspect.isbuiltin(meth)
and getattr(meth, '__self__', None) is not None
and getattr(meth.__self__, '__class__', None)
):
for cls in inspect.getmro(meth.__self__.__class__):
if meth.__name__ in cls.__dict__:
return cls
meth = getattr(meth, '__func__', meth) # fallback to __qualname__ parsing
if inspect.isfunction(meth):
cls = getattr(
inspect.getmodule(meth),
meth.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0],
None,
)
if isinstance(cls, type):
return cls
return getattr(meth, '__objclass__', None) # handle special descriptor objects
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et: