From 6085c91df17dd85f45394027f16aca37e56d4bc5 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 25 Jul 2017 00:38:27 +0200 Subject: [PATCH] Some issues regarding annotations. --- parso/python/normalizer.py | 44 +++++++++++++++++++ test/normalizer_issue_files/allowed_syntax.py | 6 +++ test/test_python_errors.py | 11 +++++ 3 files changed, 61 insertions(+) diff --git a/parso/python/normalizer.py b/parso/python/normalizer.py index 02b83a9..7f10838 100644 --- a/parso/python/normalizer.py +++ b/parso/python/normalizer.py @@ -33,6 +33,21 @@ def _is_future_import(import_from): return [n.value for n in from_names] == ['__future__'] +def _remove_parens(atom): + """ + Returns the inner part of an expression like `(foo)`. Also removes nested + parens. + """ + try: + children = atom.children + except AttributeError: + pass + else: + if len(children) == 3 and children[0] == '(': + return _remove_parens(atom.children[1]) + return atom + + def _iter_params(parent_node): return (n for n in parent_node.children if n.type == 'param') @@ -187,6 +202,35 @@ 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) yield diff --git a/test/normalizer_issue_files/allowed_syntax.py b/test/normalizer_issue_files/allowed_syntax.py index 032715d..2736d13 100644 --- a/test/normalizer_issue_files/allowed_syntax.py +++ b/test/normalizer_issue_files/allowed_syntax.py @@ -9,6 +9,12 @@ from __future__ import division ''r''u'' b'' BR'' +foo: int = 4 +(foo): int = 3 +((foo)): int = 3 +foo.bar: int +foo[3]: int + for x in [1]: try: continue # Only the other continue and pass is an error. diff --git a/test/test_python_errors.py b/test/test_python_errors.py index 818a41e..d1521b6 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -79,6 +79,17 @@ def test_indentation_errors(code, positions): #'(True,) = x', #'([False], a) = x', #'__debug__ = 1' + # Mostly 3.6 relevant + '[]: int', + '[a, b]: int', + '(): int', + '(()): int', + '((())): int', + '{}: int', + 'True: int', + '(a, b): int', + '*star,: int', + 'a, b: int = 3', # IndentationError ' foo',