/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_source.py

  • Committer: Jelmer Vernooij
  • Date: 2009-03-22 00:24:37 UTC
  • mfrom: (4180 +trunk)
  • mto: (3920.2.35 dpush)
  • mto: This revision was merged to the branch mainline in revision 4281.
  • Revision ID: jelmer@samba.org-20090322002437-0vlyqnz29isqeozo
Merge bzr.dev.

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
29
28
import symbol
30
29
import sys
31
30
import token
32
31
 
33
32
#import bzrlib specific imports here
34
33
from bzrlib import (
35
 
    diff,
36
34
    osutils,
37
 
    patiencediff,
38
 
    textfile,
39
35
    )
40
36
import bzrlib.branch
41
37
from bzrlib.tests import (
43
39
    TestCase,
44
40
    TestSkipped,
45
41
    )
46
 
from bzrlib.workingtree import WorkingTree
47
42
 
48
43
 
49
44
# Files which are listed here will be skipped when testing for Copyright (or
56
51
# but for compatibility with previous releases, we don't want to move it.
57
52
 
58
53
 
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
 
 
107
54
class TestSourceHelper(TestCase):
108
55
 
109
56
    def source_file_name(self, package):
135
82
        # do not even think of increasing this number. If you think you need to
136
83
        # increase it, then you almost certainly are doing something wrong as
137
84
        # the relationship from working_tree to branch is one way.
138
 
        # Note that this is an exact equality so that when the number drops, 
 
85
        # Note that this is an exact equality so that when the number drops,
139
86
        #it is not given a buffer but rather has this test updated immediately.
140
87
        self.assertEqual(0, occurences)
141
88
 
165
112
 
166
113
    def get_source_files(self):
167
114
        """Yield all source files for bzr and bzrlib
168
 
        
 
115
 
169
116
        :param our_files_only: If true, exclude files from included libraries
170
117
            or plugins.
171
118
        """
316
263
 
317
264
            self.fail('\n'.join(help_text))
318
265
 
319
 
    def test_no_tabs(self):
320
 
        """bzrlib source files should not contain any tab characters."""
321
 
        incorrect = []
322
 
 
323
 
        for fname, text in self.get_source_file_contents():
324
 
            if not self.is_our_code(fname):
325
 
                continue
326
 
            if '\t' in text:
327
 
                incorrect.append(fname)
328
 
 
329
 
        if incorrect:
330
 
            self.fail('Tab characters were found in the following source files.'
331
 
              '\nThey should either be replaced by "\\t" or by spaces:'
332
 
              '\n\n    %s'
333
 
              % ('\n    '.join(incorrect)))
 
266
    def _push_file(self, dict_, fname, line_no):
 
267
        if fname not in dict_:
 
268
            dict_[fname] = [line_no]
 
269
        else:
 
270
            dict_[fname].append(line_no)
 
271
 
 
272
    def _format_message(self, dict_, message):
 
273
        files = ["%s: %s" % (f, ', '.join([str(i+1) for i in lines]))
 
274
                for f, lines in dict_.items()]
 
275
        files.sort()
 
276
        return message + '\n\n    %s' % ('\n    '.join(files))
334
277
 
335
278
    def test_coding_style(self):
336
 
        """ Check if bazaar code conforms to some coding style conventions.
 
279
        """Check if bazaar code conforms to some coding style conventions.
337
280
 
338
 
        Currently we check all .py files for:
339
 
         * new trailing white space
340
 
         * new leading tabs
341
 
         * new long lines (give warning only)
 
281
        Currently we check for:
 
282
         * any tab characters
 
283
         * trailing white space
 
284
         * non-unix newlines
342
285
         * no newline at end of files
 
286
         * lines longer than 79 chars
 
287
           (only print how many files and lines are in violation)
343
288
        """
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())
 
289
        tabs = {}
 
290
        trailing_ws = {}
 
291
        illegal_newlines = {}
 
292
        long_lines = {}
 
293
        no_newline_at_eof = []
 
294
        for fname, text in self.get_source_file_contents():
 
295
            if not self.is_our_code(fname):
 
296
                continue
 
297
            lines = text.splitlines(True)
 
298
            last_line_no = len(lines) - 1
 
299
            for line_no, line in enumerate(lines):
 
300
                if '\t' in line:
 
301
                    self._push_file(tabs, fname, line_no)
 
302
                if not line.endswith('\n') or line.endswith('\r\n'):
 
303
                    if line_no != last_line_no: # not no_newline_at_eof
 
304
                        self._push_file(illegal_newlines, fname, line_no)
 
305
                if line.endswith(' \n'):
 
306
                    self._push_file(trailing_ws, fname, line_no)
 
307
                if len(line) > 80:
 
308
                    self._push_file(long_lines, fname, line_no)
 
309
            if not lines[-1].endswith('\n'):
 
310
                no_newline_at_eof.append(fname)
 
311
        problems = []
 
312
        if tabs:
 
313
            problems.append(self._format_message(tabs,
 
314
                'Tab characters were found in the following source files.'
 
315
                '\nThey should either be replaced by "\\t" or by spaces:'))
 
316
        if trailing_ws:
 
317
            problems.append(self._format_message(trailing_ws,
 
318
                'Trailing white space was found in the following source files:'
 
319
                ))
 
320
        if illegal_newlines:
 
321
            problems.append(self._format_message(illegal_newlines,
 
322
                'Non-unix newlines were found in the following source files:'))
 
323
        if long_lines:
 
324
            print ("There are %i lines longer than 79 characters in %i files."
 
325
                % (sum([len(lines) for f, lines in long_lines.items()]),
 
326
                    len(long_lines)))
 
327
        if no_newline_at_eof:
 
328
            no_newline_at_eof.sort()
 
329
            problems.append("The following source files doesn't have a "
 
330
                "newline at the end:"
 
331
               '\n\n    %s'
 
332
               % ('\n    '.join(no_newline_at_eof)))
 
333
        if problems:
 
334
            raise KnownFailure("test_coding_style has failed")
 
335
            self.fail('\n\n'.join(problems))
381
336
 
382
337
    def test_no_asserts(self):
383
338
        """bzr shouldn't use the 'assert' statement."""