1
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
41
44
# Files which are listed here will be skipped when testing for Copyright (or
43
COPYRIGHT_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py',
44
'bzrlib/doc_generate/sphinx_conf.py']
46
COPYRIGHT_EXCEPTIONS = ['bzrlib/lsprof.py']
46
LICENSE_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py',
47
'bzrlib/doc_generate/sphinx_conf.py']
48
LICENSE_EXCEPTIONS = ['bzrlib/lsprof.py']
48
49
# Technically, 'bzrlib/lsprof.py' should be 'bzrlib/util/lsprof.py',
49
50
# (we do not check bzrlib/util/, since that is code bundled from elsewhere)
50
51
# but for compatibility with previous releases, we don't want to move it.
52
# sphinx_conf is semi-autogenerated.
55
54
class TestSourceHelper(TestCase):
285
284
def test_coding_style(self):
286
285
"""Check if bazaar code conforms to some coding style conventions.
288
Currently we assert that the following is not present:
287
Currently we check for:
289
288
* any tab characters
289
* trailing white space
290
290
* non-unix newlines
291
291
* no newline at end of files
293
Print how many files have
294
* trailing white space
295
292
* lines longer than 79 chars
293
(only print how many files and lines are in violation)
323
321
'Tab characters were found in the following source files.'
324
322
'\nThey should either be replaced by "\\t" or by spaces:'))
326
print ("There are %i lines with trailing white space in %i files."
327
% (sum([len(lines) for f, lines in trailing_ws.items()]),
324
problems.append(self._format_message(trailing_ws,
325
'Trailing white space was found in the following source files:'
329
327
if illegal_newlines:
330
328
problems.append(self._format_message(illegal_newlines,
331
329
'Non-unix newlines were found in the following source files:'))
370
369
"these files contain an assert statement and should not:\n%s"
371
370
% '\n'.join(badfiles))
373
def test_extension_exceptions(self):
374
"""Extension functions should propagate exceptions.
376
Either they should return an object, have an 'except' clause, or have a
377
"# cannot_raise" to indicate that we've audited them and defined them as not
380
both_exc_and_no_exc = []
382
class_re = re.compile(r'^(cdef\s+)?class (\w+).*:', re.MULTILINE)
383
except_re = re.compile(r'cdef\s*' # start with cdef
384
r'([\w *]*?)\s*' # this is the return signature
385
r'(\w+)\s*\(' # the function name
386
r'[^)]*\)\s*' # parameters
387
r'(.*)\s*:' # the except clause
388
r'\s*(#\s*cannot[- _]raise)?' # cannot raise comment
390
for fname, text in self.get_source_file_contents(
391
extensions=('.pyx',)):
392
known_classes = set([m[1] for m in class_re.findall(text)])
393
cdefs = except_re.findall(text)
394
for sig, func, exc_clause, no_exc_comment in cdefs:
395
if not sig or sig in known_classes:
397
if exc_clause and no_exc_comment:
398
both_exc_and_no_exc.append((fname, func))
399
if sig != 'object' and not (exc_clause or no_exc_comment):
400
missing_except.append((fname, func))
402
if both_exc_and_no_exc:
403
error_msg.append('The following functions had "cannot raise" comments'
404
' but did have an except clause set:')
405
for fname, func in both_exc_and_no_exc:
406
error_msg.append('%s:%s' % (fname, func))
407
error_msg.extend(('', ''))
409
error_msg.append('The following functions have fixed return types,'
410
' but no except clause.')
411
error_msg.append('Either add an except or append "# cannot_raise".')
412
for fname, func in missing_except:
413
error_msg.append('%s:%s' % (fname, func))
414
error_msg.extend(('', ''))
416
self.fail('\n'.join(error_msg))