root / logilab.pylintinstaller / logilab / common / deprecation.py

Revision 202:d67e86292521, 4.4 kB (checked in by tziade@…, 9 months ago)

added logilab.pylintinstaller

Line 
1# This program is free software; you can redistribute it and/or modify it under
2# the terms of the GNU General Public License as published by the Free Software
3# Foundation; either version 2 of the License, or (at your option) any later
4# version.
5#
6# This program is distributed in the hope that it will be useful, but WITHOUT
7# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9#
10# You should have received a copy of the GNU General Public License along with
11# this program; if not, write to the Free Software Foundation, Inc.,
12# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
13"""Deprecation utilities
14
15:author:    Logilab
16:copyright: 2006-2008 LOGILAB S.A. (Paris, FRANCE)
17:contact:   http://www.logilab.fr/ -- mailto:python-projects@logilab.org
18"""
19__docformat__ = "restructuredtext en"
20
21from warnings import warn
22
23from logilab.common.modutils import load_module_from_name
24
25class deprecated(type):
26    """metaclass to print a warning on instantiation of a deprecated class"""
27   
28    def __call__(cls, *args, **kwargs):
29        msg = getattr(cls, "__deprecation_warning__",
30                      "%s is deprecated" % cls.__name__)
31        warn(msg, DeprecationWarning, stacklevel=2)
32        return type.__call__(cls, *args, **kwargs)
33
34
35def class_renamed(old_name, new_class, message=None):
36    """automatically creates a class which fires a DeprecationWarning
37    when instantiated.
38   
39    >>> Set = class_renamed('Set', set, 'Set is now replaced by set')
40    >>> s = Set()
41    sample.py:57: DeprecationWarning: Set is now replaced by set
42      s = Set()
43    >>>
44    """
45    clsdict = {}
46    if message is not None:
47        clsdict['__deprecation_warning__'] = message
48    try:
49        # new-style class
50        return deprecated(old_name, (new_class,), clsdict)
51    except (NameError, TypeError):
52        # old-style class
53        class DeprecatedClass(new_class):
54            """FIXME: There might be a better way to handle old/new-style class
55            """
56            def __init__(self, *args, **kwargs):
57                warn(message, DeprecationWarning, stacklevel=2)
58                new_class.__init__(self, *args, **kwargs)
59        return DeprecatedClass
60
61
62def class_moved(new_class, old_name=None, message=None):
63    """nice wrapper around class_renamed when a class has been moved into
64    another module
65    """
66    if old_name is None:
67        old_name = new_class.__name__
68    if message is None:
69        message = 'class %s is now available as %s.%s' % (
70            old_name, new_class.__module__, new_class.__name__)
71    return class_renamed(old_name, new_class, message)
72
73
74def deprecated_function(new_func, message=None):
75    """creates a function which fires a DeprecationWarning when used
76
77    For example, if <bar> is deprecated in favour of <foo> :
78    >>> bar = deprecated_function(foo, 'bar is deprecated')
79    >>> bar()
80    sample.py:57: DeprecationWarning: bar is deprecated
81      bar()
82    >>>
83    """
84    if message is None:
85        message = "this function is deprecated, use %s instead" % (
86            new_func.func_name)
87    def deprecated(*args, **kwargs):
88        warn(message, DeprecationWarning, stacklevel=2)
89        return new_func(*args, **kwargs)
90    return deprecated
91
92
93def moved(modpath, objname):
94    """use to tell that a callable has been moved to a new module.
95
96    It returns a callable wrapper, so that when its called a warning is printed
97    telling where the object can be found, import is done (and not before) and
98    the actual object is called.
99
100    NOTE: the usage is somewhat limited on classes since it will fail if the
101    wrapper is use in a class ancestors list, use the `class_moved` function
102    instead (which has no lazy import feature though).
103    """
104    def callnew(*args, **kwargs):
105        message = "this object has been moved, it's now %s.%s" % (
106            modpath, objname)
107        warn(message, DeprecationWarning, stacklevel=2)
108        m = load_module_from_name(modpath)
109        return getattr(m, objname)(*args, **kwargs)
110    return callnew
111
112def obsolete(reason="This function is obsolete"):
113    """this function is an alternative to `deprecated_function`
114    when there's no real replacement for the deprecated function
115    """
116    def newdecorator(func):
117        def wrapped(*args, **kwargs):
118            warn(reason, DeprecationWarning, stacklevel=2)
119            return func(*args, **kwargs)
120        return wrapped
121    return newdecorator
Note: See TracBrowser for help on using the browser.