Ejemplo n.º 1
0
    def get_diff(self):
        old_lines = split_lines(self._module_node.get_code(), keepends=True)
        new_lines = split_lines(self.get_new_code(), keepends=True)

        # Add a newline at the end if it's missing. Otherwise the diff will be
        # very weird. A `diff -u file1 file2` would show the string:
        #
        #     \ No newline at end of file
        #
        # This is not necessary IMO, because Medi does not really play with
        # newlines and the ending newline does not really matter in Python
        # files. ~dave
        if old_lines[-1] != '':
            old_lines[-1] += '\n'
        if new_lines[-1] != '':
            new_lines[-1] += '\n'

        project_path = self._inference_state.project._path
        if self._from_path is None:
            from_p = ''
        else:
            from_p = relpath(self._from_path, project_path)
        if self._to_path is None:
            to_p = ''
        else:
            to_p = relpath(self._to_path, project_path)
        diff = difflib.unified_diff(
            old_lines,
            new_lines,
            fromfile=from_p,
            tofile=to_p,
        )
        # Apparently there's a space at the end of the diff - for whatever
        # reason.
        return ''.join(diff).rstrip(' ')
Ejemplo n.º 2
0
def _split_prefix_at(leaf, until_line):
    """
    Returns a tuple of the leaf's prefix, split at the until_line
    position.
    """
    # second means the second returned part
    second_line_count = leaf.start_pos[0] - until_line
    lines = split_lines(leaf.prefix, keepends=True)
    return ''.join(lines[:-second_line_count]), ''.join(
        lines[-second_line_count:])
Ejemplo n.º 3
0
    def get_desired_result(self):

        if platform.system().lower() == 'windows' and self.type == 'diff':
            # Windows uses backslashes to separate paths.
            lines = split_lines(self._desired_result, keepends=True)
            for i, line in enumerate(lines):
                if re.search(' import_tree/', line):
                    lines[i] = line.replace('/', '\\')
            return ''.join(lines)
        return self._desired_result
Ejemplo n.º 4
0
def cut_value_at_position(leaf, position):
    """
    Cuts of the value of the leaf at position
    """
    lines = split_lines(leaf.value,
                        keepends=True)[:position[0] - leaf.line + 1]
    column = position[1]
    if leaf.line == position[0]:
        column -= leaf.column
    if not lines:
        return ''
    lines[-1] = lines[-1][:column]
    return ''.join(lines)
Ejemplo n.º 5
0
def _replace(nodes,
             expression_replacement,
             extracted,
             pos,
             insert_before_leaf=None,
             remaining_prefix=None):
    # Now try to replace the nodes found with a variable and move the code
    # before the current statement.
    definition = _get_parent_definition(nodes[0])
    if insert_before_leaf is None:
        insert_before_leaf = definition.get_first_leaf()
    first_node_leaf = nodes[0].get_first_leaf()

    lines = split_lines(insert_before_leaf.prefix, keepends=True)
    if first_node_leaf is insert_before_leaf:
        if remaining_prefix is not None:
            # The remaining prefix has already been calculated.
            lines[:-1] = remaining_prefix
    lines[-1:-1] = [indent_block(extracted, lines[-1]) + '\n']
    extracted_prefix = ''.join(lines)

    replacement_dct = {}
    if first_node_leaf is insert_before_leaf:
        replacement_dct[nodes[0]] = extracted_prefix + expression_replacement
    else:
        if remaining_prefix is None:
            p = first_node_leaf.prefix
        else:
            p = remaining_prefix + _get_indentation(nodes[0])
        replacement_dct[nodes[0]] = p + expression_replacement
        replacement_dct[
            insert_before_leaf] = extracted_prefix + insert_before_leaf.value

    for node in nodes[1:]:
        replacement_dct[node] = ''
    return replacement_dct
Ejemplo n.º 6
0
def _remove_indent_of_prefix(prefix):
    r"""
    Removes the last indentation of a prefix, e.g. " \n \n " becomes " \n \n".
    """
    return ''.join(split_lines(prefix, keepends=True)[:-1])
Ejemplo n.º 7
0
def _get_indentation(node):
    return split_lines(node.get_first_leaf().prefix)[-1]
Ejemplo n.º 8
0
    def __init__(self, code=None, line=None, column=None, path=None,
                 encoding=None, sys_path=None, environment=None,
                 project=None, source=None, language="python"):

        self._orig_path = path
        # An empty path (also empty string) should always result in no path.
        self.path = os.path.abspath(path) if path else None
        self.language = language
        self.grammar = marso.load_grammar(language=self.language)

        if encoding is None:
            encoding = 'utf-8'
        else:
            warnings.warn(
                "Deprecated since version 0.17.0. You should cast to valid "
                "unicode yourself, especially if you are not using utf-8.",
                DeprecationWarning,
                stacklevel=2
            )
        if line is not None:
            warnings.warn(
                "Providing the line is now done in the functions themselves "
                "like `Script(...).complete(line, column)`",
                DeprecationWarning,
                stacklevel=2
            )
        if column is not None:
            warnings.warn(
                "Providing the column is now done in the functions themselves "
                "like `Script(...).complete(line, column)`",
                DeprecationWarning,
                stacklevel=2
            )
        if source is not None:
            code = source
            warnings.warn(
                "Use the code keyword argument instead.",
                DeprecationWarning,
                stacklevel=2
            )
        if code is None:
            # TODO add a better warning than the traceback!
            with open(path, 'rb') as f:
                code = f.read()

        if sys_path is not None and not is_py3:
            sys_path = list(map(force_unicode, sys_path))

        if project is None:
            # Load the Python grammar of the current interpreter.
            project = get_default_project(
                self.language,
                os.path.dirname(self.path) if path else None
            )
        # TODO deprecate and remove sys_path from the Script API.
        if sys_path is not None:
            project._sys_path = sys_path
            warnings.warn(
                "Deprecated since version 0.17.0. Use the project API instead, "
                "which means Script(project=Project(dir, sys_path=sys_path)) instead.",
                DeprecationWarning,
                stacklevel=2
            )

        self._inference_state = InferenceState(
            project, environment=environment, script_path=self.path
        )
        debug.speed('init')
        self._module_node, code = self._inference_state.parse_and_get_code(
            code=code,
            path=self.path,
            encoding=encoding,
            use_latest_grammar=path and path.endswith('.pyi'),
            cache=False,  # No disk cache, because the current script often changes.
            diff_cache=settings.fast_parser,
            cache_path=settings.cache_directory,
        )
        debug.speed('parsed')
        self._code_lines = marso.split_lines(code, keepends=True)
        self._code = code
        self._pos = line, column

        cache.clear_time_caches()
        debug.reset_time()