~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_source.py

  • Committer: Martin Pool
  • Date: 2009-07-02 03:48:25 UTC
  • mto: This revision was merged to the branch mainline in revision 4502.
  • Revision ID: mbp@sourcefrog.net-20090702034825-2330z69r93a701ws
iter(i) returns i so we don't need a check

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
40
42
 
41
43
# Files which are listed here will be skipped when testing for Copyright (or
42
44
# GPL) statements.
43
 
COPYRIGHT_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py',
44
 
    'bzrlib/doc_generate/sphinx_conf.py']
 
45
COPYRIGHT_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py']
45
46
 
46
 
LICENSE_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py',
47
 
    'bzrlib/doc_generate/sphinx_conf.py']
 
47
LICENSE_EXCEPTIONS = ['bzrlib/lsprof.py', 'bzrlib/_bencode_py.py']
48
48
# Technically, 'bzrlib/lsprof.py' should be 'bzrlib/util/lsprof.py',
49
49
# (we do not check bzrlib/util/, since that is code bundled from elsewhere)
50
50
# but for compatibility with previous releases, we don't want to move it.
51
 
#
52
 
# sphinx_conf is semi-autogenerated.
53
51
 
54
52
 
55
53
class TestSourceHelper(TestCase):
359
357
                    return True
360
358
            return False
361
359
        badfiles = []
362
 
        assert_re = re.compile(r'\bassert\b')
363
360
        for fname, text in self.get_source_file_contents():
364
361
            if not self.is_our_code(fname):
365
362
                continue
366
 
            if not assert_re.search(text):
367
 
                continue
368
 
            ast = parser.ast2tuple(parser.suite(text))
 
363
            ast = parser.ast2tuple(parser.suite(''.join(text)))
369
364
            if search(ast):
370
365
                badfiles.append(fname)
371
366
        if badfiles:
372
367
            self.fail(
373
368
                "these files contain an assert statement and should not:\n%s"
374
369
                % '\n'.join(badfiles))
375
 
 
376
 
    def test_extension_exceptions(self):
377
 
        """Extension functions should propagate exceptions.
378
 
 
379
 
        Either they should return an object, have an 'except' clause, or have a
380
 
        "# cannot_raise" to indicate that we've audited them and defined them as not
381
 
        raising exceptions.
382
 
        """
383
 
        both_exc_and_no_exc = []
384
 
        missing_except = []
385
 
        class_re = re.compile(r'^(cdef\s+)?(public\s+)?(api\s+)?class (\w+).*:',
386
 
                              re.MULTILINE)
387
 
        except_re = re.compile(r'cdef\s+' # start with cdef
388
 
                               r'([\w *]*?)\s*' # this is the return signature
389
 
                               r'(\w+)\s*\(' # the function name
390
 
                               r'[^)]*\)\s*' # parameters
391
 
                               r'(.*)\s*:' # the except clause
392
 
                               r'\s*(#\s*cannot[- _]raise)?' # cannot raise comment
393
 
                              )
394
 
        for fname, text in self.get_source_file_contents(
395
 
                extensions=('.pyx',)):
396
 
            known_classes = set([m[-1] for m in class_re.findall(text)])
397
 
            cdefs = except_re.findall(text)
398
 
            for sig, func, exc_clause, no_exc_comment in cdefs:
399
 
                if sig.startswith('api '):
400
 
                    sig = sig[4:]
401
 
                if not sig or sig in known_classes:
402
 
                    sig = 'object'
403
 
                if 'nogil' in exc_clause:
404
 
                    exc_clause = exc_clause.replace('nogil', '').strip()
405
 
                if exc_clause and no_exc_comment:
406
 
                    both_exc_and_no_exc.append((fname, func))
407
 
                if sig != 'object' and not (exc_clause or no_exc_comment):
408
 
                    missing_except.append((fname, func))
409
 
        error_msg = []
410
 
        if both_exc_and_no_exc:
411
 
            error_msg.append('The following functions had "cannot raise" comments'
412
 
                             ' but did have an except clause set:')
413
 
            for fname, func in both_exc_and_no_exc:
414
 
                error_msg.append('%s:%s' % (fname, func))
415
 
            error_msg.extend(('', ''))
416
 
        if missing_except:
417
 
            error_msg.append('The following functions have fixed return types,'
418
 
                             ' but no except clause.')
419
 
            error_msg.append('Either add an except or append "# cannot_raise".')
420
 
            for fname, func in missing_except:
421
 
                error_msg.append('%s:%s' % (fname, func))
422
 
            error_msg.extend(('', ''))
423
 
        if error_msg:
424
 
            self.fail('\n'.join(error_msg))