diff options
author | Damien Garaud <damien.garaud@logilab.fr> | 2013-03-12 23:18:24 +0100 |
---|---|---|
committer | Damien Garaud <damien.garaud@logilab.fr> | 2013-03-12 23:18:24 +0100 |
commit | fd1bd30b6d485980157dfeac09b06dfa0149a73f (patch) | |
tree | c52cc2ec1c475efaf5569152790349a64787e0a8 | |
parent | 55cf7e15457138fe04fd40ad0fd87b2a66953189 (diff) | |
download | logilab-common-fd1bd30b6d485980157dfeac09b06dfa0149a73f.tar.gz |
deprecation: implement moved/class_renamed/class_moved using DeprecationManager
-rw-r--r-- | deprecation.py | 129 |
1 files changed, 69 insertions, 60 deletions
diff --git a/deprecation.py b/deprecation.py index 8cd72b5..c5685ec 100644 --- a/deprecation.py +++ b/deprecation.py @@ -24,66 +24,6 @@ from warnings import warn from logilab.common.changelog import Version -def class_renamed(old_name, new_class, message=None): - """automatically creates a class which fires a DeprecationWarning - when instantiated. - - >>> Set = class_renamed('Set', set, 'Set is now replaced by set') - >>> s = Set() - sample.py:57: DeprecationWarning: Set is now replaced by set - s = Set() - >>> - """ - clsdict = {} - if message is None: - message = '%s is deprecated, use %s' % (old_name, new_class.__name__) - clsdict['__deprecation_warning__'] = message - try: - # new-style class - return class_deprecated(old_name, (new_class,), clsdict) - except (NameError, TypeError): - # old-style class - class DeprecatedClass(new_class): - """FIXME: There might be a better way to handle old/new-style class - """ - def __init__(self, *args, **kwargs): - warn(message, DeprecationWarning, stacklevel=2) - new_class.__init__(self, *args, **kwargs) - return DeprecatedClass - - -def class_moved(new_class, old_name=None, message=None): - """nice wrapper around class_renamed when a class has been moved into - another module - """ - if old_name is None: - old_name = new_class.__name__ - if message is None: - message = 'class %s is now available as %s.%s' % ( - old_name, new_class.__module__, new_class.__name__) - return class_renamed(old_name, new_class, message) - - -def moved(modpath, objname): - """use to tell that a callable has been moved to a new module. - - It returns a callable wrapper, so that when its called a warning is printed - telling where the object can be found, import is done (and not before) and - the actual object is called. - - NOTE: the usage is somewhat limited on classes since it will fail if the - wrapper is use in a class ancestors list, use the `class_moved` function - instead (which has no lazy import feature though). - """ - def callnew(*args, **kwargs): - from logilab.common.modutils import load_module_from_name - message = "object %s has been moved to module %s" % (objname, modpath) - warn(message, DeprecationWarning, stacklevel=2) - m = load_module_from_name(modpath) - return getattr(m, objname)(*args, **kwargs) - return callnew - - class DeprecationWrapper(object): """proxy to print a warning on access to any attribute of the wrapped object @@ -156,6 +96,54 @@ class DeprecationManager(object): return type.__call__(cls, *args, **kwargs) return metaclass + def moved(self, version, modpath, objname): + """use to tell that a callable has been moved to a new module. + + It returns a callable wrapper, so that when its called a warning is printed + telling where the object can be found, import is done (and not before) and + the actual object is called. + + NOTE: the usage is somewhat limited on classes since it will fail if the + wrapper is use in a class ancestors list, use the `class_moved` function + instead (which has no lazy import feature though). + """ + def callnew(*args, **kwargs): + from logilab.common.modutils import load_module_from_name + message = "object %s has been moved to module %s" % (objname, modpath) + self.warn(version, message) + m = load_module_from_name(modpath) + return getattr(m, objname)(*args, **kwargs) + return callnew + + def class_renamed(self, version, old_name, new_class, message=None): + clsdict = {} + if message is None: + message = '%s is deprecated, use %s' % (old_name, new_class.__name__) + clsdict['__deprecation_warning__'] = message + try: + # new-style class + return self.class_deprecated(version)(old_name, (new_class,), clsdict) + except (NameError, TypeError): + # old-style class + class DeprecatedClass(new_class): + """FIXME: There might be a better way to handle old/new-style class + """ + def __init__(self, *args, **kwargs): + self.warn(version, message) + new_class.__init__(self, *args, **kwargs) + return DeprecatedClass + + def class_moved(self, version, new_class, old_name=None, message=None): + """nice wrapper around class_renamed when a class has been moved into + another module + """ + if old_name is None: + old_name = new_class.__name__ + if message is None: + message = 'class %s is now available as %s.%s' % ( + old_name, new_class.__module__, new_class.__name__) + return self.class_renamed(version, old_name, new_class, message) + def warn(self, version=None, reason="", stacklevel=2): """Display a deprecation message only if the version is older than the compatible version. @@ -177,3 +165,24 @@ def deprecated(reason=None, stacklevel=2, name=None, doc=None): return _defaultdeprecator.deprecated(None, reason, stacklevel, name, doc) class_deprecated = _defaultdeprecator.class_deprecated() + +def moved(modpath, objname): + return _defaultdeprecator.moved(None, modpath, objname) +moved.__doc__ = _defaultdeprecator.moved.__doc__ + +def class_renamed(old_name, new_class, message=None): + """automatically creates a class which fires a DeprecationWarning + when instantiated. + + >>> Set = class_renamed('Set', set, 'Set is now replaced by set') + >>> s = Set() + sample.py:57: DeprecationWarning: Set is now replaced by set + s = Set() + >>> + """ + return _defaultdeprecator.class_renamed(None, old_name, new_class, message) + +def class_moved(new_class, old_name=None, message=None): + return _defaultdeprecator.class_moved(None, new_class, old_name, message) +class_moved.__doc__ = _defaultdeprecator.class_moved.__doc__ + |