Skip to content

Commit f33c922

Browse files
committed
Add optional error code
1 parent 88dd26a commit f33c922

File tree

6 files changed

+99
-9
lines changed

6 files changed

+99
-9
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ necessary.
3232
Contributed by Marc Mueller (PR [20410](https://github.com/python/mypy/pull/20410))
3333
and (PR [20405](https://github.com/python/mypy/pull/20405)).
3434

35+
### Added optional error code `type-comment`
36+
37+
A new disabled by default error code `type-comment` was added. If enabled with
38+
`--enable-error-code type-comment`, mypy will generate errors if legacy type comments instead of
39+
type annotations are used.
40+
41+
```py
42+
a = 2 # type: int
43+
a: int = 2
44+
45+
def func(a, b):
46+
# type: (int, str) -> bool
47+
...
48+
49+
def func(a: int, b: str) -> bool:
50+
...
51+
```
52+
53+
Contributed by Marc Mueller (PR [20616](https://github.com/python/mypy/pull/20616)).
54+
3555
## Mypy 1.19
3656

3757
We’ve just uploaded mypy 1.19.0 to the Python Package Index ([PyPI](https://pypi.org/project/mypy/)).

docs/source/error_code_list2.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,29 @@ Example:
699699
@printing_decorator # E: Untyped decorator makes function "add_forty_two" untyped [untyped-decorator]
700700
def add_forty_two(value: int) -> int:
701701
return value + 42
702+
703+
.. _code-type-comment:
704+
705+
Check that no legacy type comments are used [type-comment]
706+
----------------------------------------------------------
707+
708+
If enabled with :option:`--enable-error-code type-comment <mypy --enable-error-code>`,
709+
mypy generates an error if legacy type comments are used. Tools like
710+
[com2ann](https://github.com/ilevkivskyi/com2ann) can help with translating type comments to
711+
type annotations.
712+
713+
More information about type comments are available in the
714+
[typing specification](https://typing.python.org/en/latest/spec/historical.html#type-comments).
715+
716+
Example:
717+
718+
.. code-block:: python
719+
720+
o = 2 # type: int
721+
722+
for x, y in points: # type: float, float
723+
...
724+
725+
def func(a, b):
726+
# type: (str, int) -> bool
727+
...

mypy/errorcodes.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ def __hash__(self) -> int:
280280
"Error when a string is used where a TypeForm is expected but a string annotation cannot be recognized",
281281
"General",
282282
)
283+
TYPE_COMMENT: Final = ErrorCode(
284+
"type-comment",
285+
"Error when legacy type comments are used instead of type annotations",
286+
"General",
287+
default_enabled=False,
288+
)
283289

284290
# Syntax errors are often blocking.
285291
SYNTAX: Final = ErrorCode("syntax", "Report syntax errors", "General")

mypy/fastparse.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ def do_func_def(
928928
return_type = None
929929
elif n.type_comment is not None:
930930
self.fail(
931-
message_registry.TYPE_COMMENT_DEPRECATED, lineno, n.col_offset, blocker=False
931+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED, lineno, n.col_offset, blocker=False
932932
)
933933
try:
934934
func_type_ast = ast3_parse(n.type_comment, "<func_type>", "func_type")
@@ -1143,7 +1143,7 @@ def make_argument(
11431143
arg_type = TypeConverter(self.errors, line=arg.lineno).visit(annotation)
11441144
elif type_comment is not None:
11451145
self.fail(
1146-
message_registry.TYPE_COMMENT_DEPRECATED,
1146+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED,
11471147
arg.lineno,
11481148
arg.col_offset,
11491149
blocker=False,
@@ -1277,7 +1277,10 @@ def visit_Assign(self, n: ast3.Assign) -> AssignmentStmt:
12771277
rvalue = self.visit(n.value)
12781278
if n.type_comment is not None:
12791279
self.fail(
1280-
message_registry.TYPE_COMMENT_DEPRECATED, n.lineno, n.col_offset, blocker=False
1280+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED,
1281+
n.lineno,
1282+
n.col_offset,
1283+
blocker=False,
12811284
)
12821285
typ = self.translate_type_comment(n, n.type_comment)
12831286
s = AssignmentStmt(lvalues, rvalue, type=typ, new_syntax=False)
@@ -1308,7 +1311,10 @@ def visit_AugAssign(self, n: ast3.AugAssign) -> OperatorAssignmentStmt:
13081311
def visit_For(self, n: ast3.For) -> ForStmt:
13091312
if n.type_comment is not None:
13101313
self.fail(
1311-
message_registry.TYPE_COMMENT_DEPRECATED, n.lineno, n.col_offset, blocker=False
1314+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED,
1315+
n.lineno,
1316+
n.col_offset,
1317+
blocker=False,
13121318
)
13131319
target_type = self.translate_type_comment(n, n.type_comment)
13141320
node = ForStmt(
@@ -1324,7 +1330,10 @@ def visit_For(self, n: ast3.For) -> ForStmt:
13241330
def visit_AsyncFor(self, n: ast3.AsyncFor) -> ForStmt:
13251331
if n.type_comment is not None:
13261332
self.fail(
1327-
message_registry.TYPE_COMMENT_DEPRECATED, n.lineno, n.col_offset, blocker=False
1333+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED,
1334+
n.lineno,
1335+
n.col_offset,
1336+
blocker=False,
13281337
)
13291338
target_type = self.translate_type_comment(n, n.type_comment)
13301339
node = ForStmt(
@@ -1355,7 +1364,10 @@ def visit_If(self, n: ast3.If) -> IfStmt:
13551364
def visit_With(self, n: ast3.With) -> WithStmt:
13561365
if n.type_comment is not None:
13571366
self.fail(
1358-
message_registry.TYPE_COMMENT_DEPRECATED, n.lineno, n.col_offset, blocker=False
1367+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED,
1368+
n.lineno,
1369+
n.col_offset,
1370+
blocker=False,
13591371
)
13601372
target_type = self.translate_type_comment(n, n.type_comment)
13611373
node = WithStmt(
@@ -1370,7 +1382,10 @@ def visit_With(self, n: ast3.With) -> WithStmt:
13701382
def visit_AsyncWith(self, n: ast3.AsyncWith) -> WithStmt:
13711383
if n.type_comment is not None:
13721384
self.fail(
1373-
message_registry.TYPE_COMMENT_DEPRECATED, n.lineno, n.col_offset, blocker=False
1385+
message_registry.TYPE_COMMENT_SOFT_DEPRECATED,
1386+
n.lineno,
1387+
n.col_offset,
1388+
blocker=False,
13741389
)
13751390
target_type = self.translate_type_comment(n, n.type_comment)
13761391
s = WithStmt(

mypy/message_registry.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,9 @@ def with_additional_msg(self, info: str) -> ErrorMessage:
311311
TYPE_COMMENT_SYNTAX_ERROR_VALUE: Final = ErrorMessage(
312312
'Syntax error in type comment "{}"', codes.SYNTAX
313313
)
314-
TYPE_COMMENT_DEPRECATED: Final = ErrorMessage(
315-
"Using type comments with mypy is deprecated, use inline annotations instead", codes.MISC
314+
TYPE_COMMENT_SOFT_DEPRECATED: Final = ErrorMessage(
315+
"Using type comments with mypy is (soft-)deprecated, use inline annotations instead",
316+
codes.TYPE_COMMENT,
316317
)
317318
ELLIPSIS_WITH_OTHER_TYPEPARAMS: Final = ErrorMessage(
318319
"Ellipses cannot accompany other parameter types in function type signature", codes.SYNTAX

test-data/unit/check-errorcodes.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,3 +1335,25 @@ def process(response1: int,response2: int) -> int: # E: Overloaded function sign
13351335

13361336
def process(response1,response2)-> Union[float,int]:
13371337
return response1 + response2
1338+
1339+
[case testLegacyTypeComments]
1340+
# flags: --enable-error-code type-comment
1341+
a = 2 # type: int # E: Using type comments with mypy is (soft-)deprecated, use inline annotations instead [type-comment]
1342+
1343+
for b in (): # type: int # E: Using type comments with mypy is (soft-)deprecated, use inline annotations instead [type-comment]
1344+
...
1345+
1346+
with f() as foo: # type: int # type: ignore[name-defined] # E: Using type comments with mypy is (soft-)deprecated, use inline annotations instead [type-comment]
1347+
...
1348+
1349+
def func(d, e): # E: Using type comments with mypy is (soft-)deprecated, use inline annotations instead [type-comment]
1350+
# type: (str, int) -> bool
1351+
...
1352+
1353+
async def func2(): # E: Using type comments with mypy is (soft-)deprecated, use inline annotations instead [type-comment]
1354+
# type: () -> None
1355+
1356+
async for c in g(): # type: int # type: ignore[name-defined] # E: Using type comments with mypy is (soft-)deprecated, use inline annotations instead [type-comment]
1357+
...
1358+
1359+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)