Yes, that’s why I characterized my solution as a workaround and why I put the word “module” in quotes.
Regarding your good point about the missing subtle things that may be expected from ModuleType:
__file__does not come fromModuleType. It is set by a file-based loader, which theInspectLoaderI used in my example is not. It would be set if you use a loader inherited fromSourceFileLoaderinstead for example.- Support for a user-defined
__getattr__(not__getitem__by the way) can be easily implemented by overloading__getattr__for our “module”. - For code that explicitly checks if our “module” is a
ModuleType, we can work around it by setting the__class__attribute.
And here’s our updated “module” type to support points 2. and 3.:
class LoggingModule:
__class__ = ModuleType
def __init__(self):
self.__dict__ = LoggingDict()
def __getattr__(self, name):
if __getattr__ := self.__dict__.get('__getattr__'):
return __getattr__(name)
raise AttributeError
Demo here, which shows that it correctly supports a user-defined __getattr__ and passes both of the following tests:
assert isinstance(foo, ModuleType)
assert inspect.ismodule(foo)