Skip to content

Commit

Permalink
In PEP 484 type comments, allow text after "# type: ignore"
Browse files Browse the repository at this point in the history
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: python/mypy#7239

Support for extra text in type comments was implemented
in CPython as https://bugs.python.org/issue36878
and in typed_ast as python/typed_ast#116.
  • Loading branch information
msullivan committed Jul 19, 2019
1 parent c0193b2 commit e6905ee
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 8 deletions.
9 changes: 5 additions & 4 deletions pyflakes/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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*(.*)$')


Expand Down
4 changes: 0 additions & 4 deletions pyflakes/test/test_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,6 @@ def test_type_comment_without_whitespace(self):
ret = self._collect('x = 1 #type:int')
self.assertSetEqual(ret, {(ast.Assign, ('#type:int',))})

def test_type_comment_starts_with_word_ignore(self):
ret = self._collect('x = 1 # type: ignore[T]')
self.assertSetEqual(ret, {(ast.Assign, ('# type: ignore[T]',))})

def test_last_node_wins(self):
"""
Test that when two typeable nodes are present on a line, the last
Expand Down
20 changes: 20 additions & 0 deletions pyflakes/test/test_type_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("""
Expand Down

0 comments on commit e6905ee

Please sign in to comment.