diff options
Diffstat (limited to 'yt_dlp/compat/compat_utils.py')
-rw-r--r-- | yt_dlp/compat/compat_utils.py | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/yt_dlp/compat/compat_utils.py b/yt_dlp/compat/compat_utils.py index b1d58f5b9..82e176281 100644 --- a/yt_dlp/compat/compat_utils.py +++ b/yt_dlp/compat/compat_utils.py @@ -4,7 +4,6 @@ import importlib import sys import types - _NO_ATTRIBUTE = object() _Package = collections.namedtuple('Package', ('name', 'version')) @@ -31,9 +30,9 @@ def _is_package(module): return True -def passthrough_module(parent, child, *, callback=lambda _: None): +def passthrough_module(parent, child, allowed_attributes=None, *, callback=lambda _: None): parent_module = importlib.import_module(parent) - child_module = importlib.import_module(child, parent) + child_module = None # Import child module only as needed class PassthroughModule(types.ModuleType): def __getattr__(self, attr): @@ -41,19 +40,30 @@ def passthrough_module(parent, child, *, callback=lambda _: None): with contextlib.suppress(ImportError): return importlib.import_module(f'.{attr}', parent) - ret = _NO_ATTRIBUTE + ret = self.__from_child(attr) + if ret is _NO_ATTRIBUTE: + raise AttributeError(f'module {parent} has no attribute {attr}') + callback(attr) + return ret + + def __from_child(self, attr): + if allowed_attributes is None: + if attr.startswith('__') and attr.endswith('__'): + return _NO_ATTRIBUTE + elif attr not in allowed_attributes: + return _NO_ATTRIBUTE + + nonlocal child_module + child_module = child_module or importlib.import_module(child, parent) + with contextlib.suppress(AttributeError): - ret = getattr(child_module, attr) + return getattr(child_module, attr) if _is_package(child_module): with contextlib.suppress(ImportError): - ret = importlib.import_module(f'.{attr}', child) - - if ret is _NO_ATTRIBUTE: - raise AttributeError(f'module {parent} has no attribute {attr}') + return importlib.import_module(f'.{attr}', child) - callback(attr) - return ret + return _NO_ATTRIBUTE # Python 3.6 does not have module level __getattr__ # https://peps.python.org/pep-0562/ |