~bzr-pqm/bzr/bzr.dev

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