+ return '__path__' in vars(module)
+
+
+class EnhancedModule(types.ModuleType):
+ def __new__(cls, name, *args, **kwargs):
+ if name not in sys.modules:
+ return super().__new__(cls, name, *args, **kwargs)
+
+ assert not args and not kwargs, 'Cannot pass additional arguments to an existing module'
+ module = sys.modules[name]
+ module.__class__ = cls
+ return module
+
+ def __init__(self, name, *args, **kwargs):
+ # Prevent __new__ from trigerring __init__ again
+ if name not in sys.modules:
+ super().__init__(name, *args, **kwargs)
+
+ def __bool__(self):
+ return vars(self).get('__bool__', lambda: True)()
+
+ def __getattribute__(self, attr):
+ try:
+ ret = super().__getattribute__(attr)
+ except AttributeError:
+ if attr.startswith('__') and attr.endswith('__'):
+ raise
+ getter = getattr(self, '__getattr__', None)
+ if not getter:
+ raise
+ ret = getter(attr)
+ return ret.fget() if isinstance(ret, property) else ret