~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_source.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-12-19 20:08:18 UTC
  • mfrom: (3572.1.11 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20081219200818-g19t5zbtkj52bwqp
(Marius Kruger) Add a source test that prevents adding new trailing
        whitespace.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
import os
26
26
import parser
27
27
import re
 
28
from cStringIO import StringIO
28
29
import symbol
29
30
import sys
30
31
import token
31
32
 
32
33
#import bzrlib specific imports here
33
34
from bzrlib import (
 
35
    diff,
34
36
    osutils,
 
37
    patiencediff,
 
38
    textfile,
35
39
    )
36
40
import bzrlib.branch
37
41
from bzrlib.tests import (
39
43
    TestCase,
40
44
    TestSkipped,
41
45
    )
 
46
from bzrlib.workingtree import WorkingTree
42
47
 
43
48
 
44
49
# Files which are listed here will be skipped when testing for Copyright (or
51
56
# but for compatibility with previous releases, we don't want to move it.
52
57
 
53
58
 
 
59
def check_coding_style(old_filename, oldlines, new_filename, newlines, to_file,
 
60
                  allow_binary=False, sequence_matcher=None,
 
61
                  path_encoding='utf8'):
 
62
    """text_differ to be passed to diff.DiffText, which checks code style """
 
63
    if allow_binary is False:
 
64
        textfile.check_text_lines(oldlines)
 
65
        textfile.check_text_lines(newlines)
 
66
 
 
67
    if sequence_matcher is None:
 
68
        sequence_matcher = patiencediff.PatienceSequenceMatcher
 
69
 
 
70
    started = [False] #trick to access parent scoped variable
 
71
    def start_if_needed():
 
72
        if not started[0]:
 
73
            to_file.write('+++ %s\n' % new_filename)
 
74
            started[0] = True
 
75
 
 
76
    def check_newlines(j1, j2):
 
77
        for i, line in enumerate(newlines[j1:j2]):
 
78
            bad_ws_match = re.match(r'^(([\t]*)(.*?)([\t ]*))(\r?\n)?$', line)
 
79
            if bad_ws_match:
 
80
                line_content = bad_ws_match.group(1)
 
81
                has_leading_tabs = bool(bad_ws_match.group(2))
 
82
                has_trailing_whitespace = bool(bad_ws_match.group(4))
 
83
                if has_leading_tabs:
 
84
                    start_if_needed()
 
85
                    to_file.write('line %i has leading tabs: "%s"\n'% (
 
86
                        i+1+j1, line_content))
 
87
                if has_trailing_whitespace:
 
88
                    start_if_needed()
 
89
                    to_file.write('line %i has trailing whitespace: "%s"\n'% (
 
90
                        i+1+j1, line_content))
 
91
                if len(line_content) > 79:
 
92
                    print (
 
93
                        '\nFile %s\nline %i is longer than 79 characters:'
 
94
                        '\n"%s"'% (new_filename, i+1+j1, line_content))
 
95
 
 
96
    for group in sequence_matcher(None, oldlines, newlines
 
97
            ).get_grouped_opcodes(0):
 
98
        for tag, i1, i2, j1, j2 in group:
 
99
            if tag == 'replace' or tag == 'insert':
 
100
                check_newlines(j1, j2)
 
101
 
 
102
    if len(newlines) == j2 and not newlines[j2-1].endswith('\n'):
 
103
        start_if_needed()
 
104
        to_file.write("\\ No newline at end of file\n")
 
105
 
 
106
 
54
107
class TestSourceHelper(TestCase):
55
108
 
56
109
    def source_file_name(self, package):
279
332
              '\n\n    %s'
280
333
              % ('\n    '.join(incorrect)))
281
334
 
 
335
    def test_coding_style(self):
 
336
        """ Check if bazaar code conforms to some coding style conventions.
 
337
 
 
338
        Currently we check all .py files for:
 
339
         * new trailing white space
 
340
         * new leading tabs
 
341
         * new long lines (give warning only)
 
342
         * no newline at end of files
 
343
        """
 
344
        bzr_dir = osutils.dirname(self.get_bzrlib_dir())
 
345
        try:
 
346
            wt = WorkingTree.open(bzr_dir)
 
347
        except:
 
348
            raise TestSkipped(
 
349
                'Could not open bazaar working tree %s'
 
350
                % bzr_dir)
 
351
        diff_output = StringIO()
 
352
        wt.lock_read()
 
353
        try:
 
354
            new_tree = wt
 
355
            old_tree = new_tree.basis_tree()
 
356
 
 
357
            old_tree.lock_read()
 
358
            new_tree.lock_read()
 
359
            try:
 
360
                iterator = new_tree.iter_changes(old_tree)
 
361
                for (file_id, paths, changed_content, versioned, parent,
 
362
                    name, kind, executable) in iterator:
 
363
                    if (changed_content and paths[1].endswith('.py')):
 
364
                        if kind == ('file', 'file'):
 
365
                            diff_text = diff.DiffText(old_tree, new_tree,
 
366
                                to_file=diff_output,
 
367
                                text_differ=check_coding_style)
 
368
                            diff_text.diff(file_id, paths[0], paths[1],
 
369
                                kind[0], kind[1])
 
370
                        else:
 
371
                            check_coding_style(name[0], (), name[1],
 
372
                                new_tree.get_file(file_id).readlines(),
 
373
                                diff_output)
 
374
            finally:
 
375
                old_tree.unlock()
 
376
                new_tree.unlock()
 
377
        finally:
 
378
            wt.unlock()
 
379
        if len(diff_output.getvalue()) > 0:
 
380
            self.fail("Unacceptable coding style:\n" + diff_output.getvalue())
 
381
 
282
382
    def test_no_asserts(self):
283
383
        """bzr shouldn't use the 'assert' statement."""
284
384
        # assert causes too much variation between -O and not, and tends to