mkdocstrings icon indicating copy to clipboard operation
mkdocstrings copied to clipboard

feature: Support `__getattr__` during dynamic analysis

Open pawamoy opened this issue 8 months ago • 2 comments

Is your feature request related to a problem? Please describe.

From https://github.com/mkdocstrings/mkdocstrings/issues/751#issuecomment-2769290965.

Dynamic analysis only uses inspect.getmembers. This doesn't pass through a module's __getattr__, so we don't see all the lazy objects that __getattr__ can return.

Describe the solution you'd like

If the module defines a __dir__ function which is not the built-in one (repr(mod.__dir__) != "<built-in function __dir__>"), we could call it to get the list of members (in addition to using inspect.getmembers), and for each name that wasn't returned by inspect.getmembers, try to obtain the member with getattr(mod, name).

Describe alternatives you've considered

/

Additional context

/

pawamoy avatar Apr 01 '25 14:04 pawamoy

Dynamic analysis only uses inspect.getmembers. This doesn't pass through a module's __getattr__, so we don't see all the lazy objects that __getattr__ can return.

@pawamoy AFAIK, inspect.getmembers() do respect custom __dir__ and __getattr__ of a module. Here is a minimal example:

(click to expand)
# file: module.py
def __dir__() -> list[str]:
    return ["foo", "bar"]
def __getattr__(name: str) -> str:
    return name
# file: main.py
import inspect, module
print(inspect.getmembers(module))

Output:

$ python main.py
[('bar', 'bar'), ('foo', 'foo')]

Why do we need extra work to support __getattr__?

liblaf avatar Sep 10 '25 12:09 liblaf

Oh, you're right, I didn't know that inspect.getmembers used __dir__. Then it's just a matter of documentation! Thanks @liblaf!

pawamoy avatar Sep 10 '25 14:09 pawamoy