[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/Kai161998/pythonVSCode/master/pythonFiles/parso/python/pep8.py [Back]  [Original]

import re
from contextlib import contextmanager

from parso.python.errors import ErrorFinder, ErrorFinderConfig
from parso.normalizer import Rule
from parso.python.tree import search_ancestor, Flow, Scope


_IMPORT_TYPES = ('import_name', 'import_from')
_SUITE_INTRODUCERS = ('classdef', 'funcdef', 'if_stmt', 'while_stmt',
                      'for_stmt', 'try_stmt', 'with_stmt')
_NON_STAR_TYPES = ('term', 'import_from', 'power')
_OPENING_BRACKETS = '(', '[', '{'
_CLOSING_BRACKETS = ')', ']', '}'
_FACTOR = '+', '-', '~'
_ALLOW_SPACE = '*', '+', '-', '**', '/', '//', '@'
_BITWISE_OPERATOR = '', '|', '&', '^'
_NEEDS_SPACE = ('=', '%', '->',
                '', '==', '>=', ' %s characters)' %
                        (last_column, self._config.max_characters),
                )

    def _check_spacing(self, part, spacing):
        def add_if_spaces(*args):
            if spaces:
                return self.add_issue(*args)

        def add_not_spaces(*args):
            if not spaces:
                return self.add_issue(*args)

        spaces = spacing.value
        prev = self._previous_part
        if prev is not None and prev.type == 'error_leaf' or part.type == 'error_leaf':
            return

        type_ = part.type
        if '\t' in spaces:
            self.add_issue(spacing, 223, 'Used tab to separate tokens')
        elif type_ == 'comment':
            if len(spaces) < self._config.spaces_before_comment:
                self.add_issue(spacing, 261, 'At least two spaces before inline comment')
        elif type_ == 'newline':
            add_if_spaces(spacing, 291, 'Trailing whitespace')
        elif len(spaces) > 1:
            self.add_issue(spacing, 221, 'Multiple spaces used')
        else:
            if prev in _OPENING_BRACKETS:
                message = "Whitespace after '%s'" % part.value
                add_if_spaces(spacing, 201, message)
            elif part in _CLOSING_BRACKETS:
                message = "Whitespace before '%s'" % part.value
                add_if_spaces(spacing, 202, message)
            elif part in (',', ';') or part == ':' \
                    and part.parent.type not in  _POSSIBLE_SLICE_PARENTS:
                message = "Whitespace before '%s'" % part.value
                add_if_spaces(spacing, 203, message)
            elif prev == ':' and prev.parent.type in _POSSIBLE_SLICE_PARENTS:
                pass # TODO
            elif prev in (',', ';', ':'):
                add_not_spaces(spacing, 231, "missing whitespace after '%s'")
            elif part == ':':  # Is a subscript
                # TODO
                pass
            elif part in ('*', '**') and part.parent.type not in _NON_STAR_TYPES \
                    or prev in ('*', '**') \
                    and prev.parent.type not in _NON_STAR_TYPES:
                # TODO
                pass
            elif prev in _FACTOR and prev.parent.type == 'factor':
                pass
            elif prev == '@' and prev.parent.type == 'decorator':
                pass  # TODO should probably raise an error if there's a space here
            elif part in _NEEDS_SPACE or prev in _NEEDS_SPACE:
                if part == '=' and part.parent.type in ('argument', 'param') \
                        or prev == '=' and prev.parent.type in ('argument', 'param'):
                    if part == '=':
                        param = part.parent
                    else:
                        param = prev.parent
                    if param.type == 'param' and param.annotation:
                        add_not_spaces(spacing, 252, 'Expected spaces around annotation equals')
                    else:
                        add_if_spaces(spacing, 251, 'Unexpected spaces around keyword / parameter equals')
                elif part in _BITWISE_OPERATOR or prev in _BITWISE_OPERATOR:
                    add_not_spaces(spacing, 227, 'Missing whitespace around bitwise or shift operator')
                elif part == '%' or prev == '%':
                    add_not_spaces(spacing, 228, 'Missing whitespace around modulo operator')
                else:
                    message_225 = 'Missing whitespace between tokens'
                    add_not_spaces(spacing, 225, message_225)
            elif type_ == 'keyword' or prev.type == 'keyword':
                add_not_spaces(spacing, 275, 'Missing whitespace around keyword')
            else:
                prev_spacing = self._previous_spacing
                if prev in _ALLOW_SPACE and spaces != prev_spacing.value \
                        and '\n' not in self._previous_leaf.prefix:
                    message = "Whitespace before operator doesn't match with whitespace after"
                    self.add_issue(spacing, 229, message)

                if spaces and part not in _ALLOW_SPACE and prev not in _ALLOW_SPACE:
                    message_225 = 'Missing whitespace between tokens'
                    #print('xy', spacing)
                    #self.add_issue(spacing, 225, message_225)
                    # TODO why only brackets?
                    if part in _OPENING_BRACKETS:
                        message = "Whitespace before '%s'" % part.value
                        add_if_spaces(spacing, 211, message)

    def _analyse_non_prefix(self, leaf):
        typ = leaf.type
        if typ == 'name' and leaf.value in ('l', 'O', 'I'):
            if leaf.is_definition():
                message = "Do not define %s named 'l', 'O', or 'I' one line"
                if leaf.parent.type == 'class' and leaf.parent.name == leaf:
                    self.add_issue(leaf, 742, message % 'classes')
                elif leaf.parent.type == 'function' and leaf.parent.name == leaf:
                    self.add_issue(leaf, 743, message % 'function')
                else:
                    self.add_issuadd_issue(741, message % 'variables', leaf)
        elif leaf.value == ':':
            if isinstance(leaf.parent, (Flow, Scope)) and leaf.parent.type != 'lambdef':
                next_leaf = leaf.get_next_leaf()
                if next_leaf.type != 'newline':
                    if leaf.parent.type == 'funcdef':
                        self.add_issue(next_leaf, 704, 'Multiple statements on one line (def)')
                    else:
                        self.add_issue(next_leaf, 701, 'Multiple statements on one line (colon)')
        elif leaf.value == ';':
            if leaf.get_next_leaf().type in ('newline', 'endmarker'):
                self.add_issue(leaf, 703, 'Statement ends with a semicolon')
            else:
                self.add_issue(leaf, 702, 'Multiple statements on one line (semicolon)')
        elif leaf.value in ('==', '!='):
            comparison = leaf.parent
            index = comparison.children.index(leaf)
            left = comparison.children[index - 1]
            right = comparison.children[index + 1]
            for node in left, right:
                if node.type == 'keyword' or node.type == 'name':
                    if node.value == 'None':
                        message = "comparison to None should be 'if cond is None:'"
                        self.add_issue(leaf, 711, message)
                        break
                    elif node.value in ('True', 'False'):
                        message = "comparison to False/True should be 'if cond is True:' or 'if cond:'"
                        self.add_issue(leaf, 712, message)
                        break
        elif leaf.value in ('in', 'is'):
            comparison = leaf.parent
            if comparison.type == 'comparison' and comparison.parent.type == 'not_test':
                if leaf.value == 'in':
                    self.add_issue(leaf, 713, "test for membership should be 'not in'")
                else:
                    self.add_issue(leaf, 714, "test for object identity should be 'is not'")
        elif typ == 'string':
            # Checking multiline strings
            for i, line in enumerate(leaf.value.splitlines()[1:]):
                indentation = re.match('[ \t]*', line).group(0)
                start_pos = leaf.line + i, len(indentation)
                # TODO check multiline indentation.
        elif typ == 'endmarker':
            if self._newline_count >= 2:
                self.add_issue(leaf, 391, 'Blank line at end of file')

    def add_issue(self, node, code, message):
        if self._previous_leaf is not None:
            if search_ancestor(self._previous_leaf, 'error_node') is not None:
                return
            if self._previous_leaf.type == 'error_leaf':
                return
        if search_ancestor(node, 'error_node') is not None:
            return
        if code in (901, 903):
            # 901 and 903 are raised by the ErrorFinder.
            super(PEP8Normalizer, self).add_issue(node, code, message)
        else:
            # Skip ErrorFinder here, because it has custom behavior.
            super(ErrorFinder, self).add_issue(node, code, message)


class PEP8NormalizerConfig(ErrorFinderConfig):
    normalizer_class = PEP8Normalizer
    """
    Normalizing to PEP8. Not really implemented, yet.
    """
    def __init__(self, indentation=' ' * 4, hanging_indentation=None,
                 max_characters=79, spaces_before_comment=2):
        self.indentation = indentation
        if hanging_indentation is None:
            hanging_indentation = indentation
        self.hanging_indentation = hanging_indentation
        self.closing_bracket_hanging_indentation = ''
        self.break_after_binary = False
        self.max_characters = max_characters
        self.spaces_before_comment = spaces_before_comment


# TODO this is not yet ready.
#@PEP8Normalizer.register_rule(type='endmarker')
class BlankLineAtEnd(Rule):
    code = 392
    message = 'Blank line at end of file'

    def is_issue(self, leaf):
        return self._newline_count >= 2

Web Proxy Viewer  |  New URL  |  Original Page