~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_source.py

  • Committer: Ian Clatworthy
  • Date: 2009-04-03 02:29:30 UTC
  • mto: This revision was merged to the branch mainline in revision 4259.
  • Revision ID: ian.clatworthy@canonical.com-20090403022930-epud0dn5421fp0a0
chk_map code from brisbane-core

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
#            and others
2
4
#
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
33
35
    )
34
36
import bzrlib.branch
35
37
from bzrlib.tests import (
 
38
    KnownFailure,
36
39
    TestCase,
37
40
    TestSkipped,
38
41
    )
40
43
 
41
44
# Files which are listed here will be skipped when testing for Copyright (or
42
45
# GPL) statements.
43
 
COPYRIGHT_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py',
44
 
    'bzrlib/doc_generate/sphinx_conf.py']
 
46
COPYRIGHT_EXCEPTIONS = ['bzrlib/lsprof.py']
45
47
 
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.
51
 
#
52
 
# sphinx_conf is semi-autogenerated.
53
52
 
54
53
 
55
54
class TestSourceHelper(TestCase):
285
284
    def test_coding_style(self):
286
285
        """Check if bazaar code conforms to some coding style conventions.
287
286
 
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
292
 
 
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)
296
294
        """
297
295
        tabs = {}
298
296
        trailing_ws = {}
323
321
                'Tab characters were found in the following source files.'
324
322
                '\nThey should either be replaced by "\\t" or by spaces:'))
325
323
        if trailing_ws:
326
 
            print ("There are %i lines with trailing white space in %i files."
327
 
                % (sum([len(lines) for f, lines in trailing_ws.items()]),
328
 
                    len(trailing_ws)))
 
324
            problems.append(self._format_message(trailing_ws,
 
325
                'Trailing white space was found in the following source files:'
 
326
                ))
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:'))
340
338
               '\n\n    %s'
341
339
               % ('\n    '.join(no_newline_at_eof)))
342
340
        if problems:
 
341
            raise KnownFailure("test_coding_style has failed")
343
342
            self.fail('\n\n'.join(problems))
344
343
 
345
344
    def test_no_asserts(self):
369
368
            self.fail(
370
369
                "these files contain an assert statement and should not:\n%s"
371
370
                % '\n'.join(badfiles))
372
 
 
373
 
    def test_extension_exceptions(self):
374
 
        """Extension functions should propagate exceptions.
375
 
 
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
378
 
        raising exceptions.
379
 
        """
380
 
        both_exc_and_no_exc = []
381
 
        missing_except = []
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
389
 
                              )
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:
396
 
                    sig = 'object'
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))
401
 
        error_msg = []
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(('', ''))
408
 
        if missing_except:
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(('', ''))
415
 
        if error_msg:
416
 
            self.fail('\n'.join(error_msg))