Exemple #1
0
    def test_apply(self):
        file_dict = {
            "f_a": ["1\n", "2\n", "3\n"],
            "f_b": ["1\n", "2\n", "3\n"],
            "f_c": ["1\n", "2\n", "3\n"]
        }
        expected_file_dict = {
            "f_a": ["1\n", "3\n"],
            "f_b": ["1\n", "3_changed\n"],
            "f_c": ["1\n", "2\n", "3\n"]
        }
        diff_dict = {"f_b": Diff()}
        diff_dict["f_b"].change_line(3, "3\n", "3_changed\n")

        section = Section("")
        section.append(Setting("editor", ""))
        uut = OpenEditorAction()
        os.system = self.fake_edit
        diff_dict = uut.apply_from_section(Result("origin", "msg", "f_a"),
                                           file_dict, diff_dict, section)
        diff_dict = uut.apply_from_section(Result("origin", "msg", "f_b"),
                                           file_dict, diff_dict, section)

        for filename in diff_dict:
            file_dict[filename] = diff_dict[filename].apply(
                file_dict[filename])

        self.assertEqual(file_dict, expected_file_dict)
    def test_treat_seperated_imports_independently(self):
        test_file = ("""
import re
import requests
from urllib.parse import urlparse

from coalib.results.Diff import Diff
from coalib.bears.LocalBear import LocalBear
""".splitlines(True))

        expected = ("""
import re
from urllib.parse import urlparse

import requests

from coalib.bears.LocalBear import LocalBear
from coalib.results.Diff import Diff
""".splitlines(True))
        diff = Diff(expected)
        settings = {'treat_seperated_imports_independently': True}
        self.assertEqual(
            list(self.uut.run('', test_file,
                              **settings))[0].diffs[''].modified,
            diff.modified)

        self.assertEqual(
            list(
                self.uut.run(
                    '',
                    ['import curses\n', 'import io\n', 'coala = "coala"\n'],
                    **settings)), [])
    def test_print_result(self):
        self.uut.print = lambda x: x
        self.assertEqual("|    |    | [{normal}] {bear}:".format(normal=RESULT_SEVERITY.__str__(RESULT_SEVERITY.NORMAL),
                                                                 bear="origin") + "\n|    |    | message",
                         self.uut._print_result(Result("origin", "message")))

        builtins.__dict__["input"] = lambda x: 0
        self.uut.print_result(PatchResult("origin", "msg", {}), {})

        (testfile, testfile_path) = tempfile.mkstemp()
        os.close(testfile)
        file_dict = {
            testfile_path: ["1\n", "2\n", "3\n"],
            "f_b": ["1", "2", "3"]
        }
        diff = Diff()
        diff.delete_line(2)
        diff.change_line(3, "3\n", "3_changed\n")
        builtins.__dict__["input"] = self.generate_input  # To assure user can rechose if he didn't chose wisely
        self.uut.print_result(PatchResult("origin", "msg", {testfile_path: diff}), file_dict)
        self.assertEqual(self.curr, 1)
        self.uut.finalize(file_dict)
        with open(testfile_path) as f:
            self.assertEqual(f.readlines(), ["1\n", "3_changed\n"])

        os.remove(testfile_path)

        name, section = self.uut._get_action_info(TestAction().get_metadata())
        self.assertEqual(str(section), " {param : 3}")
        self.assertEqual(name, "TestAction")

        builtins.__dict__["input"] = lambda x: x
Exemple #4
0
    def generate_diff(file, doc_comment, new_comment):
        """
        Generates diff between the original doc_comment and its fix
        new_comment which are instances of DocumentationComment.

        :param doc_comment:
            Original instance of DocumentationComment.
        :param new_comment:
            Fixed instance of DocumentationComment.
        :return:
            Diff instance.
        """
        diff = Diff(file)

        # We need to update old comment positions, as `assemble()`
        # prepends indentation for first line.
        old_range = TextRange.from_values(doc_comment.range.start.line, 1,
                                          doc_comment.range.end.line,
                                          doc_comment.range.end.column)

        # Clearing cached assemble() so a fresh one is fetched.
        new_comment.assemble.cache_clear()

        diff.replace(old_range, new_comment.assemble())
        return diff
Exemple #5
0
    def run(self, filename, file, file_naming_convention: str = "snake"):
        """
        Checks whether the filename follows a certain naming-convention.

        :param file_naming_convention:
            The naming-convention. Supported values are:
            - ``camel`` (``thisIsCamelCase``)
            - ``pascal`` (``ThisIsPascalCase``)
            - ``snake`` (``this_is_snake_case``)
        """
        head, tail = os.path.split(filename)
        filename_without_extension, extension = os.path.splitext(tail)
        try:
            new_name = self._naming_convention[file_naming_convention](
                filename_without_extension)
        except KeyError:
            self.err("Invalid file-naming-convention provided: " +
                     file_naming_convention)
            return

        if new_name != filename_without_extension:
            diff = Diff(file, rename=os.path.join(head, new_name + extension))

            yield Result(
                self,
                "Filename does not follow {} naming-convention.".format(
                    file_naming_convention),
                diff.affected_code(filename),
                diffs={filename: diff})
Exemple #6
0
    def test_print_result_no_input(self):
        with make_temp() as testfile_path:
            file_dict = {testfile_path: ['1\n', '2\n', '3\n']}
            diff = Diff(file_dict[testfile_path])
            diff.delete_line(2)
            diff.change_line(3, '3\n', '3_changed\n')
            with simulate_console_inputs(1, 2, 3) as generator, \
                    retrieve_stdout() as stdout:
                ApplyPatchAction.is_applicable = staticmethod(
                    lambda *args: True)
                print_results_no_input(self.log_printer,
                                       Section('someSection'),
                                       [Result('origin', 'message', diffs={
                                           testfile_path: diff})],
                                       file_dict,
                                       self.file_diff_dict,
                                       self.console_printer)
                self.assertEqual(generator.last_input, -1)
                self.assertEqual(stdout.getvalue(),
                                 """
Project wide:

**** origin [Section: someSection] ****

!    ! [Severity: NORMAL]
!    ! {}\n""".format(highlight_text(self.no_color,
                                     'message', style=BackgroundMessageStyle)))
Exemple #7
0
def generate_diff(comments, file, filename, line, line_number, pos):
    todo_source_range = SourceRange.from_values(filename, line_number, pos + 1)
    affected_comment_sourcerange = [
        c for c in comments if todo_source_range in c
    ]

    affected_len = len(affected_comment_sourcerange)

    if affected_len == 0:
        return {}
    assert affected_len == 1, 'More than 1 affected comment source ranges'

    comment_sourcerange = affected_comment_sourcerange[0]

    comment_start = comment_sourcerange.start.column
    comment_end = comment_sourcerange.end.column
    in_multi_line_comment = (comment_sourcerange.start.line !=
                             comment_sourcerange.end.line)

    line_before_todo_comment = line[:comment_start - 1].rstrip()
    line_behind_todo_comment = line[comment_end:].rstrip()

    line_replacement = line_before_todo_comment + line_behind_todo_comment

    diff = Diff(file)
    if line_replacement and not in_multi_line_comment:
        diff.change_line(line_number, line, line_replacement + '\n')
    elif line_replacement and in_multi_line_comment:
        text_replacement = line[pos:]
        diff.change_line(line_number, line,
                         line.replace(text_replacement, '').rstrip() + '\n')
    else:
        diff.delete_line(line_number)

    return {filename: diff}
Exemple #8
0
    def apply(self, result, original_file_dict, file_diff_dict, editor: str):
        """
        Open a temporary clone of the file in an editor.

        :param editor: The editor to open the file with.
        """
        filename = result.file
        original_file = original_file_dict[filename]
        diff = file_diff_dict.get(filename, Diff())
        current_file = diff.apply(original_file)

        # Prefix is nice for the user so he has an indication that its the
        # right file he's editing
        temphandle, tempname = tempfile.mkstemp(os.path.basename(filename))
        os.close(temphandle)
        with open(tempname, "w") as temphandle:
            temphandle.writelines(current_file)

        editor_arg = EDITOR_ARGS.get(editor.strip(), None)
        if editor_arg:
            editor = editor + " " + editor_arg

        # Dear user, you wanted an editor, so you get it. But do you really
        # think you can do better than we?
        os.system(editor + " " + tempname)

        with open(tempname) as temphandle:
            new_file = temphandle.readlines()

        os.remove(tempname)

        intermediate_diff = Diff.from_string_arrays(current_file, new_file)
        file_diff_dict[filename] = diff + intermediate_diff

        return file_diff_dict
def generate_label_diff(file, filename, line, line_number, match_object,
                        expected_label):
    """
    Generates a diff for a missing or wrong control loop end label.
    Missing labels will be added, wrong ones replaced, content after the
    label will be left untouched.


    :param match_object:   A Match object containing the groups ``close``
                           containing the closing delimiters of a control
                           end tag and the optional group ``label``
                           containing the end tag label.
    :param expected_label: The expected label for that control block.

    """
    diff = Diff(file)

    content_before = line[:match_object.end('close')]

    suffix_start = match_object.end('close')
    # if a label is there, we cut it out, by starting the kept suffix after it
    if match_object.group('label') is not None:
        suffix_start = match_object.end('label')

    content_after = line[suffix_start:]

    replacement = '{before}{label}{after}'.format(before=content_before,
                                                  after=content_after,
                                                  label=expected_label)
    diff.change_line(line_number, line, replacement)
    return {filename: diff}
def generate_spacing_diff(file, filename, line, line_number, match_object,
                          required_spacing):
    """
    Generate a diff for incorrectly spaced control or variable tags.

    :param match_object:     A Match object containing the groups ``open``,
                             ``close`` containing the opening and closing
                             delimiters of a Jinja2 tag and ``content``
                             containing everything in between.
    :param required_spacing: The number of spaces expected after the ``open``
                             delimiter and before the ``close`` delimiter
    """
    diff = Diff(file)

    content_before = line[:match_object.start('open')]
    content_after = line[match_object.end('close'):]

    spacing = ' ' * required_spacing
    replacement = (
        '{before}{open}{spacing}{content}{spacing}{close}{after}'.format(
            before=content_before,
            spacing=spacing,
            after=content_after,
            content=match_object.group('content').strip(),
            open=match_object.group('open'),
            close=match_object.group('close')))
    diff.change_line(line_number, line, replacement)
    return {filename: diff}
Exemple #11
0
    def process_output(self, output, filename, file):
        output = json.loads(output)

        for issue in output:
            diff = Diff(file)
            from_lines = issue['from'].splitlines()
            to_lines = issue['to'].splitlines()
            assert len(from_lines) == len(to_lines)
            for other_lines in range(1, len(from_lines)):
                assert from_lines[other_lines] == to_lines[other_lines]
            line_nr = issue['startLine']
            line_to_change = file[line_nr - 1]
            newline = line_to_change.replace(from_lines[0], to_lines[0])
            diff.change_line(line_nr, line_to_change, newline)

            yield Result.from_values(
                origin=self,
                message=issue['hint'],
                file=filename,
                severity=self.severity_map[issue['severity']],
                line=issue['startLine'],
                column=issue['startColumn'],
                end_line=issue['endLine'],
                end_column=issue['endColumn'],
                diffs={filename: diff})
Exemple #12
0
    def run(self,
            filename,
            file,
            file_naming_convention: str = None,
            ignore_uppercase_filenames: bool = True):
        """
        Checks whether the filename follows a certain naming-convention.

        :param file_naming_convention:
            The naming-convention. Supported values are:
            - ``auto`` to guess the correct convention. Defaults to ``snake``
            if the correct convention cannot be guessed.
            - ``camel`` (``thisIsCamelCase``)
            - ``kebab`` (``this-is-kebab-case``)
            - ``pascal`` (``ThisIsPascalCase``)
            - ``snake`` (``this_is_snake_case``)
            - ``space`` (``This Is Space Case``)
        :param ignore_uppercase_filenames:
            Whether or not to ignore fully uppercase filenames completely,
            e.g. COPYING, LICENSE etc.
        """
        head, tail = os.path.split(filename)
        filename_without_extension, extension = os.path.splitext(tail)

        if file_naming_convention is None:
            self.warn('Please specify a file naming convention explicitly'
                      ' or use "auto".')
            file_naming_convention = 'auto'
        else:
            file_naming_convention = file_naming_convention.lower()

        if file_naming_convention == 'auto':
            if extension in self._language_naming_convention:
                file_naming_convention = self._language_naming_convention[
                    extension]
            else:
                self.warn('The file naming convention could not be guessed. '
                          'Using the default "snake" naming convention.')
                file_naming_convention = 'snake'

        try:
            new_name = self._naming_convention[file_naming_convention](
                filename_without_extension)
        except KeyError:
            self.err('Invalid file-naming-convention provided: ' +
                     file_naming_convention)
            return

        if ignore_uppercase_filenames and filename_without_extension.isupper():
            return

        if new_name != filename_without_extension:
            diff = Diff(file, rename=os.path.join(head, new_name + extension))

            yield Result(
                self,
                'Filename does not follow {} naming-convention.'.format(
                    file_naming_convention),
                diff.affected_code(filename),
                diffs={filename: diff})
    def _get_diff(self):
        if self.treat_seperated_imports_independently:
            import_stmts = PyImportSortBear._seperate_imports(self.file)
            sorted_imps = []
            for units in import_stmts:
                sort_imports = SortImports(file_contents=''.join(
                    [x[1] for x in units]),
                                           **self.isort_settings)
                sort_imports = sort_imports.output.splitlines(True)
                sorted_imps.append((units, sort_imports))

            diff = Diff(self.file)
            for old, new in sorted_imps:
                start = old[0][0]
                end = start + len(old) - 1
                diff.delete_lines(start, end)
                assert isinstance(new, list)
                diff.add_lines(start, list(new))

            if diff.modified != diff._file:
                return diff
        else:
            sort_imports = SortImports(file_contents=''.join(self.file),
                                       **self.isort_settings)

            new_file = tuple(sort_imports.output.splitlines(True))
            if new_file != tuple(self.file):
                diff = Diff.from_string_arrays(self.file, new_file)
                return diff
        return None
Exemple #14
0
    def test_function(self):
        test_file_content = load_testfile(test_file).splitlines(True)

        arguments = {'language': 'python', 'docstyle': 'default'}
        if optional_setting:
            arguments.update(optional_setting)
        section = Section('test-section')
        for key, value in arguments.items():
            section[key] = value

        with execute_bear(
                DocumentationStyleBear(section, Queue()),
                test_file,
                test_file_content,
                **arguments) as results:

            diff = Diff(test_file_content)
            for result in results:
                # Only the given test file should contain a patch.
                self.assertEqual(len(result.diffs), 1)

                diff += result.diffs[test_file]

        correct_file_content = load_testfile(expected_file).splitlines(True)

        self.assertEqual(correct_file_content, diff.modified)
Exemple #15
0
    def test_apply_rename(self):
        # Initial file contents, *before* a patch was applied
        file_dict = {
            self.fa: ["1\n", "2\n", "3\n"]}

        # A patch that was applied for some reason to make things complicated
        file_diff_dict = {}
        diff = Diff(file_dict[self.fa], rename=self.fa+".renamed")
        diff.change_line(3, "3\n", "3_changed\n")
        ApplyPatchAction().apply(
            Result("origin", "msg", diffs={self.fa: diff}),
            file_dict,
            file_diff_dict)
        # End file contents after the patch and the OpenEditorAction was
        # applied
        expected_file_dict = {
            self.fa: ["1\n", "3_changed\n"]}

        section = Section("")
        section.append(Setting("editor", ""))
        uut = OpenEditorAction()
        subprocess.call = self.fake_edit
        diff_dict = uut.apply_from_section(
            Result.from_values("origin", "msg", self.fa),
            file_dict,
            file_diff_dict,
            section)

        for filename in diff_dict:
            file_dict[filename] = (
                file_diff_dict[filename].modified)

        self.assertEqual(file_dict, expected_file_dict)
        open(self.fa, 'w').close()
Exemple #16
0
    def test_is_applicable_empty_patch(self):
        diff = Diff([], rename='new_name')
        result = Result('', '', diffs={'f': diff})

        # Two renames donot result in any change
        self.assertEqual(
            ApplyPatchAction.is_applicable(result, {}, {'f': diff}),
            'The given patches do not change anything anymore.')
Exemple #17
0
    def test_print_result_interactive_small_patch(self, apply_from_section, _):
        file_dict = {'a': ['a\n', 'b\n', 'c\n'], 'b': ['old_first\n']}
        diff_dict = {'a': Diff(file_dict['a']),
                     'b': Diff(file_dict['b'])}
        diff_dict['a'].add_lines(1, ['test\n'])
        diff_dict['a'].delete_line(3)
        result = Result('origin', 'msg', diffs=diff_dict)
        section = Section('test')

        print_result(self.console_printer,
                     section,
                     self.file_diff_dict,
                     result,
                     file_dict,
                     True)
        apply_from_section.assert_called_once_with(
            result, file_dict, self.file_diff_dict, section)
Exemple #18
0
    def test_is_applicable_conflict(self):
        diff = Diff(["1\n", "2\n", "3\n"])
        diff.add_lines(2, ['a line'])

        conflict_result = Result("", "", diffs={'f': diff})
        # Applying the same diff twice will result in a conflict
        self.assertFalse(
            ApplyPatchAction.is_applicable(conflict_result, {}, {'f': diff}))
Exemple #19
0
    def test_print_result_interactive_big_patch(self, diffs_info, _):
        file_dict = {'a': ['a\n', 'b\n', 'c\n'], 'b': ['old_first\n']}
        diff_dict = {'a': Diff(file_dict['a']),
                     'b': Diff(file_dict['b'])}
        diff_dict['a'].add_lines(1, ['test\n', 'test1\n', 'test2\n'])
        diff_dict['a'].delete_line(3)
        diff_dict['a'].add_lines(3, ['3test\n'])
        result = Result('origin', 'msg', diffs=diff_dict)
        section = Section('test')

        print_result(self.console_printer,
                     section,
                     self.file_diff_dict,
                     result,
                     file_dict,
                     True)
        diffs_info.assert_called_once_with(diff_dict, self.console_printer)
Exemple #20
0
 def test_apply_empty(self):
     with retrieve_stdout() as stdout:
         test_result = Result('origin', 'message', diffs={'a': Diff([])})
         file_dict = {'a': []}
         self.assertEqual(
             self.uut.apply_from_section(test_result, file_dict, {},
                                         self.section), {})
         self.assertEqual(stdout.getvalue(), '')
Exemple #21
0
    def test_is_applicable_conflict(self):
        diff = Diff(['1\n', '2\n', '3\n'])
        diff.add_lines(2, ['a line'])

        conflict_result = Result('', '', diffs={'f': diff})
        # Applying the same diff twice will result in a conflict
        self.assertIn(
            'Two or more patches conflict with each other: ',
            ApplyPatchAction.is_applicable(conflict_result, {}, {'f': diff}))
    def test_print_result_interactive_big_patch(self, diffs_info, _):
        file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]}
        diff_dict = {"a": Diff(file_dict['a']),
                     "b": Diff(file_dict['b'])}
        diff_dict["a"].add_lines(1, ["test\n", "test1\n", "test2\n"])
        diff_dict["a"].delete_line(3)
        diff_dict["a"].add_lines(3, ["3test\n"])
        result = Result("origin", "msg", diffs=diff_dict)
        section = Section("test")

        print_result(self.console_printer,
                     self.log_printer,
                     section,
                     self.file_diff_dict,
                     result,
                     file_dict,
                     True)
        diffs_info.assert_called_once_with(diff_dict, self.console_printer)
    def run(self, filename, file,
            timeout: int=DEFAULT_TIMEOUT,
            ignore_regex: str="[.\/]example\.com"):
        """
        Find links in any text file and check if they are valid.

        A link is considered valid if the server responds with a 2xx code.

        This bear can automatically fix redirects, but ignores redirect
        URLs that have a huge difference with the original URL.

        :param timeout:      Request timeout period.
        :param ignore_regex: A regex for urls to ignore.
        """
        for line_number, link, code in InvalidLinkBear.find_links_in_file(
                file, timeout, ignore_regex):
            if code is None:
                yield Result.from_values(
                    origin=self,
                    message=('Broken link - unable to connect to '
                             '{url}').format(url=link),
                    file=filename,
                    line=line_number,
                    severity=RESULT_SEVERITY.MAJOR)
            elif not 200 <= code < 300:
                # HTTP status 404, 410 or 50x
                if code in (404, 410) or 500 <= code < 600:
                    yield Result.from_values(
                        origin=self,
                        message=('Broken link - unable to connect to {url} '
                                 '(HTTP Error: {code})'
                                 ).format(url=link, code=code),
                        file=filename,
                        line=line_number,
                        severity=RESULT_SEVERITY.NORMAL)
                if 300 <= code < 400:  # HTTP status 30x
                    redirect_url = requests.head(link, allow_redirects=True).url
                    matcher = SequenceMatcher(
                        None, redirect_url, link)
                    if (matcher.real_quick_ratio() > 0.7 and
                            matcher.ratio()) > 0.7:
                        diff = Diff(file)
                        current_line = file[line_number - 1]
                        start = current_line.find(link)
                        end = start + len(link)
                        replacement = current_line[:start] + \
                            redirect_url + current_line[end:]
                        diff.change_line(line_number, current_line, replacement)

                        yield Result.from_values(
                            self,
                            'This link redirects to ' + redirect_url,
                            diffs={filename: diff},
                            file=filename,
                            line=line_number,
                            severity=RESULT_SEVERITY.NORMAL)
Exemple #24
0
    def test_apply_delete(self):
        uut = ApplyPatchAction()
        with make_temp() as f_a:
            file_dict = {f_a: ['1\n', '2\n', '3\n']}
            file_diff_dict = {}
            diff = Diff(file_dict[f_a], delete=True)
            uut.apply(Result('origin', 'msg', diffs={f_a: diff}), file_dict,
                      file_diff_dict)
            self.assertFalse(isfile(f_a))
            self.assertTrue(isfile(f_a + '.orig'))
            os.remove(f_a + '.orig')

            diff = Diff(file_dict[f_a])
            diff.change_line(3, '3\n', '3_changed\n')
            uut.apply(Result('origin', 'msg', diffs={f_a: diff}), file_dict,
                      file_diff_dict)
            self.assertFalse(isfile(f_a + '.orig'))
            # Recreate file so that context manager make_temp() can delete it
            open(f_a, 'w').close()
    def test_apply(self):
        uut = ApplyPatchAction()
        with make_temp() as f_a, make_temp() as f_b, make_temp() as f_c:

            file_dict = {
                f_a: ["1\n", "2\n", "3\n"],
                f_b: ["1\n", "2\n", "3\n"],
                f_c: ["1\n", "2\n", "3\n"]
            }
            expected_file_dict = {
                f_a: ["1\n", "3_changed\n"],
                f_b: ["1\n", "2\n", "3_changed\n"],
                f_c: ["1\n", "2\n", "3\n"]
            }

            file_diff_dict = {}

            diff = Diff(file_dict[f_a])
            diff.delete_line(2)
            uut.apply_from_section(Result("origin", "msg", diffs={f_a: diff}),
                                   file_dict, file_diff_dict, Section("t"))

            diff = Diff(file_dict[f_a])
            diff.change_line(3, "3\n", "3_changed\n")
            uut.apply_from_section(Result("origin", "msg", diffs={f_a: diff}),
                                   file_dict, file_diff_dict, Section("t"))

            diff = Diff(file_dict[f_b])
            diff.change_line(3, "3\n", "3_changed\n")
            uut.apply(Result("origin", "msg", diffs={f_b: diff}), file_dict,
                      file_diff_dict)

            for filename in file_diff_dict:
                file_dict[filename] = file_diff_dict[filename].modified

            self.assertEqual(file_dict, expected_file_dict)
            with open(f_a) as fa:
                self.assertEqual(file_dict[f_a], fa.readlines())
            with open(f_b) as fb:
                self.assertEqual(file_dict[f_b], fb.readlines())
            with open(f_c) as fc:
                # File c is unchanged and should be untouched
                self.assertEqual([], fc.readlines())
    def test_acquire_actions_and_apply_single(self):
        with make_temp() as testfile_path:
            file_dict = {testfile_path: ['1\n', '2\n', '3\n']}
            diff = Diff(file_dict[testfile_path])
            diff.delete_line(2)
            diff.change_line(3, '3\n', '3_changed\n')
            with simulate_console_inputs('a', 'n') as generator:
                with retrieve_stdout() as sio:
                    ApplyPatchAction.is_applicable = staticmethod(
                        lambda *args: True)
                    acquire_actions_and_apply(self.console_printer,
                                              Section(''),
                                              self.file_diff_dict,
                                              Result(
                                                  'origin',
                                                  'message',
                                                  diffs={testfile_path: diff}),
                                              file_dict,
                                              apply_single=True)
                    self.assertEqual(generator.last_input, -1)
                    self.assertIn('', sio.getvalue())

            class InvalidateTestAction(ResultAction):

                is_applicable = staticmethod(lambda *args: True)

                def apply(*args, **kwargs):
                    ApplyPatchAction.is_applicable = staticmethod(
                        lambda *args: 'ApplyPatchAction cannot be applied.')

            old_applypatch_is_applicable = ApplyPatchAction.is_applicable
            ApplyPatchAction.is_applicable = staticmethod(lambda *args: True)
            cli_actions = [ApplyPatchAction(), InvalidateTestAction()]

            with simulate_console_inputs('a') as generator:
                with retrieve_stdout() as sio:
                    acquire_actions_and_apply(self.console_printer,
                                              Section(''),
                                              self.file_diff_dict,
                                              Result(
                                                  'origin',
                                                  'message',
                                                  diffs={testfile_path: diff}),
                                              file_dict,
                                              cli_actions=cli_actions,
                                              apply_single=True)
                    self.assertEqual(generator.last_input, -1)

                    action_fail = 'Failed to execute the action'
                    self.assertNotIn(action_fail, sio.getvalue())

                    apply_path_desc = ApplyPatchAction().get_metadata().desc
                    self.assertEqual(sio.getvalue().count(apply_path_desc), 0)

            ApplyPatchAction.is_applicable = old_applypatch_is_applicable
Exemple #27
0
    def correct_single_line_str(
        self,
        filename,
        file,
        sourcerange,
        preferred_quotation,
        force_preferred_quotation: bool = False,
    ):
        """
        Corrects a given single line string assuming it does not use the
        preferred quotation. If the preferred quotation mark is used inside the
        string, no correction will be made.

        This function will yield one or no Result objects.

        :param filename:
            The filename of the file to correct the line in.
        :param file:
            The file contents as list of lines.
        :param sourcerange:
            The sourcerange indicating where to find the string.
        :param preferred_quotation:
            ``'`` or ``"`` respectively.
        :param force_preferred_quotation:
            Decide whether the preferred quotes are compulsory
            to adhere or not.
        """
        str_contents = file[
            sourcerange.start.line -
            1][sourcerange.start.column:sourcerange.end.column - 1]

        if (preferred_quotation in str_contents
                and not force_preferred_quotation):
            return

        # Escape preferred quotes if present.
        str_contents = str_contents.replace(preferred_quotation,
                                            '\\' + preferred_quotation)

        before = file[sourcerange.start.line - 1][:sourcerange.start.column -
                                                  1]
        after = file[sourcerange.end.line - 1][sourcerange.end.column:]

        replacement = (before + preferred_quotation + str_contents +
                       preferred_quotation + after)

        diff = Diff(file)
        diff.change_line(sourcerange.start.line,
                         file[sourcerange.start.line - 1], replacement)
        yield Result(self, ('You do not use the preferred quotation marks.'
                            ' Preferred mark: {}'.format(preferred_quotation)),
                     diff.affected_code(filename),
                     diffs={filename: diff})
Exemple #28
0
 def test_apply_renaming_only(self):
     with retrieve_stdout() as stdout:
         test_result = Result('origin',
                              'message',
                              diffs={'a': Diff([], rename='b')})
         file_dict = {'a': []}
         self.assertEqual(
             self.uut.apply_from_section(test_result, file_dict, {},
                                         self.section), {})
         self.assertEqual(
             stdout.getvalue(), '[----] ' + join('a', 'a') + '\n'
             '[++++] ' + join('b', 'b') + '\n')
    def test_acquire_actions_and_apply(self):
        with make_temp() as testfile_path:
            file_dict = {testfile_path: ["1\n", "2\n", "3\n"]}
            diff = Diff(file_dict[testfile_path])
            diff.delete_line(2)
            diff.change_line(3, "3\n", "3_changed\n")
            with simulate_console_inputs(1, 0) as generator, \
                    retrieve_stdout() as sio:
                ApplyPatchAction.is_applicable = staticmethod(
                        lambda *args: True)
                acquire_actions_and_apply(self.console_printer,
                                          self.log_printer,
                                          Section(""),
                                          self.file_diff_dict,
                                          Result("origin", "message", diffs={
                                           testfile_path: diff}),
                                          file_dict)
                self.assertEqual(generator.last_input, 1)
                self.assertIn(ApplyPatchAction.SUCCESS_MESSAGE, sio.getvalue())

            class InvalidateTestAction(ResultAction):

                is_applicable = staticmethod(lambda *args: True)

                def apply(*args, **kwargs):
                    ApplyPatchAction.is_applicable = staticmethod(
                        lambda *args: False)

            old_applypatch_is_applicable = ApplyPatchAction.is_applicable
            ApplyPatchAction.is_applicable = staticmethod(lambda *args: True)
            cli_actions = [ApplyPatchAction(), InvalidateTestAction()]

            with simulate_console_inputs(2, 1, 0) as generator, \
                    retrieve_stdout() as sio:
                acquire_actions_and_apply(self.console_printer,
                                          self.log_printer,
                                          Section(""),
                                          self.file_diff_dict,
                                          Result("origin", "message",
                                                 diffs={testfile_path: diff}),
                                          file_dict,
                                          cli_actions=cli_actions)
                self.assertEqual(generator.last_input, 2)

                action_fail = "Failed to execute the action"
                self.assertNotIn(action_fail, sio.getvalue())

                apply_path_desc = ApplyPatchAction().get_metadata().desc
                self.assertEqual(sio.getvalue().count(apply_path_desc), 1)

            ApplyPatchAction.is_applicable = old_applypatch_is_applicable
Exemple #30
0
    def test_apply(self):
        file_dict = {"f_a": ["1", "2", "3"], "f_b": ["1", "2", "3"]}
        expected_file_dict = {
            "f_a": ["1", "3_changed"],
            "f_b": ["1", "2", "3"]
        }
        diff = Diff(file_dict['f_a'])
        diff.delete_line(2)
        diff.change_line(3, "3", "3_changed")

        uut = Result("origin", "msg", diffs={"f_a": diff})
        uut.apply(file_dict)

        self.assertEqual(file_dict, expected_file_dict)