diff options
Diffstat (limited to 'logilab/common/deprecation.py')
-rw-r--r-- | logilab/common/deprecation.py | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/logilab/common/deprecation.py b/logilab/common/deprecation.py index 4aaeba3..4a14aac 100644 --- a/logilab/common/deprecation.py +++ b/logilab/common/deprecation.py @@ -19,6 +19,7 @@ __docformat__ = "restructuredtext en" +import os import sys from warnings import warn from functools import wraps @@ -178,15 +179,71 @@ class DeprecationManager(object): reason = '[%s] %s' % (version, reason) warn(reason, DeprecationWarning, stacklevel=stacklevel) + _defaultdeprecator = DeprecationManager() + +def _get_package_name(number=2): + """ + automagically try to determine the package name from which the warning has + been triggered by loop other calling frames. + + If it fails to do so, return an empty string. + """ + + frame = sys._getframe() + + for i in range(number): + if frame.f_back is None: + break + + frame = frame.f_back + + if frame.f_globals["__package__"] is not None: + return frame.f_globals["__package__"] + + file_name = os.path.split(frame.f_globals["__file__"])[1] + + if file_name.endswith(".py"): + file_name = file_name[:-len(".py")] + + return file_name + + +def send_warning(reason, version=None, stacklevel=2): + """Display a deprecation message only if the version is older than the + compatible version. + """ + module_name = _get_package_name(stacklevel + 1) + + if module_name and version: + reason = '[%s %s] %s' % (module_name, version, reason) + elif module_name: + reason = '[%s] %s' % (module_name, reason) + elif version: + reason = '[%s] %s' % (version, reason) + + warn(reason, DeprecationWarning, stacklevel=stacklevel) + + def deprecated(reason=None, stacklevel=2, name=None, doc=None): return _defaultdeprecator.deprecated(None, reason, stacklevel, name, doc) -class_deprecated = _defaultdeprecator.class_deprecated() + +class class_deprecated(type): + """metaclass to print a warning on instantiation of a deprecated class""" + + def __call__(cls, *args, **kwargs): + msg = getattr(cls, "__deprecation_warning__", + "%(cls)s is deprecated") % {'cls': cls.__name__} + send_warning(msg, stacklevel=4) + return type.__call__(cls, *args, **kwargs) + def moved(modpath, objname): return _defaultdeprecator.moved(None, modpath, objname) + + moved.__doc__ = _defaultdeprecator.moved.__doc__ |