~bzr-pqm/bzr/bzr.dev

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