~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_source.py

  • Committer: Marius Kruger
  • Date: 2008-12-06 12:45:12 UTC
  • mto: This revision was merged to the branch mainline in revision 3915.
  • Revision ID: amanic@gmail.com-20081206124512-w1xwgt7s1o1ea0qv
* move test_coding_style into test_source
* rename internal_diff to check_coding_style

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