~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/symbol_versioning.py

  • Committer: Patch Queue Manager
  • Date: 2011-09-15 15:37:20 UTC
  • mfrom: (6140.1.3 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20110915153720-n17t6m5oh5bblqad
(vila) Open 2.5b2 for bugfixes (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
2
 
#   Authors: Robert Collins <robert.collins@canonical.com> and others
 
1
# Copyright (C) 2006-2010 Canonical Ltd
3
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
13
12
#
14
13
# You should have received a copy of the GNU General Public License
15
14
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
16
 
18
17
"""Symbol versioning
19
18
 
28
27
           'deprecated_passed',
29
28
           'set_warning_method',
30
29
           'warn',
31
 
           'zero_seven',
32
 
           'zero_eight',
33
 
           'zero_nine',
34
 
           'zero_ten',
35
 
           'zero_eleven',
36
 
           'zero_twelve',
37
 
           'zero_thirteen',
38
 
           'zero_fourteen',
39
 
           'zero_fifteen',
40
 
           'zero_sixteen',
41
 
           'zero_seventeen',
42
 
           'zero_eighteen',
43
 
           'zero_ninety',
44
 
           'zero_ninetyone',
45
 
           'zero_ninetytwo',
46
 
           'zero_ninetythree',
47
 
           'one_zero',
48
 
           'one_one',
49
 
           'one_two',
50
 
           'one_three',
51
 
           'one_four',
52
 
           'one_five',
53
 
           'one_six',
54
30
           ]
55
31
 
 
32
 
 
33
import warnings
 
34
# Import the 'warn' symbol so bzrlib can call it even if we redefine it
56
35
from warnings import warn
57
36
 
58
37
import bzrlib
59
38
 
60
39
 
61
40
DEPRECATED_PARAMETER = "A deprecated parameter marker."
62
 
zero_seven = "%s was deprecated in version 0.7."
63
 
zero_eight = "%s was deprecated in version 0.8."
64
 
zero_nine = "%s was deprecated in version 0.9."
65
 
zero_ten = "%s was deprecated in version 0.10."
66
 
zero_eleven = "%s was deprecated in version 0.11."
67
 
zero_twelve = "%s was deprecated in version 0.12."
68
 
zero_thirteen = "%s was deprecated in version 0.13."
69
 
zero_fourteen = "%s was deprecated in version 0.14."
70
 
zero_fifteen = "%s was deprecated in version 0.15."
71
 
zero_sixteen = "%s was deprecated in version 0.16."
72
 
zero_seventeen = "%s was deprecated in version 0.17."
73
 
zero_eighteen = "%s was deprecated in version 0.18."
74
 
zero_ninety = "%s was deprecated in version 0.90."
75
 
zero_ninetyone = "%s was deprecated in version 0.91."
76
 
zero_ninetytwo = "%s was deprecated in version 0.92."
77
 
one_zero = "%s was deprecated in version 1.0."
78
 
zero_ninetythree = one_zero # Maintained for backwards compatibility
79
 
one_one = "%s was deprecated in version 1.1."
80
 
one_two = "%s was deprecated in version 1.2."
81
 
one_three = "%s was deprecated in version 1.3."
82
 
one_four = "%s was deprecated in version 1.4."
83
 
one_five = "%s was deprecated in version 1.5."
84
 
one_six = "%s was deprecated in version 1.6."
85
41
 
86
42
 
87
43
def deprecated_in(version_tuple):
88
44
    """Generate a message that something was deprecated in a release.
89
45
 
90
46
    >>> deprecated_in((1, 4, 0))
91
 
    '%s was deprecated in version 1.4.'
 
47
    '%s was deprecated in version 1.4.0.'
92
48
    """
93
49
    return ("%%s was deprecated in version %s."
94
50
            % bzrlib._format_version_tuple(version_tuple))
135
91
 
136
92
    def function_decorator(callable):
137
93
        """This is the function python calls to perform the decoration."""
138
 
        
 
94
 
139
95
        def decorated_function(*args, **kwargs):
140
96
            """This is the decorated function."""
 
97
            from bzrlib import trace
 
98
            trace.mutter_callsite(4, "Deprecated function called")
141
99
            warn(deprecation_string(callable, deprecation_version),
142
100
                DeprecationWarning, stacklevel=2)
143
101
            return callable(*args, **kwargs)
150
108
def deprecated_method(deprecation_version):
151
109
    """Decorate a method so that use of it will trigger a warning.
152
110
 
153
 
    To deprecate a static or class method, use 
 
111
    To deprecate a static or class method, use
154
112
 
155
113
        @staticmethod
156
114
        @deprecated_function
157
115
        def ...
158
 
    
 
116
 
159
117
    To deprecate an entire class, decorate __init__.
160
118
    """
161
119
 
162
120
    def method_decorator(callable):
163
121
        """This is the function python calls to perform the decoration."""
164
 
        
 
122
 
165
123
        def decorated_method(self, *args, **kwargs):
166
124
            """This is the decorated method."""
 
125
            from bzrlib import trace
167
126
            if callable.__name__ == '__init__':
168
127
                symbol = "%s.%s" % (self.__class__.__module__,
169
128
                                    self.__class__.__name__,
173
132
                                       self.__class__.__name__,
174
133
                                       callable.__name__
175
134
                                       )
 
135
            trace.mutter_callsite(4, "Deprecated method called")
176
136
            warn(deprecation_version % symbol, DeprecationWarning, stacklevel=2)
177
137
            return callable(self, *args, **kwargs)
178
138
        _populate_decorated(callable, deprecation_version, "method",
183
143
 
184
144
def deprecated_passed(parameter_value):
185
145
    """Return True if parameter_value was used."""
186
 
    # FIXME: it might be nice to have a parameter deprecation decorator. 
 
146
    # FIXME: it might be nice to have a parameter deprecation decorator.
187
147
    # it would need to handle positional and *args and **kwargs parameters,
188
148
    # which means some mechanism to describe how the parameter was being
189
149
    # passed before deprecation, and some way to deprecate parameters that
209
169
    if len(docstring_lines) == 0:
210
170
        decorated_callable.__doc__ = deprecation_version % ("This " + label)
211
171
    elif len(docstring_lines) == 1:
212
 
        decorated_callable.__doc__ = (callable.__doc__ 
 
172
        decorated_callable.__doc__ = (callable.__doc__
213
173
                                    + "\n"
214
174
                                    + "\n"
215
175
                                    + deprecation_version % ("This " + label)
263
223
            typically from deprecated_in()
264
224
        :param initial_value: The contents of the dict
265
225
        :param variable_name: This allows better warnings to be printed
266
 
        :param advice: String of advice on what callers should do instead 
 
226
        :param advice: String of advice on what callers should do instead
267
227
            of using this variable.
268
228
        """
269
229
        self._deprecation_version = deprecation_version
305
265
        def _warn_deprecated(self, func, *args, **kwargs):
306
266
            warn(msg, DeprecationWarning, stacklevel=3)
307
267
            return func(self, *args, **kwargs)
308
 
            
 
268
 
309
269
        def append(self, obj):
310
270
            """appending to %s is deprecated""" % (variable_name,)
311
271
            return self._warn_deprecated(list.append, obj)
323
283
            return self._warn_deprecated(list.remove, value)
324
284
 
325
285
        def pop(self, index=None):
326
 
            """pop'ing from from %s is deprecated""" % (variable_name,)
 
286
            """pop'ing from %s is deprecated""" % (variable_name,)
327
287
            if index:
328
288
                return self._warn_deprecated(list.pop, index)
329
289
            else:
335
295
 
336
296
def _check_for_filter(error_only):
337
297
    """Check if there is already a filter for deprecation warnings.
338
 
    
 
298
 
339
299
    :param error_only: Only match an 'error' filter
340
300
    :return: True if a filter is found, False otherwise
341
301
    """
342
 
    import warnings
343
302
    for filter in warnings.filters:
344
303
        if issubclass(DeprecationWarning, filter[2]):
345
304
            # This filter will effect DeprecationWarning
348
307
    return False
349
308
 
350
309
 
 
310
def _remove_filter_callable(filter):
 
311
    """Build and returns a callable removing filter from the warnings.
 
312
 
 
313
    :param filter: The filter to remove (can be None).
 
314
 
 
315
    :return: A callable that will remove filter from warnings.filters.
 
316
    """
 
317
    def cleanup():
 
318
        if filter:
 
319
            warnings.filters.remove(filter)
 
320
    return cleanup
 
321
 
 
322
 
351
323
def suppress_deprecation_warnings(override=True):
352
324
    """Call this function to suppress all deprecation warnings.
353
325
 
357
329
 
358
330
    :param override: If True, always set the ignore, if False, only set the
359
331
        ignore if there isn't already a filter.
 
332
 
 
333
    :return: A callable to remove the new warnings this added.
360
334
    """
361
 
    import warnings
362
335
    if not override and _check_for_filter(error_only=False):
363
336
        # If there is already a filter effecting suppress_deprecation_warnings,
364
337
        # then skip it.
365
 
        return
366
 
    warnings.filterwarnings('ignore', category=DeprecationWarning)
 
338
        filter = None
 
339
    else:
 
340
        warnings.filterwarnings('ignore', category=DeprecationWarning)
 
341
        filter = warnings.filters[0]
 
342
    return _remove_filter_callable(filter)
367
343
 
368
344
 
369
345
def activate_deprecation_warnings(override=True):
380
356
    :param override: If False, only add a filter if there isn't an error filter
381
357
        already. (This slightly differs from suppress_deprecation_warnings, in
382
358
        because it always overrides everything but -Werror).
 
359
 
 
360
    :return: A callable to remove the new warnings this added.
383
361
    """
384
 
    import warnings
385
362
    if not override and _check_for_filter(error_only=True):
386
363
        # DeprecationWarnings are already turned into errors, don't downgrade
387
364
        # them to 'default'.
388
 
        return
389
 
    warnings.filterwarnings('default', category=DeprecationWarning)
 
365
        filter = None
 
366
    else:
 
367
        warnings.filterwarnings('default', category=DeprecationWarning)
 
368
        filter = warnings.filters[0]
 
369
    return _remove_filter_callable(filter)