87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
import warnings
|
|
from importlib import import_module
|
|
|
|
|
|
class RemovedInWagtail80Warning(DeprecationWarning):
|
|
pass
|
|
|
|
|
|
removed_in_next_version_warning = RemovedInWagtail80Warning
|
|
|
|
|
|
class RemovedInWagtail90Warning(PendingDeprecationWarning):
|
|
pass
|
|
|
|
|
|
class MovedDefinitionHandler:
|
|
"""
|
|
A wrapper for module objects to enable definitions to be moved to a new module, with a
|
|
deprecation path for the old location. Importing the name from the old location will
|
|
raise a deprecation warning (but will still complete successfully).
|
|
|
|
To use, place the following code in the old module:
|
|
|
|
import sys
|
|
from wagtail.utils.deprecation import MovedDefinitionHandler, RemovedInWagtailXWarning
|
|
|
|
MOVED_DEFINITIONS = {
|
|
'SomeClassOrVariableName': 'path.to.new.module',
|
|
}
|
|
|
|
sys.modules[__name__] = MovedDefinitionHandler(sys.modules[__name__], MOVED_DEFINITIONS, RemovedInWagtailXWarning)
|
|
|
|
If the name of the definition has also changed, you can specify its new name along with
|
|
the path to its new module using a tuple. For example:
|
|
|
|
MOVED_DEFINITIONS = {
|
|
'SomeClassOrVariableName': ('path.to.new.module', 'NewClassOrVariableName'),
|
|
}
|
|
"""
|
|
|
|
def __init__(self, real_module, moved_definitions, warning_class):
|
|
self.real_module = real_module
|
|
self.moved_definitions = moved_definitions
|
|
self.warning_class = warning_class
|
|
|
|
def __getattr__(self, name):
|
|
try:
|
|
return getattr(self.real_module, name)
|
|
except AttributeError as e:
|
|
try:
|
|
# is the missing name one of our moved definitions?
|
|
new_module_name = self.moved_definitions[name]
|
|
new_name = name
|
|
|
|
if isinstance(new_module_name, tuple):
|
|
new_module_name, new_name = new_module_name
|
|
|
|
except KeyError:
|
|
# raise the original AttributeError without including the inner try/catch
|
|
# in the stack trace
|
|
raise e from None
|
|
|
|
if new_name != name:
|
|
warnings.warn(
|
|
"%s has been moved from %s to %s and renamed to %s"
|
|
% (name, self.real_module.__name__, new_module_name, new_name),
|
|
category=self.warning_class,
|
|
stacklevel=2,
|
|
)
|
|
|
|
else:
|
|
warnings.warn(
|
|
"%s has been moved from %s to %s"
|
|
% (name, self.real_module.__name__, new_module_name),
|
|
category=self.warning_class,
|
|
stacklevel=2,
|
|
)
|
|
|
|
# load the requested definition from the module named in moved_definitions
|
|
new_module = import_module(new_module_name)
|
|
definition = getattr(new_module, new_name)
|
|
|
|
# stash that definition into the current module so that we don't have to
|
|
# redo this import next time we access it
|
|
setattr(self.real_module, name, definition)
|
|
|
|
return definition
|