Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if '.' not in name:
raise NotFoundError('{n} is not a valid module name'.format(n=name)) from err
try:
# Try to get an attribute of a module
mod, attr = name.rsplit('.', maxsplit=1)
package = resolve_exposing(mod)
cls = getattr(package, attr)
assert(isinstance(cls, type))
return cls
except ImportError as err:
raise NotFoundError('{n} is not a valid class or module name'.format(n=name)) from err
except AttributeError as err:
raise NotFoundError('{a} does not exist within {m}'.format(a=attr, m=mod)) from err
except AssertionError as err:
raise ResolveError('{a} in {m} is not a valid class'.format(a=attr, m=mod)) from err
def resolve_exposing(name):
""" Attempt an import but reraise any error other than module not found as terminal to resolving """
try:
return import_module(name)
except ImportError as err:
# Pass any non-suspicious errors on
if err.msg.endswith('is not a package') or err.msg.startswith('No module') and name in err.msg:
raise
# Reraise any suspicious errors as terminal - resolve fails
raise ResolveError('Error importing module {n}'.format(n=name)) from err
from collections import abc
from importlib import import_module
from importlib.util import resolve_name
from contextlib import suppress
__all__ = ['patchy', 'super_patchy']
logger = logging.getLogger(__name__)
class ResolveError(Exception):
""" Used to indicate terminal exception during resolve """
pass
class NotFoundError(ResolveError, ImportError):
pass
def patchy(target, source=None):
""" If source is not supplied, auto updates cannot be applied """
if isinstance(target, str):
target = resolve(target)
if isinstance(source, str):
source = resolve(source)
if isinstance(target, ModuleType):
return PatchModule(target, source)
elif isinstance(target, type) and source:
return PatchClass(target, source)
def super_patchy(*args, do_call=True, **kwargs):