示例#1
0
def format_line(line: str) -> str:
    """Try format a source code line"""

    formatted_line = line
    try:
        # If we handling multilines this will not be parsed
        formatted_line, _ =  FormatCode(line)

    except IndentationError as error:
        # Case of trying to parse a piece of a statement, like a for loop header
        # Try again with a pass stament
        formatted_line, _ = FormatCode(line + "pass")
        formatted_line = formatted_line.replace("pass", "")

    except SyntaxError as error:
        if error.args[0] == "unexpected EOF while parsing":
            try:
                formatted_line, _ = FormatCode(line + "pass")
                formatted_line = formatted_line.replace("pass", "")
            except SyntaxError as syntax_error:
                raise ParseError("Could not parse line: {}".format(line)) from syntax_error
        else:
            raise ParseError("Could not parse line: {}".format(line)) from error

    return formatted_line.strip()
示例#2
0
def _format(document, lines=None):
    # Yapf doesn't work with CRLF/CR line endings, so we replace them by '\n'
    # and restore them below.
    replace_eols = False
    source = document.source
    eol_chars = get_eol_chars(source)
    if eol_chars in ['\r', '\r\n']:
        replace_eols = True
        source = source.replace(eol_chars, '\n')

    new_source, changed = FormatCode(
        source,
        lines=lines,
        filename=document.filename,
        style_config=file_resources.GetDefaultStyleForDir(
            os.path.dirname(document.path)
        )
    )

    if not changed:
        return []

    if replace_eols:
        new_source = new_source.replace('\n', eol_chars)

    # I'm too lazy at the moment to parse diffs into TextEdit items
    # So let's just return the entire file...
    return [{
        'range': {
            'start': {'line': 0, 'character': 0},
            # End char 0 of the line after our document
            'end': {'line': len(document.lines), 'character': 0}
        },
        'newText': new_source
    }]
示例#3
0
    def get_setup(self):
        # render template
        with self.setup_path.open(encoding='utf-8') as f:
            document = f.read()
        template = Environment().from_string(document)
        document = template.render(
            package=self.package,
            format_vcs=self._format_vcs,
        )

        # format by yapf
        style = CreateGoogleStyle()
        document, _changed = FormatCode(document, style_config=style)
        # remove empty strings
        while '\n\n' in document:
            document = document.replace('\n\n', '\n')
        # format by autopep8
        document = fix_code(document)
        return document
示例#4
0
def get_function_signature(
    function,
    owner_class=None,
    strip_self_param=False,
    show_module=False,
    pretty=True,
):
    # Get base name.
    name_parts = []
    if show_module:
        name_parts.append(function.__module__)
    if owner_class:
        name_parts.append(owner_class.__name__)
    if hasattr(function, '__name__'):
        name_parts.append(function.__name__)
    else:
        name_parts.append(type(function).__name__)
        name_parts.append('__call__')
        function = function.__call__
    name = '.'.join(name_parts)

    try:
        argspec = get_full_arg_spec(function)
    except TypeError:
        parameters = []
    else:
        parameters = get_paramaters_from_arg_spec(argspec,
                                                  strip_self=strip_self_param)

    # Prettify annotations.
    class repr_str(str):
        def __repr__(self):
            return self

    def prettify(val):  # type: (Parameter.Value) -> Parameter.Value
        if isinstance(val.value, type):
            val = Parameter.Value(repr_str(val.value.__name__))
        return val

    for i, param in enumerate(parameters):
        if param.annotation:
            param = param.replace(annotation=prettify(param.annotation))
        if param.default:
            param = param.replace(default=prettify(param.default))
        parameters[i] = param

    if pretty:
        # Replace annotations and defaults with placeholders that are valid syntax.
        supplements = {}
        counter = [0]

        def _add_supplement(value):
            annotation_id = '_{}'.format(counter[0])
            annotation_id += '_' * (len(repr(value)) - len(annotation_id))
            supplements[annotation_id] = value
            counter[0] += 1
            return repr_str(annotation_id)

        for i, param in enumerate(parameters):
            if param.annotation:
                param = param.replace(annotation=Parameter.Value(
                    _add_supplement(param.annotation.value)))
            if param.default:
                param = param.replace(default=Parameter.Value(
                    _add_supplement(param.default.value)))
            parameters[i] = param

    # Use a placeholder in pretty mode as the generated *name* may also
    # sometimes not be valid syntax (eg. if it includes the class name).
    name_placeholder = '_PH_' + '_' * (len(name) - 2)
    sig = (name_placeholder if pretty else
           name) + '(' + format_parameters_list(parameters) + ')'

    if pretty:
        sig, _ = FormatCode('def ' + sig + ': pass', style_config='pep8')
        sig = sig[4:].rpartition(':')[0]

        # Replace the annotation and default placeholders with the actual values.
        for placeholder, annotation in supplements.items():
            sig = sig.replace(placeholder, repr(annotation))

        # Replace the placeholder and fix indents.
        sig = sig.replace(name_placeholder, name)
        delta = len(name_placeholder) - len(name)
        lines = sig.split('\n')
        for i, line in enumerate(lines[1:], 1):
            indent = len(line) - len(line.lstrip()) - delta - 4  # 4 for "def "
            if indent <= 0 and line.strip() != ')':
                indent = 4
            lines[i] = ' ' * indent + line.lstrip()
        sig = '\n'.join(lines)

    return sig