I’ve encountered a weird issue with inspect.getmembers() and would like some help.
Background:
I’ve been adding type hints to a project. One of my classes is a generic container, so I made a type variable _T = TypeVar('_T') so I could write class MyContainer(Deque[_T]) and not export the variable from the module.
Problem:
There is a test that uses importlib and inspect to make sure only the public API is exported.
For some reason in Python >= 3.7, inspect.getmembers() shows _T as one of the exports despite the leading underscore and despite __all__ excluding _T. This is causing the test fail.
A simplified example and results can be seen here:
What changed between 3.6 and 3.7? Am I using inspect.getmembers() incorrectly?
Digging into this further, it seems that the change was not in inspect.getmembers(), but either inspect.getmodule() or typing.TypeVar.
This is basically the test I was using:
# return a set of strings that represent the names of objects defined in that module
import inspect
import importlib
module = importlib.import('mod')
return {n for n, o in inspect.getmembers(module, lambda m: inspect.getmodule(m) is module)}
The lambda there is supposed to filter out things not defined in the module. Using the code from my GitHub link above, I get these interesting results:
Ok, yeah typing.TypeVar was changed in Python 3.7. There were apparently issues with pickling generic types and part of the fix was setting the module that type variables are defined in.
I think I’m going to have to rethink my test though, because it still fails with code like this:
mod.py:
__all__ = ['A', 'B']
class A:
pass
class B:
pass
class _C:
pass