Exemple #1
0
 def test_lint_one_empty_lint(self):
     linter1 = functools.partial(
         linters.lint_command, 'l1', 'linter1', ['-f'],
         '^Line (?P<line>{lines}): (?P<message>.*)$')
     linter2 = functools.partial(
         linters.lint_command, 'l2', 'linter2', [],
         '^ line (?P<line>{lines}): (?P<message>.*)$')
     config = {'extensions': {'.txt': [linter1, linter2]}}
     outputs = [b'', os.linesep.join([' line 4: 4']).encode('utf-8')]
     with mock.patch('subprocess.check_output',
                     side_effect=outputs) as check_output, \
             mock.patch('os.path.getmtime', side_effect=[1, 0, 1, 0]):
         filename = 'foo.txt'
         self.assertEqual(
             {
                 filename: {
                     'comments': [
                         {
                             'line': 4,
                             'message': '4'
                         },
                     ],
                 },
             }, linters.lint(filename, lines=[4, 5], config=config))
         expected_calls = [
             mock.call(['linter1', '-f', 'foo.txt'],
                       stderr=subprocess.STDOUT),
             mock.call(['linter2', 'foo.txt'], stderr=subprocess.STDOUT)
         ]
         self.assertEqual(expected_calls, check_output.call_args_list)
Exemple #2
0
 def test_lint_one_empty_lint(self):
     linter1 = functools.partial(
         linters.lint_command, 'l1', 'linter1', ['-f'],
         '^Line (?P<line>{lines}): (?P<message>.*)$')
     linter2 = functools.partial(
         linters.lint_command, 'l2', 'linter2', [],
         '^ line (?P<line>{lines}): (?P<message>.*)$')
     config = {'.txt': [linter1, linter2]}
     outputs = [b'', os.linesep.join([' line 4: 4']).encode('utf-8')]
     with mock.patch('subprocess.check_output',
                     side_effect=outputs) as check_output, \
             mock.patch('os.path.getmtime', side_effect=[1, 0, 1, 0]):
         filename = 'foo.txt'
         self.assertEqual({
             filename: {
                 'comments': [
                     {
                         'line': 4,
                         'message': '4'
                     },
                 ],
             },
         }, linters.lint(filename, lines=[4, 5], config=config))
         expected_calls = [
             mock.call(
                 ['linter1', '-f', 'foo.txt'], stderr=subprocess.STDOUT),
             mock.call(['linter2', 'foo.txt'], stderr=subprocess.STDOUT)
         ]
         self.assertEqual(expected_calls, check_output.call_args_list)
 def test_lint_all_empty_lint(self):
     linter1 = functools.partial(
         linters.lint_command, 'l1', 'linter1', ['-f'], '^Line {lines}:')
     linter2 = functools.partial(
         linters.lint_command, 'l2', 'linter2', [], '^ line {lines}:')
     config = {
         '.txt': [linter1, linter2]
     }
     outputs = [b'', b'']
     with mock.patch('subprocess.check_output',
                     side_effect=outputs) as check_output, \
             mock.patch('os.path.getmtime', side_effect=[1, 0, 1, 0]):
         filename = 'foo.txt'
         self.assertEqual(
             {
                 filename: {
                     'comments': []
                 }
             },
             linters.lint(filename, lines=[4, 5], config=config))
         expected_calls = [
             mock.call(['linter1', '-f', 'foo.txt'],
                       stderr=subprocess.STDOUT),
             mock.call(['linter2', 'foo.txt'], stderr=subprocess.STDOUT)]
         self.assertEqual(expected_calls, check_output.call_args_list)
Exemple #4
0
 def test_lint_two_missing_programs(self):
     linter1 = functools.partial(linters.missing_requirements_command,
                                 ['p1', 'p2'], 'Install p1 and p2')
     config = {'.txt': [linter1, linter1]}
     output = linters.lint('foo.txt', lines=[4, 5], config=config)
     self.assertEqual(2, len(output['foo.txt']['skipped']))
     output['foo.txt']['skipped'] = []
     self.assertEqual({'foo.txt': {'skipped': []}}, output)
Exemple #5
0
 def test_lint_two_missing_programs(self):
     linter1 = functools.partial(linters.missing_requirements_command, 'l1',
                                 ['p1', 'p2'])
     config = {'extensions': {'.txt': [linter1, linter1]}}
     output = linters.lint('foo.txt', lines=[4, 5], config=config)
     self.assertEqual(2, len(output['foo.txt']['skipped']))
     output['foo.txt']['skipped'] = []
     self.assertEqual({'foo.txt': {'skipped': []}}, output)
Exemple #6
0
 def test_lint_output_is_sorted(self):
     linter1 = functools.partial(
         linters.lint_command, 'l1', 'linter1', ['-f'],
         '^Line (?P<line>{lines}): (?P<message>.*)$')
     linter2 = functools.partial(
         linters.lint_command, 'l2', 'linter2', [],
         '^ line (?P<line>{lines}): (?P<message>.*)$')
     linter3 = functools.partial(linters.lint_command, 'l3', 'linter3', [],
                                 '^(?P<message>.*)$')
     linter4 = functools.partial(
         linters.lint_command, 'l4', 'linter4', [],
         r'^(?P<line>{lines}):(?P<column>\d+): (?P<message>.*)$')
     config = {'extensions': {'.txt': [linter1, linter2, linter3, linter4]}}
     outputs = [
         os.linesep.join(['Line 5: 5', 'Line 1: 1']).encode('utf-8'),
         os.linesep.join([' line 4: 4']).encode('utf-8'),
         os.linesep.join(['message']).encode('utf-8'),
         os.linesep.join(['4:10: 4.a', '4:1: 4.b']).encode('utf-8'),
     ]
     with mock.patch('subprocess.check_output', side_effect=outputs), \
             mock.patch('os.path.getmtime', side_effect=[1, 0] * 4):
         filename = 'foo.txt'
         self.assertEqual(
             {
                 filename: {
                     'comments': [
                         {
                             'message': 'message',
                         },
                         {
                             'line': 1,
                             'message': '1',
                         },
                         {
                             'line': 4,
                             'message': '4',
                         },
                         {
                             'line': 4,
                             'column': 1,
                             'message': '4.b',
                         },
                         {
                             'line': 4,
                             'column': 10,
                             'message': '4.a',
                         },
                         {
                             'line': 5,
                             'message': '5',
                         },
                     ],
                 },
             }, linters.lint(filename, lines=None, config=config))
Exemple #7
0
 def test_lint_output_is_sorted(self):
     linter1 = functools.partial(
         linters.lint_command, 'l1', 'linter1', ['-f'],
         '^Line (?P<line>{lines}): (?P<message>.*)$')
     linter2 = functools.partial(
         linters.lint_command, 'l2', 'linter2', [],
         '^ line (?P<line>{lines}): (?P<message>.*)$')
     linter3 = functools.partial(linters.lint_command, 'l3', 'linter3', [],
                                 '^(?P<message>.*)$')
     linter4 = functools.partial(
         linters.lint_command, 'l4', 'linter4', [],
         r'^(?P<line>{lines}):(?P<column>\d+): (?P<message>.*)$')
     config = {'.txt': [linter1, linter2, linter3, linter4]}
     outputs = [
         os.linesep.join(['Line 5: 5', 'Line 1: 1']).encode('utf-8'),
         os.linesep.join([' line 4: 4']).encode('utf-8'),
         os.linesep.join(['message']).encode('utf-8'),
         os.linesep.join(['4:10: 4.a', '4:1: 4.b']).encode('utf-8'),
     ]
     with mock.patch('subprocess.check_output', side_effect=outputs), \
             mock.patch('os.path.getmtime', side_effect=[1, 0] * 4):
         filename = 'foo.txt'
         self.assertEqual({
             filename: {
                 'comments': [
                     {
                         'message': 'message',
                     },
                     {
                         'line': 1,
                         'message': '1',
                     },
                     {
                         'line': 4,
                         'message': '4',
                     },
                     {
                         'line': 4,
                         'column': 1,
                         'message': '4.b',
                     },
                     {
                         'line': 4,
                         'column': 10,
                         'message': '4.a',
                     },
                     {
                         'line': 5,
                         'message': '5',
                     },
                 ],
             },
         }, linters.lint(filename, lines=None, config=config))
 def test_lint_extension_not_defined(self):
     config = {}
     output = linters.lint('foo.txt', lines=[4, 5], config=config)
     self.assertEqual(1, len(output['foo.txt']['skipped']))
     output['foo.txt']['skipped'] = []
     self.assertEqual(
         {
             'foo.txt': {
                 'skipped': []
             }
         },
         output)
Exemple #9
0
def process_file(vcs, commit, force, gitlint_config, file_data):
    """Lint the file

    Returns:
      The results from the linter.
    """
    filename, extra_data = file_data

    if force:
        modified_lines = None
    else:
        modified_lines = vcs.modified_lines(
            filename, extra_data, commit=commit)
    result = linters.lint(filename, modified_lines, gitlint_config)
    result = result[filename]

    return filename, result
Exemple #10
0
def process_file(vcs, commit, force, linter_config, fixer_config, fix, fix_all, file_data):
    """Lint and optionally fix the file.

    Returns:
      The results from the linter.
    """
    filename, extra_data = file_data

    if fix:
        fixers.fix(filename, fixer_config, get_vcs_modified_lines(vcs, force, filename, extra_data, commit))
    elif fix_all:
        fixers.fix(filename, fixer_config)
    
    result = linters.lint(filename, get_vcs_modified_lines(vcs, force, filename, extra_data, commit), linter_config)
    result = result[filename]

    return filename, result
Exemple #11
0
 def test_lint_all_empty_lint(self):
     linter1 = functools.partial(linters.lint_command, 'l1', 'linter1',
                                 ['-f'], '^Line {lines}:')
     linter2 = functools.partial(linters.lint_command, 'l2', 'linter2', [],
                                 '^ line {lines}:')
     config = {'extensions': {'.txt': [linter1, linter2]}}
     outputs = [b'', b'']
     with mock.patch('subprocess.check_output',
                     side_effect=outputs) as check_output, \
             mock.patch('os.path.getmtime', side_effect=[1, 0, 1, 0]):
         filename = 'foo.txt'
         self.assertEqual({filename: {
             'comments': []
         }}, linters.lint(filename, lines=[4, 5], config=config))
         expected_calls = [
             mock.call(['linter1', '-f', 'foo.txt'],
                       stderr=subprocess.STDOUT),
             mock.call(['linter2', 'foo.txt'], stderr=subprocess.STDOUT)
         ]
         self.assertEqual(expected_calls, check_output.call_args_list)
Exemple #12
0
def main(argv, stdout=sys.stdout, stderr=sys.stderr):
    """Main gitlint routine. To be called from scripts."""
    # Wrap sys stdout for python 2, so print can understand unicode.
    linesep = os.linesep
    if sys.version_info[0] < 3:
        if stdout == sys.stdout:
            stdout = codecs.getwriter("utf-8")(stdout)
        if stderr == sys.stderr:
            stderr = codecs.getwriter("utf-8")(stderr)
        linesep = unicode(os.linesep)

    arguments = docopt.docopt(__doc__,
                              argv=argv[1:],
                              version='git-lint v%s' % __VERSION__)

    json_output = arguments['--json']

    vcs, repository_root = get_vcs_root()

    if vcs is None:
        stderr.write('fatal: Not a git repository' + os.linesep)
        return 128

    commit = None
    if arguments['--last-commit']:
        commit = vcs.last_commit()

    if arguments['FILENAME']:
        invalid_filenames = find_invalid_filenames(arguments['FILENAME'],
                                                   repository_root)
        if invalid_filenames:
            invalid_filenames.append(('', ''))
            stderr.write(
                os.linesep.join(invalid[1] for invalid in invalid_filenames))
            return 2

        changed_files = vcs.modified_files(repository_root,
                                           tracked_only=arguments['--tracked'],
                                           commit=commit)
        modified_files = {}
        for filename in arguments['FILENAME']:
            normalized_filename = os.path.abspath(filename)
            modified_files[normalized_filename] = changed_files.get(
                normalized_filename)
    else:
        modified_files = vcs.modified_files(repository_root,
                                            tracked_only=arguments['--tracked'],
                                            commit=commit)

    linter_not_found = False
    files_with_problems = 0
    gitlint_config = get_config(repository_root)
    json_result = {}

    error = termcolor.colored('ERROR', 'red', attrs=('bold',))
    skipped = termcolor.colored('SKIPPED', 'yellow', attrs=('bold',))

    for filename in sorted(modified_files.keys()):
        rel_filename = os.path.relpath(filename)
        if not json_output:
            stdout.write('Linting file: %s%s' %
                         (termcolor.colored(rel_filename, attrs=('bold',)),
                          linesep))
        if arguments['--force']:
            modified_lines = None
        else:
            modified_lines = vcs.modified_lines(filename,
                                                modified_files[filename],
                                                commit=commit)

        result = linters.lint(
            filename, modified_lines, gitlint_config)
        result = result[filename]

        output = ''
        if result.get('error'):
            output += os.linesep.join(
                '%s: %s' % (error, reason) for reason in result.get('error')
            )
            linter_not_found = True
        if result.get('skipped'):
            output += os.linesep.join(
                '%s: %s' % (skipped, reason) for reason in result.get('skipped')
            )
        if result.get('comments', []) == []:
            if not output:
                output += termcolor.colored('OK', 'green', attrs=('bold',))
        else:
            files_with_problems += 1
            messages = []
            for data in result['comments']:
                formatted_message = format_comment(data)
                messages.append(formatted_message)
                data['formatted_message'] = formatted_message
            output += os.linesep.join(messages)

        if json_output:
            json_result[filename] = result
        else:
            stdout.write(output)
            stdout.write(linesep + linesep)

    if json_output:
        # Hack to convert to unicode, Python3 returns unicode, wheres Python2
        # returns str.
        stdout.write(
            json.dumps(json_result,
                       ensure_ascii=False).encode('utf-8').decode('utf-8'))

    if files_with_problems > 0:
        return 1
    if linter_not_found:
        return 4
    return 0
Exemple #13
0
def main(argv, stdout=sys.stdout, stderr=sys.stderr):
    """Main gitlint routine. To be called from scripts."""
    # Wrap sys stdout for python 2, so print can understand unicode.
    linesep = os.linesep
    if sys.version_info[0] < 3:
        if stdout == sys.stdout:
            stdout = codecs.getwriter("utf-8")(stdout)
        if stderr == sys.stderr:
            stderr = codecs.getwriter("utf-8")(stderr)
        linesep = unicode(os.linesep)

    arguments = docopt.docopt(__doc__,
                              argv=argv[1:],
                              version='git-lint v%s' % __VERSION__)

    json_output = arguments['--json']

    vcs, repository_root = get_vcs_root()

    if vcs is None:
        stderr.write('fatal: Not a git repository' + linesep)
        return 128

    commit = None
    if arguments['--last-commit']:
        commit = vcs.last_commit()

    if arguments['FILENAME']:
        invalid_filenames = find_invalid_filenames(arguments['FILENAME'],
                                                   repository_root)
        if invalid_filenames:
            invalid_filenames.append(('', ''))
            stderr.write(
                linesep.join(invalid[1] for invalid in invalid_filenames))
            return 2

        changed_files = vcs.modified_files(repository_root,
                                           tracked_only=arguments['--tracked'],
                                           commit=commit)
        modified_files = {}
        for filename in arguments['FILENAME']:
            normalized_filename = os.path.abspath(filename)
            modified_files[normalized_filename] = changed_files.get(
                normalized_filename)
    else:
        modified_files = vcs.modified_files(
            repository_root,
            tracked_only=arguments['--tracked'],
            commit=commit)

    linter_not_found = False
    files_with_problems = 0
    gitlint_config = get_config(repository_root)
    json_result = {}

    for filename in sorted(modified_files.keys()):
        rel_filename = os.path.relpath(filename)
        if not json_output:
            stdout.write(
                'Linting file: %s%s' %
                (termcolor.colored(rel_filename, attrs=('bold', )), linesep))
        if arguments['--force']:
            modified_lines = None
        else:
            modified_lines = vcs.modified_lines(filename,
                                                modified_files[filename],
                                                commit=commit)

        result = linters.lint(filename, modified_lines, gitlint_config)
        result = result[filename]

        output_lines = []
        if result.get('error'):
            output_lines.extend('%s: %s' % (ERROR, reason)
                                for reason in result.get('error'))
            linter_not_found = True
        if result.get('skipped'):
            output_lines.extend('%s: %s' % (SKIPPED, reason)
                                for reason in result.get('skipped'))
        if result.get('comments', []) == []:
            if not output_lines:
                output_lines.append(OK)
        else:
            files_with_problems += 1
            for data in result['comments']:
                formatted_message = format_comment(data)
                output_lines.append(formatted_message)
                data['formatted_message'] = formatted_message

        if json_output:
            json_result[filename] = result
        else:
            output = linesep.join(output_lines)
            stdout.write(output)
            stdout.write(linesep + linesep)

    if json_output:
        # Hack to convert to unicode, Python3 returns unicode, wheres Python2
        # returns str.
        stdout.write(
            json.dumps(json_result,
                       ensure_ascii=False).encode('utf-8').decode('utf-8'))

    if files_with_problems > 0:
        return 1
    if linter_not_found:
        return 4
    return 0
Exemple #14
0
 def test_lint_extension_not_defined(self, _):
     config = {'extensions': {}}
     output = linters.lint('foo.txt', lines=[4, 5], config=config)
     self.assertEqual(1, len(output['foo.txt']['skipped']))
     output['foo.txt']['skipped'] = []
     self.assertEqual({'foo.txt': {'skipped': []}}, output)