From 904f2938300abaf4194dc9e86873965f96d3e0e1 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 18 Aug 2017 18:15:24 +0200 Subject: [PATCH] Move annassign and starexprs. --- parso/python/errors.py | 124 ++++++++++++---------- parso/python/pep8.py | 3 +- test/normalizer_issue_files/E12_second.py | 2 +- 3 files changed, 72 insertions(+), 57 deletions(-) diff --git a/parso/python/errors.py b/parso/python/errors.py index c27d94b..965cf4a 100644 --- a/parso/python/errors.py +++ b/parso/python/errors.py @@ -343,29 +343,6 @@ class ErrorFinder(Normalizer): if count >= 256: message = "too many expressions in star-unpacking assignment" self._add_syntax_error(message, starred[0]) - elif node.type == 'star_expr': - if node.parent.type not in _STAR_EXPR_PARENTS: - message = "starred assignment target must be in a list or tuple" - self._add_syntax_error(message, node) - if node.parent.type == 'testlist_comp': - # [*[] for a in [1]] - if node.parent.children[1].type == 'comp_for': - message = "iterable unpacking cannot be used in comprehension" - self._add_syntax_error(message, node) - if self.version <= (3, 4): - n = search_ancestor(node, 'for_stmt', 'expr_stmt') - found_definition = False - if n is not None: - if n.type == 'expr_stmt': - exprs = _get_expr_stmt_definition_exprs(n) - else: - exprs = _get_for_stmt_definition_exprs(n) - if node in exprs: - found_definition = True - - if not found_definition: - message = "can use starred expression only as assignment target" - self._add_syntax_error(message, node) elif node.type == 'comp_for': # Some of the nodes here are already used, so no else if expr_list = node.children[1 + int(node.children[0] == 'async')] @@ -448,35 +425,6 @@ class ErrorFinder(Normalizer): self._add_syntax_error(message, node) else: default_only = True - elif node.type == 'annassign': - # x, y: str - type_ = None - message = "only single target (not %s) can be annotated" - lhs = node.parent.children[0] - lhs = _remove_parens(lhs) - try: - children = lhs.children - except AttributeError: - pass - else: - if ',' in children or lhs.type == 'atom' and children[0] == '(': - type_ = 'tuple' - elif lhs.type == 'atom' and children[0] == '[': - type_ = 'list' - trailer = children[-1] - - if type_ is None: - if not (lhs.type == 'name' - # subscript/attributes are allowed - or lhs.type in ('atom_expr', 'power') - and trailer.type == 'trailer' - and trailer.children[0] != '('): - # True: int - # {}: float - message = "illegal target for annotation" - self._add_syntax_error(message, lhs.parent) - else: - self._add_syntax_error(message % type_, lhs.parent) elif node.type == 'argument': first = node.children[0] if node.children[1] == '=' and first.type != 'name': @@ -622,12 +570,13 @@ class ErrorFinder(Normalizer): self._add_syntax_error(message, node) def _add_indentation_error(self, message, spacing): - self._add_error(903, "IndentationError: " + message, spacing) + self.add_issue(spacing, 903, "IndentationError: " + message) def _add_syntax_error(self, message, node): - self._add_error(901, "SyntaxError: " + message, node) + self.add_issue(node, 901, "SyntaxError: " + message) - def _add_error(self, code, message, node): + def add_issue(self, node, code, message): + # Overwrite the default behavior. # Check if the issues are on the same line. line = node.start_pos[0] args = (code, message, node) @@ -874,3 +823,68 @@ class FutureImportRule(SyntaxRule): elif name not in ALLOWED_FUTURES: message = "future feature %s is not defined" % name self.add_issue(node, message=message) + + +@ErrorFinder.register_rule(type='star_expr') +class StarExprRule(SyntaxRule): + message = "starred assignment target must be in a list or tuple" + message_iterable_unpacking = "iterable unpacking cannot be used in comprehension" + message_assignment = "can use starred expression only as assignment target" + + def is_issue(self, node): + if node.parent.type not in _STAR_EXPR_PARENTS: + return True + if node.parent.type == 'testlist_comp': + # [*[] for a in [1]] + if node.parent.children[1].type == 'comp_for': + self.add_issue(node, message=self.message_iterable_unpacking) + if self._normalizer.version <= (3, 4): + n = search_ancestor(node, 'for_stmt', 'expr_stmt') + found_definition = False + if n is not None: + if n.type == 'expr_stmt': + exprs = _get_expr_stmt_definition_exprs(n) + else: + exprs = _get_for_stmt_definition_exprs(n) + if node in exprs: + found_definition = True + + if not found_definition: + self.add_issue(node, message=self.message_assignment) + + +@ErrorFinder.register_rule(type='annassign') +class AnnassignRule(SyntaxRule): + # True: int + # {}: float + message = "illegal target for annotation" + + def get_node(self, node): + return node.parent + + def is_issue(self, node): + type_ = None + lhs = node.parent.children[0] + lhs = _remove_parens(lhs) + try: + children = lhs.children + except AttributeError: + pass + else: + if ',' in children or lhs.type == 'atom' and children[0] == '(': + type_ = 'tuple' + elif lhs.type == 'atom' and children[0] == '[': + type_ = 'list' + trailer = children[-1] + + if type_ is None: + if not (lhs.type == 'name' + # subscript/attributes are allowed + or lhs.type in ('atom_expr', 'power') + and trailer.type == 'trailer' + and trailer.children[0] != '('): + return True + else: + # x, y: str + message = "only single target (not %s) can be annotated" + self.add_issue(lhs.parent, message=message % type_) diff --git a/parso/python/pep8.py b/parso/python/pep8.py index ba11e10..816c3d1 100644 --- a/parso/python/pep8.py +++ b/parso/python/pep8.py @@ -692,7 +692,8 @@ class PEP8Normalizer(ErrorFinder): return if search_ancestor(node, 'error_node') is not None: return - super(PEP8Normalizer, self).add_issue(node, code, message) + # Skip ErrorFinder here, because it has custom behavior. + super(ErrorFinder, self).add_issue(node, code, message) class PEP8NormalizerConfig(ErrorFinderConfig): diff --git a/test/normalizer_issue_files/E12_second.py b/test/normalizer_issue_files/E12_second.py index f238e12..5488ea4 100644 --- a/test/normalizer_issue_files/E12_second.py +++ b/test/normalizer_issue_files/E12_second.py @@ -23,7 +23,7 @@ if True: or another_very_long_variable_name: raise Exception() -#: E901+1:8 E901+5 +#: E901+1:8 dictionary = [ "is": { # Might be a E122:4, but is not because the code is invalid Python.