_depr_module.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. """
  2. This module houses a utility class for mocking deprecated modules.
  3. It is for internal use only and should not be used beyond this purpose.
  4. """
  5. import importlib
  6. from typing import Iterable
  7. import warnings
  8. class _DeprecatedModule:
  9. """
  10. Class for mocking deprecated modules.
  11. Parameters
  12. ----------
  13. deprmod : name of module to be deprecated.
  14. deprmodto : name of module as a replacement, optional.
  15. If not given, the __module__ attribute will
  16. be used when needed.
  17. removals : objects or methods in module that will no longer be
  18. accessible once module is removed.
  19. moved : dict, optional
  20. dictionary of function name -> new location for moved
  21. objects
  22. """
  23. def __init__(self, deprmod, deprmodto=None, removals=None, moved=None):
  24. self.deprmod = deprmod
  25. self.deprmodto = deprmodto
  26. self.removals = removals
  27. if self.removals is not None:
  28. self.removals = frozenset(self.removals)
  29. self.moved = moved
  30. # For introspection purposes.
  31. self.self_dir = frozenset(dir(type(self)))
  32. def __dir__(self) -> Iterable[str]:
  33. deprmodule = self._import_deprmod()
  34. return dir(deprmodule)
  35. def __repr__(self) -> str:
  36. deprmodule = self._import_deprmod()
  37. return repr(deprmodule)
  38. __str__ = __repr__
  39. def __getattr__(self, name: str):
  40. if name in self.self_dir:
  41. return object.__getattribute__(self, name)
  42. try:
  43. deprmodule = self._import_deprmod(self.deprmod)
  44. except ImportError:
  45. if self.deprmodto is None:
  46. raise
  47. # a rename
  48. deprmodule = self._import_deprmod(self.deprmodto)
  49. obj = getattr(deprmodule, name)
  50. if self.removals is not None and name in self.removals:
  51. warnings.warn(
  52. f"{self.deprmod}.{name} is deprecated and will be removed in "
  53. "a future version.",
  54. FutureWarning,
  55. stacklevel=2,
  56. )
  57. elif self.moved is not None and name in self.moved:
  58. warnings.warn(
  59. f"{self.deprmod} is deprecated and will be removed in "
  60. f"a future version.\nYou can access {name} as {self.moved[name]}",
  61. FutureWarning,
  62. stacklevel=2,
  63. )
  64. else:
  65. deprmodto = self.deprmodto
  66. if deprmodto is False:
  67. warnings.warn(
  68. f"{self.deprmod}.{name} is deprecated and will be removed in "
  69. "a future version.",
  70. FutureWarning,
  71. stacklevel=2,
  72. )
  73. else:
  74. if deprmodto is None:
  75. deprmodto = obj.__module__
  76. # The object is actually located in another module.
  77. warnings.warn(
  78. f"{self.deprmod}.{name} is deprecated. Please use "
  79. f"{deprmodto}.{name} instead.",
  80. FutureWarning,
  81. stacklevel=2,
  82. )
  83. return obj
  84. def _import_deprmod(self, mod=None):
  85. if mod is None:
  86. mod = self.deprmod
  87. with warnings.catch_warnings():
  88. warnings.filterwarnings("ignore", category=FutureWarning)
  89. deprmodule = importlib.import_module(mod)
  90. return deprmodule