/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
1
# Copyright (C) 2005-2011 Canonical Ltd
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
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
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
16
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
17
"""These tests are tests about the source code of breezy itself.
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
18
19
They are useful for testing code quality, checking coverage metric etc.
20
"""
21
22
import os
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
23
import parser
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
24
import re
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
25
import symbol
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
26
import sys
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
27
import token
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
28
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
29
from breezy import (
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
30
    osutils,
31
    )
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
32
import breezy.branch
33
from breezy.tests import (
7167.1.2 by Jelmer Vernooij
Add test_flake8.
34
    features,
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
35
    TestCase,
36
    TestSkipped,
37
    )
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
38
39
2052.3.8 by John Arbash Meinel
Better documentation about the exception variables
40
# Files which are listed here will be skipped when testing for Copyright (or
41
# GPL) statements.
5193.6.24 by Vincent Ladeuil
Add copyrights in placeholder __init__.py files and fix the fallout from bzrlib/doc_generate/conf.py rename.
42
COPYRIGHT_EXCEPTIONS = [
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
43
    'breezy/_bencode_py.py',
44
    'breezy/doc_generate/conf.py',
45
    'breezy/lsprof.py',
5193.6.24 by Vincent Ladeuil
Add copyrights in placeholder __init__.py files and fix the fallout from bzrlib/doc_generate/conf.py rename.
46
    ]
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
47
5193.6.24 by Vincent Ladeuil
Add copyrights in placeholder __init__.py files and fix the fallout from bzrlib/doc_generate/conf.py rename.
48
LICENSE_EXCEPTIONS = [
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
49
    'breezy/_bencode_py.py',
50
    'breezy/doc_generate/conf.py',
51
    'breezy/lsprof.py',
5193.6.24 by Vincent Ladeuil
Add copyrights in placeholder __init__.py files and fix the fallout from bzrlib/doc_generate/conf.py rename.
52
    ]
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
53
# Technically, 'breezy/lsprof.py' should be 'breezy/util/lsprof.py',
54
# (we do not check breezy/util/, since that is code bundled from elsewhere)
2052.3.8 by John Arbash Meinel
Better documentation about the exception variables
55
# but for compatibility with previous releases, we don't want to move it.
4634.37.3 by Martin Pool
sphinx autogenerate configuration is exempt from test_source
56
#
57
# sphinx_conf is semi-autogenerated.
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
58
3572.1.7 by Marius Kruger
Code style and minor changes as per review.
59
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
60
class TestSourceHelper(TestCase):
61
62
    def source_file_name(self, package):
63
        """Return the path of the .py file for package."""
3616.2.7 by Mark Hammond
prefer getattr() over hasattr()
64
        if getattr(sys, "frozen", None) is not None:
3616.2.5 by Mark Hammond
don't try and test source code when we are frozen.
65
            raise TestSkipped("can't test sources in frozen distributions.")
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
66
        path = package.__file__
67
        if path[-1] in 'co':
68
            return path[:-1]
69
        else:
70
            return path
71
72
73
class TestApiUsage(TestSourceHelper):
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
74
1524 by Robert Collins
Test the uses of WorkingTree from branch.py
75
    def find_occurences(self, rule, filename):
76
        """Find the number of occurences of rule in a file."""
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
77
        occurences = 0
6973.7.5 by Jelmer Vernooij
s/file/open.
78
        source = open(filename, 'r')
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
79
        for line in source:
1524 by Robert Collins
Test the uses of WorkingTree from branch.py
80
            if line.find(rule) > -1:
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
81
                occurences += 1
1524 by Robert Collins
Test the uses of WorkingTree from branch.py
82
        return occurences
83
84
    def test_branch_working_tree(self):
85
        """Test that the number of uses of working_tree in branch is stable."""
86
        occurences = self.find_occurences('self.working_tree()',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
87
                                          self.source_file_name(breezy.branch))
1523 by Robert Collins
Test for the number of uses of self.working_tree() in branch.py
88
        # do not even think of increasing this number. If you think you need to
89
        # increase it, then you almost certainly are doing something wrong as
90
        # the relationship from working_tree to branch is one way.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
91
        # Note that this is an exact equality so that when the number drops,
7143.15.2 by Jelmer Vernooij
Run autopep8.
92
        # it is not given a buffer but rather has this test updated immediately.
1534.4.35 by Robert Collins
Give branch its own basis tree and last_revision methods; deprecated branch.working_tree()
93
        self.assertEqual(0, occurences)
1524 by Robert Collins
Test the uses of WorkingTree from branch.py
94
95
    def test_branch_WorkingTree(self):
96
        """Test that the number of uses of working_tree in branch is stable."""
97
        occurences = self.find_occurences('WorkingTree',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
98
                                          self.source_file_name(breezy.branch))
2696.1.1 by Martin Pool
Remove things deprecated in 0.11 and earlier
99
        # Do not even think of increasing this number. If you think you need to
1524 by Robert Collins
Test the uses of WorkingTree from branch.py
100
        # increase it, then you almost certainly are doing something wrong as
101
        # the relationship from working_tree to branch is one way.
2696.1.1 by Martin Pool
Remove things deprecated in 0.11 and earlier
102
        # As of 20070809, there are no longer any mentions at all.
103
        self.assertEqual(0, occurences)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
104
105
106
class TestSource(TestSourceHelper):
107
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
108
    def get_breezy_dir(self):
109
        """Get the path to the root of breezy"""
110
        source = self.source_file_name(breezy)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
111
        source_dir = os.path.dirname(source)
112
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
113
        # Avoid the case when breezy is packaged in a zip file
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
114
        if not os.path.isdir(source_dir):
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
115
            raise TestSkipped(
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
116
                'Cannot find breezy source directory. Expected %s'
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
117
                % source_dir)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
118
        return source_dir
119
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
120
    def get_source_files(self, extensions=None):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
121
        """Yield all source files for bzr and breezy
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
122
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
123
        :param our_files_only: If true, exclude files from included libraries
124
            or plugins.
125
        """
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
126
        breezy_dir = self.get_breezy_dir()
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
127
        if extensions is None:
128
            extensions = ('.py',)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
129
130
        # This is the front-end 'bzr' script
6622.1.1 by Jelmer Vernooij
Rename bzrlib => brzlib, bzr => brz.
131
        bzr_path = self.get_brz_path()
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
132
        yield bzr_path
133
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
134
        for root, dirs, files in os.walk(breezy_dir):
2102.3.1 by mbp at sourcefrog
test_source should avoid walking into tempdirs
135
            for d in dirs:
136
                if d.endswith('.tmp'):
137
                    dirs.remove(d)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
138
            for f in files:
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
139
                for extension in extensions:
140
                    if f.endswith(extension):
141
                        break
142
                else:
143
                    # Did not match the accepted extensions
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
144
                    continue
145
                yield osutils.pathjoin(root, f)
146
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
147
    def get_source_file_contents(self, extensions=None):
148
        for fname in self.get_source_files(extensions=extensions):
7045.4.10 by Jelmer Vernooij
Fix a couple more tests.
149
            with open(fname, 'r') as f:
150
                yield fname, f.read()
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
151
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
152
    def is_our_code(self, fname):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
153
        """True if it's a "real" part of breezy rather than external code"""
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
154
        if '/util/' in fname or '/plugins/' in fname:
155
            return False
156
        else:
157
            return True
158
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
159
    def is_copyright_exception(self, fname):
160
        """Certain files are allowed to be different"""
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
161
        if not self.is_our_code(fname):
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
162
            return True
163
        for exc in COPYRIGHT_EXCEPTIONS:
164
            if fname.endswith(exc):
165
                return True
166
        return False
167
168
    def is_license_exception(self, fname):
169
        """Certain files are allowed to be different"""
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
170
        if not self.is_our_code(fname):
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
171
            return True
172
        for exc in LICENSE_EXCEPTIONS:
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
173
            if fname.endswith(exc):
174
                return True
175
        return False
176
2102.3.1 by mbp at sourcefrog
test_source should avoid walking into tempdirs
177
    def test_tmpdir_not_in_source_files(self):
178
        """When scanning for source files, we don't descend test tempdirs"""
179
        for filename in self.get_source_files():
180
            if re.search(r'test....\.tmp', filename):
181
                self.fail("get_source_file() returned filename %r "
182
                          "from within a temporary directory"
183
                          % filename)
184
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
185
    def test_copyright(self):
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
186
        """Test that all .py and .pyx files have a valid copyright statement"""
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
187
        incorrect = []
188
2052.3.7 by John Arbash Meinel
Use positive lookahead to avoid extra newlines
189
        copyright_re = re.compile('#\\s*copyright.*(?=\n)', re.I)
6621.21.1 by Martin
Update bt.test_source copyright test to accept other copyright holders
190
        copyright_statement_re = re.compile(
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
191
            r'# Copyright \(C\) '  # Opening "# Copyright (C)"
6621.21.1 by Martin
Update bt.test_source copyright test to accept other copyright holders
192
            r'(\d+?)((, |-)\d+)*'  # followed by a series of dates
193
            r' [^ ]*')             # and then whoever.
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
194
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
195
        for fname, text in self.get_source_file_contents(
196
                extensions=('.py', '.pyx')):
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
197
            if self.is_copyright_exception(fname):
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
198
                continue
6621.21.1 by Martin
Update bt.test_source copyright test to accept other copyright holders
199
            match = copyright_statement_re.search(text)
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
200
            if not match:
201
                match = copyright_re.search(text)
202
                if match:
203
                    incorrect.append((fname, 'found: %s' % (match.group(),)))
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
204
                else:
205
                    incorrect.append((fname, 'no copyright line found\n'))
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
206
            else:
207
                if 'by Canonical' in match.group():
208
                    incorrect.append((fname,
7143.15.2 by Jelmer Vernooij
Run autopep8.
209
                                      'should not have: "by Canonical": %s'
210
                                      % (match.group(),)))
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
211
212
        if incorrect:
213
            help_text = ["Some files have missing or incorrect copyright"
214
                         " statements.",
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
215
                         "",
216
                         "Please either add them to the list of"
217
                         " COPYRIGHT_EXCEPTIONS in"
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
218
                         " breezy/tests/test_source.py",
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
219
                         # this is broken to prevent a false match
220
                         "or add '# Copyright (C)"
6621.21.1 by Martin
Update bt.test_source copyright test to accept other copyright holders
221
                         " 2007 Bazaar hackers' to these files:",
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
222
                         "",
7143.15.2 by Jelmer Vernooij
Run autopep8.
223
                         ]
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
224
            for fname, comment in incorrect:
225
                help_text.append(fname)
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
226
                help_text.append((' ' * 4) + comment)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
227
228
            self.fail('\n'.join(help_text))
229
230
    def test_gpl(self):
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
231
        """Test that all .py and .pyx files have a GPL disclaimer."""
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
232
        incorrect = []
233
234
        gpl_txt = """
235
# This program is free software; you can redistribute it and/or modify
236
# it under the terms of the GNU General Public License as published by
237
# the Free Software Foundation; either version 2 of the License, or
238
# (at your option) any later version.
239
#
240
# This program is distributed in the hope that it will be useful,
241
# but WITHOUT ANY WARRANTY; without even the implied warranty of
242
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
243
# GNU General Public License for more details.
244
#
245
# You should have received a copy of the GNU General Public License
246
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
247
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
248
"""
249
        gpl_re = re.compile(re.escape(gpl_txt), re.MULTILINE)
250
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
251
        for fname, text in self.get_source_file_contents(
252
                extensions=('.py', '.pyx')):
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
253
            if self.is_license_exception(fname):
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
254
                continue
255
            if not gpl_re.search(text):
256
                incorrect.append(fname)
257
258
        if incorrect:
259
            help_text = ['Some files have missing or incomplete GPL statement',
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
260
                         "",
261
                         "Please either add them to the list of"
262
                         " LICENSE_EXCEPTIONS in"
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
263
                         " breezy/tests/test_source.py",
2052.3.5 by John Arbash Meinel
Guide people to how to add files to the list of exceptions
264
                         "Or add the following text to the beginning:",
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
265
                         gpl_txt]
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
266
            for fname in incorrect:
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
267
                help_text.append((' ' * 4) + fname)
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
268
269
            self.fail('\n'.join(help_text))
2120.2.1 by John Arbash Meinel
Remove tabs from source files, and add a test to keep it that way.
270
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
271
    def _push_file(self, dict_, fname, line_no):
272
        if fname not in dict_:
273
            dict_[fname] = [line_no]
274
        else:
275
            dict_[fname].append(line_no)
276
277
    def _format_message(self, dict_, message):
6619.3.18 by Jelmer Vernooij
Run 2to3 idioms fixer.
278
        files = sorted(["%s: %s" % (f, ', '.join([str(i + 1) for i in lines]))
7143.15.2 by Jelmer Vernooij
Run autopep8.
279
                        for f, lines in dict_.items()])
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
280
        return message + '\n\n    %s' % ('\n    '.join(files))
281
3943.7.1 by Marius Kruger
* Change test_no_tabs to test_coding_style and let it check for trailing newlines too.
282
    def test_coding_style(self):
283
        """Check if bazaar code conforms to some coding style conventions.
284
5967.5.1 by Martin Pool
Don't print a message about long lines or trailing newlines.
285
        Generally we expect PEP8, but we do not generally strictly enforce
286
        this, and there are existing files that do not comply.  The 'pep8'
287
        tool, available separately, will check for more cases.
4210.5.1 by Marius Kruger
don't raise KnownFailure for all coding_style regressions,
288
5967.5.1 by Martin Pool
Don't print a message about long lines or trailing newlines.
289
        This test only enforces conditions that are globally true at the
290
        moment, and that should cause a patch to be rejected: spaces rather
291
        than tabs, unix newlines, and a newline at the end of the file.
3943.7.1 by Marius Kruger
* Change test_no_tabs to test_coding_style and let it check for trailing newlines too.
292
        """
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
293
        tabs = {}
294
        illegal_newlines = {}
3943.7.4 by Marius Kruger
now also check for 'no newline at end of files'
295
        no_newline_at_eof = []
4198.1.1 by John Arbash Meinel
Include pyrex files in our source testing for GPL and Copyright checks.
296
        for fname, text in self.get_source_file_contents(
297
                extensions=('.py', '.pyx')):
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
298
            if not self.is_our_code(fname):
2234.4.1 by Wouter van Heyst
(John Arbash Meinel) Fix selftest for installed bzr (#80330)
299
                continue
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
300
            lines = text.splitlines(True)
3943.7.4 by Marius Kruger
now also check for 'no newline at end of files'
301
            last_line_no = len(lines) - 1
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
302
            for line_no, line in enumerate(lines):
303
                if '\t' in line:
304
                    self._push_file(tabs, fname, line_no)
305
                if not line.endswith('\n') or line.endswith('\r\n'):
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
306
                    if line_no != last_line_no:  # not no_newline_at_eof
3943.7.4 by Marius Kruger
now also check for 'no newline at end of files'
307
                        self._push_file(illegal_newlines, fname, line_no)
308
            if not lines[-1].endswith('\n'):
309
                no_newline_at_eof.append(fname)
3943.7.1 by Marius Kruger
* Change test_no_tabs to test_coding_style and let it check for trailing newlines too.
310
        problems = []
311
        if tabs:
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
312
            problems.append(self._format_message(tabs,
7143.15.2 by Jelmer Vernooij
Run autopep8.
313
                                                 'Tab characters were found in the following source files.'
314
                                                 '\nThey should either be replaced by "\\t" or by spaces:'))
3943.7.2 by Marius Kruger
* also check for unix style newlines and note in HACKING that this is what we use.
315
        if illegal_newlines:
316
            problems.append(self._format_message(illegal_newlines,
7143.15.2 by Jelmer Vernooij
Run autopep8.
317
                                                 'Non-unix newlines were found in the following source files:'))
3943.7.4 by Marius Kruger
now also check for 'no newline at end of files'
318
        if no_newline_at_eof:
319
            no_newline_at_eof.sort()
320
            problems.append("The following source files doesn't have a "
7143.15.2 by Jelmer Vernooij
Run autopep8.
321
                            "newline at the end:"
322
                            '\n\n    %s'
323
                            % ('\n    '.join(no_newline_at_eof)))
3943.7.1 by Marius Kruger
* Change test_no_tabs to test_coding_style and let it check for trailing newlines too.
324
        if problems:
3943.7.4 by Marius Kruger
now also check for 'no newline at end of files'
325
            self.fail('\n\n'.join(problems))
3572.1.3 by Marius Kruger
* move test_coding_style into test_source
326
7167.1.2 by Jelmer Vernooij
Add test_flake8.
327
    def test_flake8(self):
7167.1.3 by Jelmer Vernooij
Use addCleanup.
328
        self.requireFeature(features.flake8)
329
        # Older versions of flake8 don't support the 'paths'
330
        # variable
331
        new_path = list(sys.path)
332
        new_path.insert(
333
            0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools'))
334
        self.overrideAttr(sys, 'path', new_path)
7296.1.4 by Jelmer Vernooij
Avoid using legacy API for flake8.
335
        from flake8.main.application import Application
336
        from flake8.formatting.base import BaseFormatter
337
        app = Application()
338
        app.config = u'setup.cfg'
339
        app.jobs = 1
340
341
        class Formatter(BaseFormatter):
342
343
            def __init__(self):
344
                self.errors = []
345
346
            def start(self):
347
                pass
348
349
            def stop(self):
350
                app.file_checker_manager.report()
351
352
            def handle(self, error):
353
                self.errors.append(error)
354
355
        app.formatter = Formatter()
356
        app.initialize([])
357
        app.run_checks()
358
        app.report()
359
        self.assertEqual(app.formatter.errors, [])
7167.1.2 by Jelmer Vernooij
Add test_flake8.
360
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
361
    def test_no_asserts(self):
362
        """bzr shouldn't use the 'assert' statement."""
363
        # assert causes too much variation between -O and not, and tends to
364
        # give bad errors to the user
365
        def search(x):
366
            # scan down through x for assert statements, report any problems
367
            # this is a bit cheesy; it may get some false positives?
368
            if x[0] == symbol.assert_stmt:
369
                return True
370
            elif x[0] == token.NAME:
371
                # can't search further down
372
                return False
373
            for sub in x[1:]:
374
                if sub and search(sub):
375
                    return True
376
            return False
377
        badfiles = []
4699.1.1 by Harald Meland
Make test_no_asserts quicker by doing a regexp check for the presence of any 'assert' word before doing any expensive AST stuff
378
        assert_re = re.compile(r'\bassert\b')
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
379
        for fname, text in self.get_source_file_contents():
380
            if not self.is_our_code(fname):
381
                continue
4699.1.1 by Harald Meland
Make test_no_asserts quicker by doing a regexp check for the presence of any 'assert' word before doing any expensive AST stuff
382
            if not assert_re.search(text):
383
                continue
7045.4.10 by Jelmer Vernooij
Fix a couple more tests.
384
            st = parser.suite(text)
385
            code = parser.st2tuple(st)
386
            if search(code):
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
387
                badfiles.append(fname)
388
        if badfiles:
3376.2.7 by Martin Pool
Treat assert statements in our code as a hard error
389
            self.fail(
3376.2.1 by Martin Pool
Add test_no_asserts and cleanup test_source
390
                "these files contain an assert statement and should not:\n%s"
391
                % '\n'.join(badfiles))
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
392
393
    def test_extension_exceptions(self):
394
        """Extension functions should propagate exceptions.
395
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
396
        Either they should return an object, have an 'except' clause, or
397
        have a "# cannot_raise" to indicate that we've audited them and
398
        defined them as not raising exceptions.
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
399
        """
400
        both_exc_and_no_exc = []
401
        missing_except = []
7038.1.5 by Martin
Fix test_source failure after removing magic comment
402
        common_classes = ('StaticTuple',)
5365.5.29 by John Arbash Meinel
Handle test_source and extensions. Also define an 'extern' protocol, to allow
403
        class_re = re.compile(r'^(cdef\s+)?(public\s+)?'
404
                              r'(api\s+)?class (\w+).*:', re.MULTILINE)
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
405
        except_re = re.compile(
406
            r'cdef\s+'        # start with cdef
407
            r'([\w *]*?)\s*'  # this is the return signature
408
            r'(\w+)\s*\('     # the function name
409
            r'[^)]*\)\s*'     # parameters
410
            r'(.*)\s*:'       # the except clause
411
            r'\s*(#\s*cannot[- _]raise)?')  # cannot raise comment
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
412
        for fname, text in self.get_source_file_contents(
413
                extensions=('.pyx',)):
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
414
            known_classes = {m[-1] for m in class_re.findall(text)}
7038.1.5 by Martin
Fix test_source failure after removing magic comment
415
            known_classes.update(common_classes)
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
416
            cdefs = except_re.findall(text)
417
            for sig, func, exc_clause, no_exc_comment in cdefs:
4932.1.2 by John Arbash Meinel
Clean up _simple_set.pyx, and handle 'nogil'.
418
                if sig.startswith('api '):
419
                    sig = sig[4:]
4634.117.8 by John Arbash Meinel
Use a class regex to find other signatures to exclude.
420
                if not sig or sig in known_classes:
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
421
                    sig = 'object'
4932.1.2 by John Arbash Meinel
Clean up _simple_set.pyx, and handle 'nogil'.
422
                if 'nogil' in exc_clause:
423
                    exc_clause = exc_clause.replace('nogil', '').strip()
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
424
                if exc_clause and no_exc_comment:
425
                    both_exc_and_no_exc.append((fname, func))
426
                if sig != 'object' and not (exc_clause or no_exc_comment):
427
                    missing_except.append((fname, func))
428
        error_msg = []
429
        if both_exc_and_no_exc:
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
430
            error_msg.append(
431
                'The following functions had "cannot raise" comments'
432
                ' but did have an except clause set:')
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
433
            for fname, func in both_exc_and_no_exc:
434
                error_msg.append('%s:%s' % (fname, func))
435
            error_msg.extend(('', ''))
436
        if missing_except:
5967.5.2 by Martin Pool
Make test_source actually comply with pep8 itself
437
            error_msg.append(
438
                'The following functions have fixed return types,'
439
                ' but no except clause.')
440
            error_msg.append(
441
                'Either add an except or append "# cannot_raise".')
4634.117.5 by John Arbash Meinel
Add a test_source test, to ensure that all funcs have either an except
442
            for fname, func in missing_except:
443
                error_msg.append('%s:%s' % (fname, func))
444
            error_msg.extend(('', ''))
445
        if error_msg:
446
            self.fail('\n'.join(error_msg))