~bzr-pqm/bzr/bzr.dev

5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2006-2011 Canonical Ltd
1534.2.1 by Robert Collins
Implement deprecated_method
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1534.2.1 by Robert Collins
Implement deprecated_method
16
17
"""Symbol versioning tests."""
18
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
19
import warnings
20
21
from bzrlib import symbol_versioning
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
22
from bzrlib.symbol_versioning import (
23
    deprecated_function,
24
    deprecated_in,
25
    deprecated_method,
26
    )
1534.2.1 by Robert Collins
Implement deprecated_method
27
from bzrlib.tests import TestCase
28
29
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
30
@deprecated_function(deprecated_in((0, 7, 0)))
31
def sample_deprecated_function():
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
32
    """Deprecated function docstring."""
1534.2.2 by Robert Collins
Implement deprecated_function.
33
    return 1
34
1534.2.1 by Robert Collins
Implement deprecated_method
35
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
36
a_deprecated_list = symbol_versioning.deprecated_list(deprecated_in((0, 9, 0)),
1836.1.12 by John Arbash Meinel
Move ignores into a file of their own, make DEFAULT_IGNORE a deprecated list. Create deprecated_list in symbol versioning.
37
    'a_deprecated_list', ['one'], extra="Don't use me")
38
39
2227.1.2 by mbp at sourcefrog
Add a simple DeprecatedDict class
40
a_deprecated_dict = symbol_versioning.DeprecatedDict(
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
41
    deprecated_in((0, 14, 0)),
2227.1.2 by mbp at sourcefrog
Add a simple DeprecatedDict class
42
    'a_deprecated_dict',
43
    dict(a=42),
44
    advice='Pull the other one!',
45
    )
46
47
1534.2.1 by Robert Collins
Implement deprecated_method
48
class TestDeprecationWarnings(TestCase):
49
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
50
    def capture_warning(self, message, category, stacklevel=None):
51
        self._warnings.append((message, category, stacklevel))
1534.2.1 by Robert Collins
Implement deprecated_method
52
53
    def setUp(self):
54
        super(TestDeprecationWarnings, self).setUp()
55
        self._warnings = []
56
    
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
57
    @deprecated_method(deprecated_in((0, 7, 0)))
1534.2.1 by Robert Collins
Implement deprecated_method
58
    def deprecated_method(self):
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
59
        """Deprecated method docstring.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
60
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
61
        This might explain stuff.
62
        """
1534.2.2 by Robert Collins
Implement deprecated_function.
63
        return 1
1534.2.1 by Robert Collins
Implement deprecated_method
64
2825.3.3 by Martin Pool
Add basic test for calling deprecated static methods
65
    @staticmethod
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
66
    @deprecated_function(deprecated_in((0, 7, 0)))
2825.3.3 by Martin Pool
Add basic test for calling deprecated static methods
67
    def deprecated_static():
68
        """Deprecated static."""
69
        return 1
70
71
    def test_deprecated_static(self):
2825.3.4 by Martin Pool
Better explanation of deprecation
72
        # XXX: The results are not quite right because the class name is not
73
        # shown - however it is enough to give people a good indication of
74
        # where the problem is.
2825.3.3 by Martin Pool
Add basic test for calling deprecated static methods
75
        expected_warning = (
76
            "bzrlib.tests.test_symbol_versioning."
77
            "deprecated_static "
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
78
            "was deprecated in version 0.7.0.", DeprecationWarning, 2)
2825.3.3 by Martin Pool
Add basic test for calling deprecated static methods
79
        expected_docstring = (
80
            'Deprecated static.\n'
81
            '\n'
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
82
            'This function was deprecated in version 0.7.0.\n'
2825.3.3 by Martin Pool
Add basic test for calling deprecated static methods
83
            )
84
        self.check_deprecated_callable(
85
            expected_warning, expected_docstring,
86
            "deprecated_static",
87
            "bzrlib.tests.test_symbol_versioning",
88
            self.deprecated_static)
89
1534.2.1 by Robert Collins
Implement deprecated_method
90
    def test_deprecated_method(self):
1534.2.2 by Robert Collins
Implement deprecated_function.
91
        expected_warning = (
92
            "bzrlib.tests.test_symbol_versioning."
93
            "TestDeprecationWarnings.deprecated_method "
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
94
            "was deprecated in version 0.7.0.", DeprecationWarning, 2)
95
        expected_docstring = (
96
            'Deprecated method docstring.\n'
97
            '\n'
98
            '        This might explain stuff.\n'
99
            '        \n'
100
            '        This method was deprecated in version 0.7.0.\n'
101
            '        ')
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
102
        self.check_deprecated_callable(expected_warning, expected_docstring,
1534.2.5 by Robert Collins
Set the __name__ attribute on decorated methods and functions.
103
                                       "deprecated_method",
1534.1.3 by Robert Collins
Bugfix the symbol_versioning deprecation decorators to update the
104
                                       "bzrlib.tests.test_symbol_versioning",
1534.2.2 by Robert Collins
Implement deprecated_function.
105
                                       self.deprecated_method)
106
107
    def test_deprecated_function(self):
108
        expected_warning = (
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
109
            "bzrlib.tests.test_symbol_versioning.sample_deprecated_function "
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
110
            "was deprecated in version 0.7.0.", DeprecationWarning, 2)
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
111
        expected_docstring = ('Deprecated function docstring.\n'
112
                              '\n'
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
113
                              'This function was deprecated in version 0.7.0.\n'
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
114
                              )
115
        self.check_deprecated_callable(expected_warning, expected_docstring,
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
116
                                       "sample_deprecated_function",
1534.1.3 by Robert Collins
Bugfix the symbol_versioning deprecation decorators to update the
117
                                       "bzrlib.tests.test_symbol_versioning",
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
118
                                       sample_deprecated_function)
1534.2.2 by Robert Collins
Implement deprecated_function.
119
1836.1.12 by John Arbash Meinel
Move ignores into a file of their own, make DEFAULT_IGNORE a deprecated list. Create deprecated_list in symbol versioning.
120
    def test_deprecated_list(self):
121
        expected_warning = (
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
122
            "Modifying a_deprecated_list was deprecated in version 0.9.0."
1836.1.12 by John Arbash Meinel
Move ignores into a file of their own, make DEFAULT_IGNORE a deprecated list. Create deprecated_list in symbol versioning.
123
            " Don't use me", DeprecationWarning, 3)
124
        old_warning_method = symbol_versioning.warn
125
        try:
126
            symbol_versioning.set_warning_method(self.capture_warning)
127
            self.assertEqual(['one'], a_deprecated_list)
128
            self.assertEqual([], self._warnings)
129
130
            a_deprecated_list.append('foo')
131
            self.assertEqual([expected_warning], self._warnings)
132
            self.assertEqual(['one', 'foo'], a_deprecated_list)
133
134
            a_deprecated_list.extend(['bar', 'baz'])
135
            self.assertEqual([expected_warning]*2, self._warnings)
136
            self.assertEqual(['one', 'foo', 'bar', 'baz'], a_deprecated_list)
137
138
            a_deprecated_list.insert(1, 'xxx')
139
            self.assertEqual([expected_warning]*3, self._warnings)
140
            self.assertEqual(['one', 'xxx', 'foo', 'bar', 'baz'], a_deprecated_list)
141
142
            a_deprecated_list.remove('foo')
143
            self.assertEqual([expected_warning]*4, self._warnings)
144
            self.assertEqual(['one', 'xxx', 'bar', 'baz'], a_deprecated_list)
145
146
            val = a_deprecated_list.pop()
147
            self.assertEqual([expected_warning]*5, self._warnings)
148
            self.assertEqual('baz', val)
149
            self.assertEqual(['one', 'xxx', 'bar'], a_deprecated_list)
150
151
            val = a_deprecated_list.pop(1)
152
            self.assertEqual([expected_warning]*6, self._warnings)
153
            self.assertEqual('xxx', val)
154
            self.assertEqual(['one', 'bar'], a_deprecated_list)
155
        finally:
156
            symbol_versioning.set_warning_method(old_warning_method)
157
2227.1.2 by mbp at sourcefrog
Add a simple DeprecatedDict class
158
    def test_deprecated_dict(self):
159
        expected_warning = (
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
160
            "access to a_deprecated_dict was deprecated in version 0.14.0."
2227.1.2 by mbp at sourcefrog
Add a simple DeprecatedDict class
161
            " Pull the other one!", DeprecationWarning, 2)
162
        old_warning_method = symbol_versioning.warn
163
        try:
164
            symbol_versioning.set_warning_method(self.capture_warning)
165
            self.assertEqual(len(a_deprecated_dict), 1)
166
            self.assertEqual([expected_warning], self._warnings)
167
168
            a_deprecated_dict['b'] = 42
169
            self.assertEqual(a_deprecated_dict['b'], 42)
170
            self.assertTrue('b' in a_deprecated_dict)
171
            del a_deprecated_dict['b']
172
            self.assertFalse('b' in a_deprecated_dict)
173
            self.assertEqual([expected_warning] * 6, self._warnings)
174
        finally:
175
            symbol_versioning.set_warning_method(old_warning_method)
176
177
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
178
    def check_deprecated_callable(self, expected_warning, expected_docstring,
1534.1.3 by Robert Collins
Bugfix the symbol_versioning deprecation decorators to update the
179
                                  expected_name, expected_module,
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
180
                                  deprecated_callable):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
181
        if __doc__ is None:
182
            # With -OO the docstring should just be the deprecated version
183
            expected_docstring = expected_docstring.split('\n')[-2].lstrip()
1534.2.1 by Robert Collins
Implement deprecated_method
184
        old_warning_method = symbol_versioning.warn
185
        try:
186
            symbol_versioning.set_warning_method(self.capture_warning)
1534.2.2 by Robert Collins
Implement deprecated_function.
187
            self.assertEqual(1, deprecated_callable())
1534.2.1 by Robert Collins
Implement deprecated_method
188
            self.assertEqual([expected_warning], self._warnings)
1534.2.2 by Robert Collins
Implement deprecated_function.
189
            deprecated_callable()
1534.2.1 by Robert Collins
Implement deprecated_method
190
            self.assertEqual([expected_warning, expected_warning],
191
                             self._warnings)
1534.2.3 by Robert Collins
decorate docstrings in deprecated functions.
192
            self.assertEqualDiff(expected_docstring, deprecated_callable.__doc__)
1534.2.5 by Robert Collins
Set the __name__ attribute on decorated methods and functions.
193
            self.assertEqualDiff(expected_name, deprecated_callable.__name__)
1534.1.3 by Robert Collins
Bugfix the symbol_versioning deprecation decorators to update the
194
            self.assertEqualDiff(expected_module, deprecated_callable.__module__)
1581.1.1 by Robert Collins
Bugfix aliases to be backwards compatible with plugins providing command.run_argv.
195
            self.assertTrue(deprecated_callable.is_deprecated)
1534.2.1 by Robert Collins
Implement deprecated_method
196
        finally:
197
            symbol_versioning.set_warning_method(old_warning_method)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
198
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
199
    def test_deprecated_passed(self):
200
        self.assertEqual(True, symbol_versioning.deprecated_passed(None))
201
        self.assertEqual(True, symbol_versioning.deprecated_passed(True))
202
        self.assertEqual(True, symbol_versioning.deprecated_passed(False))
203
        self.assertEqual(False,
204
                         symbol_versioning.deprecated_passed(
1534.4.32 by Robert Collins
Rename deprecated_nonce to DEPRECATED_PARAMETER
205
                            symbol_versioning.DEPRECATED_PARAMETER))
1982.3.1 by Robert Collins
New utility function symbol_versioning.deprecation_string. Returns the
206
207
    def test_deprecation_string(self):
208
        """We can get a deprecation string for a method or function."""
209
        self.assertEqual('bzrlib.tests.test_symbol_versioning.'
210
            'TestDeprecationWarnings.test_deprecation_string was deprecated in '
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
211
            'version 0.11.0.',
1982.3.1 by Robert Collins
New utility function symbol_versioning.deprecation_string. Returns the
212
            symbol_versioning.deprecation_string(
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
213
            self.test_deprecation_string,
214
            deprecated_in((0, 11, 0))))
1982.3.1 by Robert Collins
New utility function symbol_versioning.deprecation_string. Returns the
215
        self.assertEqual('bzrlib.symbol_versioning.deprecated_function was '
4634.50.7 by John Arbash Meinel
Fix the symbol versioning output now that we use the wide form.
216
            'deprecated in version 0.11.0.',
1982.3.1 by Robert Collins
New utility function symbol_versioning.deprecation_string. Returns the
217
            symbol_versioning.deprecation_string(
218
                symbol_versioning.deprecated_function,
3948.3.1 by Martin Pool
Remove old static deprecation template strings, and update style of their tests
219
                deprecated_in((0, 11, 0))))
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
220
221
222
class TestSuppressAndActivate(TestCase):
223
224
    def setUp(self):
4153.1.2 by Andrew Bennetts
Add missing TestCase.setUp upcalls.
225
        TestCase.setUp(self)
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
226
        existing_filters = list(warnings.filters)
227
        def restore():
228
            warnings.filters[:] = existing_filters
229
        self.addCleanup(restore)
3427.5.5 by John Arbash Meinel
Disable suppression if there is already a filter present for Warnings
230
        # Clean out the filters so we have a clean slate.
231
        warnings.resetwarnings()
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
232
233
    def assertFirstWarning(self, action, category):
234
        """Test the first warning in the filters is correct"""
235
        first = warnings.filters[0]
236
        self.assertEqual((action, category), (first[0], first[2]))
237
238
    def test_suppress_deprecation_warnings(self):
239
        """suppress_deprecation_warnings sets DeprecationWarning to ignored."""
240
        symbol_versioning.suppress_deprecation_warnings()
241
        self.assertFirstWarning('ignore', DeprecationWarning)
242
5320.2.1 by Robert Collins
The symbol_versioning module can now cleanup after itself -
243
    def test_set_restore_filters(self):
244
        original_filters = warnings.filters[:]
245
        symbol_versioning.suppress_deprecation_warnings()()
246
        self.assertEqual(original_filters, warnings.filters)
247
3427.5.5 by John Arbash Meinel
Disable suppression if there is already a filter present for Warnings
248
    def test_suppress_deprecation_with_warning_filter(self):
249
        """don't suppress if we already have a filter"""
3427.5.7 by John Arbash Meinel
Bring back always in the form of 'override'.
250
        warnings.filterwarnings('error', category=Warning)
251
        self.assertFirstWarning('error', Warning)
3427.5.5 by John Arbash Meinel
Disable suppression if there is already a filter present for Warnings
252
        self.assertEqual(1, len(warnings.filters))
3427.5.7 by John Arbash Meinel
Bring back always in the form of 'override'.
253
        symbol_versioning.suppress_deprecation_warnings(override=False)
254
        self.assertFirstWarning('error', Warning)
3427.5.5 by John Arbash Meinel
Disable suppression if there is already a filter present for Warnings
255
        self.assertEqual(1, len(warnings.filters))
256
257
    def test_suppress_deprecation_with_filter(self):
258
        """don't suppress if we already have a filter"""
3427.5.7 by John Arbash Meinel
Bring back always in the form of 'override'.
259
        warnings.filterwarnings('error', category=DeprecationWarning)
260
        self.assertFirstWarning('error', DeprecationWarning)
261
        self.assertEqual(1, len(warnings.filters))
262
        symbol_versioning.suppress_deprecation_warnings(override=False)
263
        self.assertFirstWarning('error', DeprecationWarning)
264
        self.assertEqual(1, len(warnings.filters))
265
        symbol_versioning.suppress_deprecation_warnings(override=True)
266
        self.assertFirstWarning('ignore', DeprecationWarning)
267
        self.assertEqual(2, len(warnings.filters))
3427.5.5 by John Arbash Meinel
Disable suppression if there is already a filter present for Warnings
268
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
269
    def test_activate_deprecation_no_error(self):
270
        # First nuke the filters, so we know it is clean
3427.5.6 by John Arbash Meinel
remove the parameter from activate, and just have it always False
271
        symbol_versioning.activate_deprecation_warnings()
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
272
        self.assertFirstWarning('default', DeprecationWarning)
273
274
    def test_activate_deprecation_with_error(self):
275
        # First nuke the filters, so we know it is clean
276
        # Add a warning == error rule
277
        warnings.filterwarnings('error', category=Warning)
278
        self.assertFirstWarning('error', Warning)
279
        self.assertEqual(1, len(warnings.filters))
3427.5.7 by John Arbash Meinel
Bring back always in the form of 'override'.
280
        symbol_versioning.activate_deprecation_warnings(override=False)
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
281
        # There should not be a new warning
282
        self.assertFirstWarning('error', Warning)
283
        self.assertEqual(1, len(warnings.filters))
284
285
    def test_activate_deprecation_with_DW_error(self):
286
        # First nuke the filters, so we know it is clean
287
        # Add a warning == error rule
288
        warnings.filterwarnings('error', category=DeprecationWarning)
289
        self.assertFirstWarning('error', DeprecationWarning)
290
        self.assertEqual(1, len(warnings.filters))
3427.5.7 by John Arbash Meinel
Bring back always in the form of 'override'.
291
        symbol_versioning.activate_deprecation_warnings(override=False)
3427.5.3 by John Arbash Meinel
Update the activate_deprecation_warnings so it can be skipped if there is already an error set.
292
        # There should not be a new warning
293
        self.assertFirstWarning('error', DeprecationWarning)
294
        self.assertEqual(1, len(warnings.filters))
3427.5.7 by John Arbash Meinel
Bring back always in the form of 'override'.
295
        symbol_versioning.activate_deprecation_warnings(override=True)
296
        self.assertFirstWarning('default', DeprecationWarning)
297
        self.assertEqual(2, len(warnings.filters))