108 lines
3.4 KiB
Python
108 lines
3.4 KiB
Python
![]() |
"""
|
||
|
This module houses a utility class for mocking deprecated modules.
|
||
|
It is for internal use only and should not be used beyond this purpose.
|
||
|
"""
|
||
|
|
||
|
import importlib
|
||
|
from typing import Iterable
|
||
|
import warnings
|
||
|
|
||
|
|
||
|
class _DeprecatedModule:
|
||
|
"""
|
||
|
Class for mocking deprecated modules.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
deprmod : name of module to be deprecated.
|
||
|
deprmodto : name of module as a replacement, optional.
|
||
|
If not given, the __module__ attribute will
|
||
|
be used when needed.
|
||
|
removals : objects or methods in module that will no longer be
|
||
|
accessible once module is removed.
|
||
|
moved : dict, optional
|
||
|
dictionary of function name -> new location for moved
|
||
|
objects
|
||
|
"""
|
||
|
|
||
|
def __init__(self, deprmod, deprmodto=None, removals=None, moved=None):
|
||
|
self.deprmod = deprmod
|
||
|
self.deprmodto = deprmodto
|
||
|
self.removals = removals
|
||
|
if self.removals is not None:
|
||
|
self.removals = frozenset(self.removals)
|
||
|
self.moved = moved
|
||
|
|
||
|
# For introspection purposes.
|
||
|
self.self_dir = frozenset(dir(type(self)))
|
||
|
|
||
|
def __dir__(self) -> Iterable[str]:
|
||
|
deprmodule = self._import_deprmod()
|
||
|
return dir(deprmodule)
|
||
|
|
||
|
def __repr__(self) -> str:
|
||
|
deprmodule = self._import_deprmod()
|
||
|
return repr(deprmodule)
|
||
|
|
||
|
__str__ = __repr__
|
||
|
|
||
|
def __getattr__(self, name: str):
|
||
|
if name in self.self_dir:
|
||
|
return object.__getattribute__(self, name)
|
||
|
|
||
|
try:
|
||
|
deprmodule = self._import_deprmod(self.deprmod)
|
||
|
except ImportError:
|
||
|
if self.deprmodto is None:
|
||
|
raise
|
||
|
|
||
|
# a rename
|
||
|
deprmodule = self._import_deprmod(self.deprmodto)
|
||
|
|
||
|
obj = getattr(deprmodule, name)
|
||
|
|
||
|
if self.removals is not None and name in self.removals:
|
||
|
warnings.warn(
|
||
|
f"{self.deprmod}.{name} is deprecated and will be removed in "
|
||
|
"a future version.",
|
||
|
FutureWarning,
|
||
|
stacklevel=2,
|
||
|
)
|
||
|
elif self.moved is not None and name in self.moved:
|
||
|
warnings.warn(
|
||
|
f"{self.deprmod} is deprecated and will be removed in "
|
||
|
f"a future version.\nYou can access {name} as {self.moved[name]}",
|
||
|
FutureWarning,
|
||
|
stacklevel=2,
|
||
|
)
|
||
|
else:
|
||
|
deprmodto = self.deprmodto
|
||
|
if deprmodto is False:
|
||
|
warnings.warn(
|
||
|
f"{self.deprmod}.{name} is deprecated and will be removed in "
|
||
|
"a future version.",
|
||
|
FutureWarning,
|
||
|
stacklevel=2,
|
||
|
)
|
||
|
else:
|
||
|
if deprmodto is None:
|
||
|
deprmodto = obj.__module__
|
||
|
# The object is actually located in another module.
|
||
|
warnings.warn(
|
||
|
f"{self.deprmod}.{name} is deprecated. Please use "
|
||
|
f"{deprmodto}.{name} instead.",
|
||
|
FutureWarning,
|
||
|
stacklevel=2,
|
||
|
)
|
||
|
|
||
|
return obj
|
||
|
|
||
|
def _import_deprmod(self, mod=None):
|
||
|
if mod is None:
|
||
|
mod = self.deprmod
|
||
|
|
||
|
with warnings.catch_warnings():
|
||
|
warnings.filterwarnings("ignore", category=FutureWarning)
|
||
|
deprmodule = importlib.import_module(mod)
|
||
|
return deprmodule
|