Source code for dataclass_wizard.utils.lazy_loader
"""
Utility for lazy loading Python modules.
Credits: https://wil.yegelwel.com/lazily-importing-python-modules/
"""
import importlib
import logging
import types
[docs]
class LazyLoader(types.ModuleType):
"""
Lazily import a module, mainly to avoid pulling in large dependencies.
`contrib`, and `ffmpeg` are examples of modules that are large and not always
needed, and this allows them to only be loaded when they are used.
"""
def __init__(self, parent_module_globals, name,
extra=None, local_name=None, warning=None):
self._local_name = local_name or name
self._parent_module_globals = parent_module_globals
self._extra = extra
self._warning = warning
super(LazyLoader, self).__init__(name)
def _load(self):
"""Load the module and insert it into the parent's globals."""
# Import the target module and insert it into the parent's namespace
try:
module = importlib.import_module(self.__name__)
except ModuleNotFoundError:
# The lazy-loaded module is not currently installed.
msg = f'Unable to import the module `{self._local_name}`'
if self._extra:
from ..__version__ import __title__
msg = f'{msg}. Please run the following command to resolve the issue:\n' \
f' $ pip install {__title__}[{self._extra}]'
raise ImportError(msg) from None
self._parent_module_globals[self._local_name] = module
# Emit a warning if one was specified
if self._warning:
logging.warning(self._warning)
# Make sure to only warn once.
self._warning = None
# Update this object's dict so that if someone keeps a reference to the
# LazyLoader, lookups are efficient (__getattr__ is only called on lookups
# that fail).
self.__dict__.update(module.__dict__)
return module
def __getattr__(self, item):
module = self._load()
return getattr(module, item)
def __dir__(self):
module = self._load()
return dir(module)