~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/symbol_versioning.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

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
 
20
19
The methods here allow for api symbol versioning.
21
20
"""
22
21
 
 
22
from __future__ import absolute_import
 
23
 
23
24
__all__ = ['deprecated_function',
24
25
           'deprecated_in',
25
26
           'deprecated_list',
28
29
           'deprecated_passed',
29
30
           'set_warning_method',
30
31
           '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
32
           ]
55
33
 
 
34
 
 
35
import warnings
 
36
# Import the 'warn' symbol so bzrlib can call it even if we redefine it
56
37
from warnings import warn
57
38
 
58
39
import bzrlib
59
40
 
60
41
 
61
42
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
43
 
86
44
 
87
45
def deprecated_in(version_tuple):
88
46
    """Generate a message that something was deprecated in a release.
89
47
 
90
48
    >>> deprecated_in((1, 4, 0))
91
 
    '%s was deprecated in version 1.4.'
 
49
    '%s was deprecated in version 1.4.0.'
92
50
    """
93
51
    return ("%%s was deprecated in version %s."
94
52
            % bzrlib._format_version_tuple(version_tuple))
135
93
 
136
94
    def function_decorator(callable):
137
95
        """This is the function python calls to perform the decoration."""
138
 
        
 
96
 
139
97
        def decorated_function(*args, **kwargs):
140
98
            """This is the decorated function."""
141
99
            from bzrlib import trace
152
110
def deprecated_method(deprecation_version):
153
111
    """Decorate a method so that use of it will trigger a warning.
154
112
 
155
 
    To deprecate a static or class method, use 
 
113
    To deprecate a static or class method, use
156
114
 
157
115
        @staticmethod
158
116
        @deprecated_function
159
117
        def ...
160
 
    
 
118
 
161
119
    To deprecate an entire class, decorate __init__.
162
120
    """
163
121
 
164
122
    def method_decorator(callable):
165
123
        """This is the function python calls to perform the decoration."""
166
 
        
 
124
 
167
125
        def decorated_method(self, *args, **kwargs):
168
126
            """This is the decorated method."""
169
127
            from bzrlib import trace
187
145
 
188
146
def deprecated_passed(parameter_value):
189
147
    """Return True if parameter_value was used."""
190
 
    # FIXME: it might be nice to have a parameter deprecation decorator. 
 
148
    # FIXME: it might be nice to have a parameter deprecation decorator.
191
149
    # it would need to handle positional and *args and **kwargs parameters,
192
150
    # which means some mechanism to describe how the parameter was being
193
151
    # passed before deprecation, and some way to deprecate parameters that
213
171
    if len(docstring_lines) == 0:
214
172
        decorated_callable.__doc__ = deprecation_version % ("This " + label)
215
173
    elif len(docstring_lines) == 1:
216
 
        decorated_callable.__doc__ = (callable.__doc__ 
 
174
        decorated_callable.__doc__ = (callable.__doc__
217
175
                                    + "\n"
218
176
                                    + "\n"
219
177
                                    + deprecation_version % ("This " + label)
267
225
            typically from deprecated_in()
268
226
        :param initial_value: The contents of the dict
269
227
        :param variable_name: This allows better warnings to be printed
270
 
        :param advice: String of advice on what callers should do instead 
 
228
        :param advice: String of advice on what callers should do instead
271
229
            of using this variable.
272
230
        """
273
231
        self._deprecation_version = deprecation_version
309
267
        def _warn_deprecated(self, func, *args, **kwargs):
310
268
            warn(msg, DeprecationWarning, stacklevel=3)
311
269
            return func(self, *args, **kwargs)
312
 
            
 
270
 
313
271
        def append(self, obj):
314
272
            """appending to %s is deprecated""" % (variable_name,)
315
273
            return self._warn_deprecated(list.append, obj)
327
285
            return self._warn_deprecated(list.remove, value)
328
286
 
329
287
        def pop(self, index=None):
330
 
            """pop'ing from from %s is deprecated""" % (variable_name,)
 
288
            """pop'ing from %s is deprecated""" % (variable_name,)
331
289
            if index:
332
290
                return self._warn_deprecated(list.pop, index)
333
291
            else:
339
297
 
340
298
def _check_for_filter(error_only):
341
299
    """Check if there is already a filter for deprecation warnings.
342
 
    
 
300
 
343
301
    :param error_only: Only match an 'error' filter
344
302
    :return: True if a filter is found, False otherwise
345
303
    """
346
 
    import warnings
347
304
    for filter in warnings.filters:
348
305
        if issubclass(DeprecationWarning, filter[2]):
349
306
            # This filter will effect DeprecationWarning
352
309
    return False
353
310
 
354
311
 
 
312
def _remove_filter_callable(filter):
 
313
    """Build and returns a callable removing filter from the warnings.
 
314
 
 
315
    :param filter: The filter to remove (can be None).
 
316
 
 
317
    :return: A callable that will remove filter from warnings.filters.
 
318
    """
 
319
    def cleanup():
 
320
        if filter:
 
321
            warnings.filters.remove(filter)
 
322
    return cleanup
 
323
 
 
324
 
355
325
def suppress_deprecation_warnings(override=True):
356
326
    """Call this function to suppress all deprecation warnings.
357
327
 
361
331
 
362
332
    :param override: If True, always set the ignore, if False, only set the
363
333
        ignore if there isn't already a filter.
 
334
 
 
335
    :return: A callable to remove the new warnings this added.
364
336
    """
365
 
    import warnings
366
337
    if not override and _check_for_filter(error_only=False):
367
338
        # If there is already a filter effecting suppress_deprecation_warnings,
368
339
        # then skip it.
369
 
        return
370
 
    warnings.filterwarnings('ignore', category=DeprecationWarning)
 
340
        filter = None
 
341
    else:
 
342
        warnings.filterwarnings('ignore', category=DeprecationWarning)
 
343
        filter = warnings.filters[0]
 
344
    return _remove_filter_callable(filter)
371
345
 
372
346
 
373
347
def activate_deprecation_warnings(override=True):
384
358
    :param override: If False, only add a filter if there isn't an error filter
385
359
        already. (This slightly differs from suppress_deprecation_warnings, in
386
360
        because it always overrides everything but -Werror).
 
361
 
 
362
    :return: A callable to remove the new warnings this added.
387
363
    """
388
 
    import warnings
389
364
    if not override and _check_for_filter(error_only=True):
390
365
        # DeprecationWarnings are already turned into errors, don't downgrade
391
366
        # them to 'default'.
392
 
        return
393
 
    warnings.filterwarnings('default', category=DeprecationWarning)
 
367
        filter = None
 
368
    else:
 
369
        warnings.filterwarnings('default', category=DeprecationWarning)
 
370
        filter = warnings.filters[0]
 
371
    return _remove_filter_callable(filter)