1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
"""Deprecation utilities.
:copyright: 2006-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: General Public License version 2 - http://www.gnu.org/licenses
"""
__docformat__ = "restructuredtext en"
import sys
from warnings import warn
class deprecated(type):
"""metaclass to print a warning on instantiation of a deprecated class"""
def __call__(cls, *args, **kwargs):
msg = getattr(cls, "__deprecation_warning__",
"%s is deprecated" % cls.__name__)
warn(msg, DeprecationWarning, stacklevel=2)
return type.__call__(cls, *args, **kwargs)
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 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 deprecated_function(new_func, message=None):
"""Creates a function which fires a DeprecationWarning when used.
For example, if <bar> is deprecated in favour of <foo>:
>>> bar = deprecated_function(foo, 'bar is deprecated')
>>> bar()
sample.py:57: DeprecationWarning: bar is deprecated
bar()
>>>
"""
if message is None:
message = "this function is deprecated, use %s instead" % (
new_func.func_name)
def deprecated(*args, **kwargs):
warn(message, DeprecationWarning, stacklevel=2)
return new_func(*args, **kwargs)
return deprecated
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
# from logilab.common.modutils import LazyObject
# class WarnLazyObject(LazyObject):
# def __init__(self, oldname, newname):
# # XXX doesn't work if module isn't in a package
# package, module = newname.rsplit('.', 1)
# super(WarnLazyObject, self).__init__(package, module)
# self.oldname = oldname
# self.newname = newname
# print 'hop', oldname, newname
# sys.modules[oldname] = self
# def __getobj(self):
# if self._imported is None:
# message = "module %s has moved, it's now %s" % (
# self.oldname, self.newname)
# warn(message, DeprecationWarning, stacklevel=2)
# return super(WarnLazyObject, self).__getobj()
# module_moved = WarnLazyObject
def obsolete(reason="This function is obsolete"):
"""this function is an alternative to `deprecated_function`
when there's no real replacement for the deprecated function
"""
def newdecorator(func):
def wrapped(*args, **kwargs):
warn(reason, DeprecationWarning, stacklevel=2)
return func(*args, **kwargs)
return wrapped
return newdecorator
|