From 141947f071cf91b2bfa90a46da36174081ef1587 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Fri, 19 Jul 2019 13:42:04 -0700 Subject: [PATCH] In PEP 484 type comments, allow text after "# type: ignore" This is to support allowing typecheckers to implement ignores for specific errors, using syntax like `# type: ignore=E1000` or `# type: ignore[type-mismatch` or some such. mypy is about to add support for ignoring specific errors following this design: https://github.com/python/mypy/issues/7239 Support for extra text in type comments was implemented in CPython as https://bugs.python.org/issue36878 and in typed_ast as https://github.com/python/typed_ast/pull/116. --- pyflakes/checker.py | 9 +++++---- pyflakes/test/test_type_annotations.py | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pyflakes/checker.py b/pyflakes/checker.py index acc2ae74..7aa10747 100644 --- a/pyflakes/checker.py +++ b/pyflakes/checker.py @@ -73,11 +73,12 @@ def getAlternatives(n): FOR_TYPES = (ast.For,) LOOP_TYPES = (ast.While, ast.For) -# https://github.com/python/typed_ast/blob/55420396/ast27/Parser/tokenizer.c#L102-L104 +# https://github.com/python/typed_ast/blob/1.4.0/ast27/Parser/tokenizer.c#L102-L104 TYPE_COMMENT_RE = re.compile(r'^#\s*type:\s*') -# https://github.com/python/typed_ast/blob/55420396/ast27/Parser/tokenizer.c#L1400 -TYPE_IGNORE_RE = re.compile(TYPE_COMMENT_RE.pattern + r'ignore\s*(#|$)') -# https://github.com/python/typed_ast/blob/55420396/ast27/Grammar/Grammar#L147 +# https://github.com/python/typed_ast/blob/1.4.0/ast27/Parser/tokenizer.c#L1408-L1413 +ASCII_NON_ALNUM = ''.join([chr(i) for i in range(128) if not chr(i).isalnum()]) +TYPE_IGNORE_RE = re.compile(TYPE_COMMENT_RE.pattern + r'ignore([{}]|$)'.format(ASCII_NON_ALNUM)) +# https://github.com/python/typed_ast/blob/1.4.0/ast27/Grammar/Grammar#L147 TYPE_FUNC_RE = re.compile(r'^(\(.*?\))\s*->\s*(.*)$') diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py index 9c34dcfd..3d5a4581 100644 --- a/pyflakes/test/test_type_annotations.py +++ b/pyflakes/test/test_type_annotations.py @@ -343,6 +343,26 @@ def test_typeCommentsAssignedToPreviousNode(self): # type: F """) + def test_typeIgnore(self): + self.flakes(""" + a = 0 # type: ignore + b = 0 # type: ignore[excuse] + c = 0 # type: ignore=excuse + d = 0 # type: ignore [excuse] + e = 0 # type: ignore whatever + """) + + def test_typeIgnoreBogus(self): + self.flakes(""" + x = 1 # type: ignored + """, m.UndefinedName) + + def test_typeIgnoreBogusUnicode(self): + error = m.CommentAnnotationSyntaxError if version_info < (3,) else m.UndefinedName + self.flakes(""" + x = 2 # type: ignore\xc3 + """, error) + @skipIf(version_info < (3,), 'new in Python 3') def test_return_annotation_is_class_scope_variable(self): self.flakes("""