/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/symbol_versioning.py

  • Committer: Michael Ellerman
  • Date: 2006-03-09 00:24:48 UTC
  • mto: (1610.1.8 bzr.mbp.integration)
  • mto: This revision was merged to the branch mainline in revision 1616.
  • Revision ID: michael@ellerman.id.au-20060309002448-70cce15e3d605130
Make the "ignore line" in the commit message editor the "right" width, so
that if you make your message that wide it won't wrap in bzr log output.
Just as a visual aid.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 by Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
"""Symbol versioning
 
19
 
 
20
The methods here allow for api symbol versioning.
 
21
"""
 
22
 
 
23
__all__ = ['deprecated_function',
 
24
           'deprecated_method',
 
25
           'DEPRECATED_PARAMETER',
 
26
           'deprecated_passed',
 
27
           'warn', 'set_warning_method', 'zero_seven',
 
28
           'zero_eight',
 
29
           ]
 
30
 
 
31
from warnings import warn
 
32
 
 
33
 
 
34
DEPRECATED_PARAMETER = "A deprecated parameter marker."
 
35
zero_seven = "%s was deprecated in version 0.7."
 
36
zero_eight = "%s was deprecated in version 0.8."
 
37
 
 
38
 
 
39
def set_warning_method(method):
 
40
    """Set the warning method to be used by this module.
 
41
 
 
42
    It should take a message and a warning category as warnings.warn does.
 
43
    """
 
44
    global warn
 
45
    warn = method
 
46
 
 
47
 
 
48
# TODO - maybe this would be easier to use as one 'smart' method that
 
49
# guess if it is a method or a class or an attribute ? If so, we can
 
50
# add that on top of the primitives, once we have all three written
 
51
# - RBC 20050105
 
52
 
 
53
def deprecated_function(deprecation_version):
 
54
    """Decorate a function so that use of it will trigger a warning."""
 
55
 
 
56
    def function_decorator(callable):
 
57
        """This is the function python calls to perform the decoration."""
 
58
        
 
59
        def decorated_function(*args, **kwargs):
 
60
            """This is the decorated function."""
 
61
            symbol = "%s.%s" % (callable.__module__, 
 
62
                                callable.__name__
 
63
                                )
 
64
            warn(deprecation_version % symbol, DeprecationWarning, stacklevel=2)
 
65
            return callable(*args, **kwargs)
 
66
        _populate_decorated(callable, deprecation_version, "function",
 
67
                            decorated_function)
 
68
        return decorated_function
 
69
    return function_decorator
 
70
 
 
71
 
 
72
def deprecated_method(deprecation_version):
 
73
    """Decorate a method so that use of it will trigger a warning.
 
74
    
 
75
    To deprecate an entire class, decorate __init__.
 
76
    """
 
77
 
 
78
    def method_decorator(callable):
 
79
        """This is the function python calls to perform the decoration."""
 
80
        
 
81
        def decorated_method(self, *args, **kwargs):
 
82
            """This is the decorated method."""
 
83
            symbol = "%s.%s.%s" % (self.__class__.__module__, 
 
84
                                   self.__class__.__name__,
 
85
                                   callable.__name__
 
86
                                   )
 
87
            warn(deprecation_version % symbol, DeprecationWarning, stacklevel=2)
 
88
            return callable(self, *args, **kwargs)
 
89
        _populate_decorated(callable, deprecation_version, "method",
 
90
                            decorated_method)
 
91
        return decorated_method
 
92
    return method_decorator
 
93
 
 
94
 
 
95
def deprecated_passed(parameter_value):
 
96
    """Return True if parameter_value was used."""
 
97
    # FIXME: it might be nice to have a parameter deprecation decorator. 
 
98
    # it would need to handle positional and *args and **kwargs parameters,
 
99
    # which means some mechanism to describe how the parameter was being
 
100
    # passed before deprecation, and some way to deprecate parameters that
 
101
    # were not at the end of the arg list. Thats needed for __init__ where
 
102
    # we cannot just forward to a new method name.I.e. in the following
 
103
    # examples we would want to have callers that pass any value to 'bad' be
 
104
    # given a warning - because we have applied:
 
105
    # @deprecated_parameter('bad', zero_seven)
 
106
    #
 
107
    # def __init__(self, bad=None)
 
108
    # def __init__(self, bad, other)
 
109
    # def __init__(self, **kwargs)
 
110
    # RBC 20060116
 
111
    return not parameter_value is DEPRECATED_PARAMETER
 
112
 
 
113
 
 
114
def _decorate_docstring(callable, deprecation_version, label,
 
115
                        decorated_callable):
 
116
    docstring_lines = callable.__doc__.split('\n')
 
117
    if len(docstring_lines) == 0:
 
118
        decorated_callable.__doc__ = deprecation_version % ("This " + label)
 
119
    elif len(docstring_lines) == 1:
 
120
        decorated_callable.__doc__ = (callable.__doc__ 
 
121
                                    + "\n"
 
122
                                    + "\n"
 
123
                                    + deprecation_version % ("This " + label)
 
124
                                    + "\n")
 
125
    else:
 
126
        spaces = len(docstring_lines[-1])
 
127
        new_doc = callable.__doc__
 
128
        new_doc += "\n" + " " * spaces
 
129
        new_doc += deprecation_version % ("This " + label)
 
130
        new_doc += "\n" + " " * spaces
 
131
        decorated_callable.__doc__ = new_doc
 
132
 
 
133
 
 
134
def _populate_decorated(callable, deprecation_version, label,
 
135
                        decorated_callable):
 
136
    """Populate attributes like __name__ and __doc__ on the decorated callable.
 
137
    """
 
138
    _decorate_docstring(callable, deprecation_version, label,
 
139
                        decorated_callable)
 
140
    decorated_callable.__module__ = callable.__module__
 
141
    decorated_callable.__name__ = callable.__name__
 
142
    decorated_callable.is_deprecated = True