From 766d4e7c95816b286964faee0c46131aec7b21c6 Mon Sep 17 00:00:00 2001 From: Charulata <11500589+charulatalodha@users.noreply.github.com> Date: Mon, 19 May 2025 13:33:46 -0400 Subject: [PATCH 01/12] syntax error messages capitalization --- mypy/fastparse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index aed04c6f2eb9..652bc7d4b3d5 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -263,7 +263,7 @@ def parse( raise e except SyntaxError as e: - message = e.msg + message = e.msg.capitalize() if feature_version > sys.version_info.minor and message.startswith("invalid syntax"): python_version_str = f"{options.python_version[0]}.{options.python_version[1]}" message += f"; you likely need to run mypy using Python {python_version_str} or newer" From c48241d4e90c63d2c17ca1023f1ef31c912319fa Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Mon, 19 May 2025 14:55:08 -0400 Subject: [PATCH 02/12] Capitalise only first non space word in syntax err msg --- mypy/fastparse.py | 4 +- mypy/test/teststubtest.py | 2 +- test-data/unit/check-basic.test | 2 +- test-data/unit/check-columns.test | 2 +- test-data/unit/check-errorcodes.test | 4 +- test-data/unit/check-expressions.test | 2 +- test-data/unit/check-fastparse.test | 4 +- test-data/unit/check-ignore.test | 4 +- test-data/unit/check-newsyntax.test | 4 +- test-data/unit/check-statements.test | 2 +- test-data/unit/cmdline.test | 8 +-- test-data/unit/fine-grained-blockers.test | 76 +++++++++++------------ test-data/unit/parse-errors.test | 56 ++++++++--------- test-data/unit/parse.test | 12 ++-- test-data/unit/semanal-errors.test | 58 ++++++++--------- test-data/unit/semanal-statements.test | 4 +- 16 files changed, 122 insertions(+), 122 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 652bc7d4b3d5..a119e357b944 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -263,14 +263,14 @@ def parse( raise e except SyntaxError as e: - message = e.msg.capitalize() + message = e.msg if feature_version > sys.version_info.minor and message.startswith("invalid syntax"): python_version_str = f"{options.python_version[0]}.{options.python_version[1]}" message += f"; you likely need to run mypy using Python {python_version_str} or newer" errors.report( e.lineno if e.lineno is not None else -1, e.offset, - message, + re.sub(r"^(\s*\w)", lambda m: m.group(1).upper(), message), blocker=True, code=codes.SYNTAX, ) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 492897d33a4a..7925f2a6bd3e 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -2581,7 +2581,7 @@ def test_mypy_build(self) -> None: output = run_stubtest(stub="+", runtime="", options=[]) assert output == ( "error: not checking stubs due to failed mypy compile:\n{}.pyi:1: " - "error: invalid syntax [syntax]\n".format(TEST_MODULE_NAME) + "error: Invalid syntax [syntax]\n".format(TEST_MODULE_NAME) ) output = run_stubtest(stub="def f(): ...\ndef f(): ...", runtime="", options=[]) diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index 6ecbbdcc13eb..3f2164bf5a24 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -289,7 +289,7 @@ x in 1, # E: Unsupported right operand type for in ("int") [case testTrailingCommaInIfParsing] if x in 1, : pass [out] -main:1: error: invalid syntax +main:1: error: Invalid syntax [case testInitReturnTypeError] class C: diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 8f91d99a0576..c18313bbc24f 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -4,7 +4,7 @@ f() 1 + [out] -main:2:5: error: invalid syntax +main:2:5: error: Invalid syntax [case testColumnsNestedFunctions] import typing diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 21112b7d85a2..0cd6dc081629 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -33,9 +33,9 @@ reveal_type(1) # N: Revealed type is "Literal[1]?" [case testErrorCodeSyntaxError] 1 '' [out] -main:1: error: invalid syntax [syntax] +main:1: error: Invalid syntax [syntax] [out version==3.10.0] -main:1: error: invalid syntax. Perhaps you forgot a comma? [syntax] +main:1: error: Invalid syntax. Perhaps you forgot a comma? [syntax] [case testErrorCodeSyntaxError2] def f(): # E: Type signature has too many arguments [syntax] diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 81eb4c7c0dc8..a3b15a3b1da4 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1861,7 +1861,7 @@ None < None # E: Unsupported left operand type for < ("None") [case testDictWithStarExpr] -b = {'z': 26, *a} # E: invalid syntax +b = {'z': 26, *a} # E: Invalid syntax [builtins fixtures/dict.pyi] [case testDictWithStarStarExpr] diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index f93e4fe07218..80d314333ddc 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -1,6 +1,6 @@ [case testFastParseSyntaxError] -1 + # E: invalid syntax +1 + # E: Invalid syntax [case testFastParseTypeCommentSyntaxError] @@ -158,7 +158,7 @@ def f(a, # type: A [case testFastParsePerArgumentAnnotationsWithAnnotatedBareStar] -def f(*, # type: int # E: bare * has associated type comment +def f(*, # type: int # E: Bare * has associated type comment x # type: str ): # type: (...) -> int diff --git a/test-data/unit/check-ignore.test b/test-data/unit/check-ignore.test index fa451f373e70..a4234e7a37a1 100644 --- a/test-data/unit/check-ignore.test +++ b/test-data/unit/check-ignore.test @@ -38,7 +38,7 @@ from m import a # type: ignore [file m.py] + [out] -tmp/m.py:1: error: invalid syntax +tmp/m.py:1: error: Invalid syntax [case testIgnoreAppliesOnlyToMissing] import a # type: ignore @@ -59,7 +59,7 @@ from m import * # type: ignore [file m.py] + [out] -tmp/m.py:1: error: invalid syntax +tmp/m.py:1: error: Invalid syntax [case testIgnoreAssignmentTypeError] x = 1 diff --git a/test-data/unit/check-newsyntax.test b/test-data/unit/check-newsyntax.test index 3ed4c6d3d8e2..a696eb2932fe 100644 --- a/test-data/unit/check-newsyntax.test +++ b/test-data/unit/check-newsyntax.test @@ -1,5 +1,5 @@ [case testNewSyntaxSyntaxError] -x: int: int # E: invalid syntax +x: int: int # E: Invalid syntax [out] [case testNewSyntaxBasics] @@ -126,4 +126,4 @@ reveal_type(f'{1}') # N: Revealed type is "builtins.str" # flags: --python-version 3.99 x *** x this is what future python looks like public static void main String[] args await goto exit [out] -main:2: error: invalid syntax; you likely need to run mypy using Python 3.99 or newer +main:2: error: Invalid syntax; you likely need to run mypy using Python 3.99 or newer diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index 9f77100863be..b0b673f696e1 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -1311,7 +1311,7 @@ def f() -> Iterator[List[int]]: [case testYieldFromNotAppliedToNothing] def h(): - yield from # E: invalid syntax + yield from # E: Invalid syntax [out] [case testYieldFromAndYieldTogether] diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 748a655d5a10..fb2e0c01fe0e 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -896,7 +896,7 @@ some_file.py:11: error: Argument 1 to "some_interesting_method" of [file some_file.py] it_looks_like_we_started_typing_something_but_then. = did_not_notice(an_extra_dot) [out] -some_file.py:1: error: invalid syntax [syntax] +some_file.py:1: error: Invalid syntax [syntax] ...ooks_like_we_started_typing_something_but_then. = did_not_notice(an_ex... ^ == Return code: 2 @@ -1035,15 +1035,15 @@ public static void main(String[] args) [file pkg/y.py] x: str = 0 [out] -pkg/x.py:1: error: invalid syntax +pkg/x.py:1: error: Invalid syntax Found 1 error in 1 file (errors prevented further checking) == Return code: 2 [out version>=3.10] -pkg/x.py:1: error: invalid syntax. Perhaps you forgot a comma? +pkg/x.py:1: error: Invalid syntax. Perhaps you forgot a comma? Found 1 error in 1 file (errors prevented further checking) == Return code: 2 [out version>=3.10.3] -pkg/x.py:1: error: invalid syntax +pkg/x.py:1: error: Invalid syntax Found 1 error in 1 file (errors prevented further checking) == Return code: 2 diff --git a/test-data/unit/fine-grained-blockers.test b/test-data/unit/fine-grained-blockers.test index 33dedd887114..8e16da053d6a 100644 --- a/test-data/unit/fine-grained-blockers.test +++ b/test-data/unit/fine-grained-blockers.test @@ -19,13 +19,13 @@ def f(x: int) -> None: pass def f() -> None: pass [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == main:2: error: Missing positional argument "x" in call to "f" == [out version>=3.10] == -a.py:1: error: expected ':' +a.py:1: error: Expected ':' == main:2: error: Missing positional argument "x" in call to "f" == @@ -44,7 +44,7 @@ def f(x: int) -> None: pass def f() -> None: pass [out] == -a.py:1: error: invalid syntax [syntax] +a.py:1: error: Invalid syntax [syntax] def f(x: int) -> ^ == @@ -54,7 +54,7 @@ main:3: error: Missing positional argument "x" in call to "f" [call-arg] == [out version>=3.10] == -a.py:1: error: expected ':' [syntax] +a.py:1: error: Expected ':' [syntax] def f(x: int) -> ^ == @@ -77,16 +77,16 @@ def f(x: int def f(x: int) -> None: pass [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == -a.py:2: error: invalid syntax +a.py:2: error: Invalid syntax == main:2: error: Missing positional argument "x" in call to "f" [out version>=3.10] == -a.py:1: error: expected ':' +a.py:1: error: Expected ':' == -a.py:2: error: expected ':' +a.py:2: error: Expected ':' == main:2: error: Missing positional argument "x" in call to "f" @@ -124,7 +124,7 @@ def f() -> None: pass main:3: error: Too many arguments for "f" main:5: error: Too many arguments for "f" == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == main:3: error: Too many arguments for "f" main:5: error: Too many arguments for "f" @@ -132,7 +132,7 @@ main:5: error: Too many arguments for "f" main:3: error: Too many arguments for "f" main:5: error: Too many arguments for "f" == -a.py:1: error: expected ':' +a.py:1: error: Expected ':' == main:3: error: Too many arguments for "f" main:5: error: Too many arguments for "f" @@ -153,12 +153,12 @@ class C: def f(self, x: int) -> None: pass [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == main:5: error: Missing positional argument "x" in call to "f" of "C" [out version==3.10.0] == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == main:5: error: Missing positional argument "x" in call to "f" of "C" @@ -173,14 +173,14 @@ def f() -> None: pass main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == main:2: error: Too many arguments for "f" [out version==3.10.0] main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == main:2: error: Too many arguments for "f" @@ -208,7 +208,7 @@ a.f() def g() -> None: pass [out] == -b.py:1: error: invalid syntax +b.py:1: error: Invalid syntax == [case testModifyTwoFilesOneWithBlockingError2] @@ -235,7 +235,7 @@ def f() -> None: pass b.g() [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == [case testBlockingErrorRemainsUnfixed] @@ -254,16 +254,16 @@ import b b.f() [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == a.py:2: error: Missing positional argument "x" in call to "f" [out version==3.10.0] == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == a.py:2: error: Missing positional argument "x" in call to "f" @@ -303,9 +303,9 @@ def g() -> None: pass a.f(1) [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == a.py:3: error: Too many arguments for "g" b.py:3: error: Too many arguments for "f" @@ -325,14 +325,14 @@ x x [delete a.py.3] [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports b.py:1: error: Cannot find implementation or library stub for module named "a" [out version==3.10.0] == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == main:1: error: Cannot find implementation or library stub for module named "a" main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports @@ -353,14 +353,14 @@ x x [delete a.py.3] [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == b.py:1: error: Cannot find implementation or library stub for module named "a" b.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports main:1: error: Cannot find implementation or library stub for module named "a" [out version==3.10.0] == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == b.py:1: error: Cannot find implementation or library stub for module named "a" b.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports @@ -382,17 +382,17 @@ a.f() [builtins fixtures/module.pyi] [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == b.py:2: error: Module has no attribute "f" b.py:3: error: "int" not callable [out version==3.10.0] == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == b.py:2: error: Module has no attribute "f" b.py:3: error: "int" not callable @@ -408,12 +408,12 @@ import blocker def f() -> None: pass [out] == -/test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax +/test-data/unit/lib-stub/blocker.pyi:2: error: Invalid syntax == a.py:1: error: "int" not callable [out version==3.10.0] == -/test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax. Perhaps you forgot a comma? +/test-data/unit/lib-stub/blocker.pyi:2: error: Invalid syntax. Perhaps you forgot a comma? == a.py:1: error: "int" not callable @@ -485,16 +485,16 @@ import sys [builtins fixtures/tuple.pyi] [out] == -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == -/test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax +/test-data/unit/lib-stub/blocker.pyi:2: error: Invalid syntax == a.py:2: error: "int" not callable [out version==3.10.0] == -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == -/test-data/unit/lib-stub/blocker.pyi:2: error: invalid syntax. Perhaps you forgot a comma? +/test-data/unit/lib-stub/blocker.pyi:2: error: Invalid syntax. Perhaps you forgot a comma? == a.py:2: error: "int" not callable @@ -511,12 +511,12 @@ x = 1 def f() -> int: return 0 [out] -a.py:1: error: invalid syntax +a.py:1: error: Invalid syntax == b.py:2: error: Incompatible return value type (got "str", expected "int") == [out version==3.10.0] -a.py:1: error: invalid syntax. Perhaps you forgot a comma? +a.py:1: error: Invalid syntax. Perhaps you forgot a comma? == b.py:2: error: Incompatible return value type (got "str", expected "int") == diff --git a/test-data/unit/parse-errors.test b/test-data/unit/parse-errors.test index 33c2a6ddf5c0..4ebcd358fa68 100644 --- a/test-data/unit/parse-errors.test +++ b/test-data/unit/parse-errors.test @@ -12,7 +12,7 @@ def f() pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testUnexpectedIndent] 1 @@ -39,18 +39,18 @@ file:3: error: unindent does not match any outer indentation level a* a+1* [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testDoubleStar] **a [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testMissingSuperClass] class A(: pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testUnexpectedEof] if 1: @@ -70,12 +70,12 @@ file:1: error: positional argument follows keyword argument unpacking [case testInvalidBareAsteriskAndVarArgs2] def f(*x: A, *) -> None: pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidBareAsteriskAndVarArgs3] def f(*, *x: A) -> None: pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidBareAsteriskAndVarArgs4] def f(*, **x: A) -> None: pass @@ -101,13 +101,13 @@ file:1: error: non-default argument follows default argument def f(**x, y): pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidFuncDefArgs4] def f(**x, y=x): pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidTypeComment] 0 @@ -288,76 +288,76 @@ file:1: error: Missing parentheses in call to 'print'. Did you mean print(1)? [case testInvalidConditionInConditionalExpression] 1 if 2, 3 else 4 [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidConditionInConditionalExpression2] 1 if x for y in z else 4 [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidConditionInConditionalExpression3] 1 if x else for y in z [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testYieldFromNotRightParameter] def f(): yield from [out] -file:2: error: invalid syntax +file:2: error: Invalid syntax [case testYieldFromAfterReturn] def f(): return yield from h() [out] -file:2: error: invalid syntax +file:2: error: Invalid syntax [case testImportDotModule] import .x [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testImportDot] import . [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidFunctionName] def while(): pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testInvalidEllipsis1] ...0 ..._ ...a [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testBlockStatementInSingleLineIf] if 1: if 2: pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testBlockStatementInSingleLineIf2] if 1: while 2: pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testBlockStatementInSingleLineIf3] if 1: for x in y: pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testUnexpectedEllipsis] a = a... [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testParseErrorBeforeUnicodeLiteral] x u'y' [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testParseErrorInExtendedSlicing] x[:, @@ -409,27 +409,27 @@ file:0: error: unknown encoding: uft8 2L 0x2L [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testPython2LegacyInequalityInPython3] 1 <> 2 [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testLambdaInListComprehensionInPython3] ([ 0 for x in 1, 2 if 3 ]) [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testTupleArgListInPython3] def f(x, (y, z)): pass [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testBackquoteInPython3] `1 + 2` [out] -file:1: error: invalid syntax +file:1: error: Invalid syntax [case testSmartQuotes] foo = ‘bar’ @@ -442,4 +442,4 @@ try: except KeyError, IndexError: pass [out] -file:3: error: invalid syntax +file:3: error: Invalid syntax diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index 943ca49081f1..fa1d797fada4 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -932,20 +932,20 @@ MypyFile:1( [case testNotAsBinaryOp] x not y [out] -main:1: error: invalid syntax +main:1: error: Invalid syntax [out version==3.10.0] -main:1: error: invalid syntax. Perhaps you forgot a comma? +main:1: error: Invalid syntax. Perhaps you forgot a comma? [case testNotIs] -x not is y # E: invalid syntax +x not is y # E: Invalid syntax [out] [case testBinaryNegAsBinaryOp] 1 ~ 2 [out] -main:1: error: invalid syntax +main:1: error: Invalid syntax [out version==3.10.0] -main:1: error: invalid syntax. Perhaps you forgot a comma? +main:1: error: Invalid syntax. Perhaps you forgot a comma? [case testSliceInList39] # flags: --python-version 3.9 @@ -3211,7 +3211,7 @@ MypyFile:1( [case testParseExtendedSlicing4] m[*index, :] [out] -main:1: error: invalid syntax +main:1: error: Invalid syntax [out version>=3.11] MypyFile:1( ExpressionStmt:1( diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 52c658c97c3b..6350c74cf662 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -361,84 +361,84 @@ main:2: error: "yield" outside function [case testInvalidLvalues1] 1 = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [out version>=3.10] -main:1: error: cannot assign to literal here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to literal here. Maybe you meant '==' instead of '='? [case testInvalidLvalues2] (1) = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [out version>=3.10] -main:1: error: cannot assign to literal here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to literal here. Maybe you meant '==' instead of '='? [case testInvalidLvalues3] (1, 1) = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [case testInvalidLvalues4] [1, 1] = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [case testInvalidLvalues6] x = y = z = 1 # ok x, (y, 1) = 1 [out] -main:2: error: cannot assign to literal +main:2: error: Cannot assign to literal [case testInvalidLvalues7] x, [y, 1] = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [case testInvalidLvalues8] x, [y, [z, 1]] = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [case testInvalidLvalues9] x, (y) = 1 # ok x, (y, (z, z)) = 1 # ok x, (y, (z, 1)) = 1 [out] -main:3: error: cannot assign to literal +main:3: error: Cannot assign to literal [case testInvalidLvalues10] x + x = 1 [out] -main:1: error: cannot assign to operator +main:1: error: Cannot assign to operator [out version>=3.10] -main:1: error: cannot assign to expression here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to expression here. Maybe you meant '==' instead of '='? [case testInvalidLvalues11] -x = 1 [out] -main:1: error: cannot assign to operator +main:1: error: Cannot assign to operator [out version>=3.10] -main:1: error: cannot assign to expression here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to expression here. Maybe you meant '==' instead of '='? [case testInvalidLvalues12] 1.1 = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [out version>=3.10] -main:1: error: cannot assign to literal here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to literal here. Maybe you meant '==' instead of '='? [case testInvalidLvalues13] 'x' = 1 [out] -main:1: error: cannot assign to literal +main:1: error: Cannot assign to literal [out version>=3.10] -main:1: error: cannot assign to literal here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to literal here. Maybe you meant '==' instead of '='? [case testInvalidLvalues14] x() = 1 [out] -main:1: error: cannot assign to function call +main:1: error: Cannot assign to function call [out version>=3.10] -main:1: error: cannot assign to function call here. Maybe you meant '==' instead of '='? +main:1: error: Cannot assign to function call here. Maybe you meant '==' instead of '='? [case testTwoStarExpressions] a, *b, *c = 1 @@ -492,7 +492,7 @@ main:2: error: can't use starred expression here x = 1 del x(1) [out] -main:2: error: cannot delete function call +main:2: error: Cannot delete function call [case testInvalidDel2] x = 1 @@ -500,7 +500,7 @@ del x + 1 [out] main:2: error: cannot delete operator [out version>=3.10] -main:2: error: cannot delete expression +main:2: error: Cannot delete expression [case testInvalidDel3] del z # E: Name "z" is not defined @@ -897,9 +897,9 @@ import typing def f(): pass f() = 1 # type: int [out] -main:3: error: cannot assign to function call +main:3: error: Cannot assign to function call [out version>=3.10] -main:3: error: cannot assign to function call here. Maybe you meant '==' instead of '='? +main:3: error: Cannot assign to function call here. Maybe you meant '==' instead of '='? [case testIndexedAssignmentWithTypeDeclaration] import typing @@ -975,9 +975,9 @@ x, y = 1, 2 # type: int # E: Tuple type expected for multiple variables a = 1 a() = None # type: int [out] -main:2: error: cannot assign to function call +main:2: error: Cannot assign to function call [out version>=3.10] -main:2: error: cannot assign to function call here. Maybe you meant '==' instead of '='? +main:2: error: Cannot assign to function call here. Maybe you meant '==' instead of '='? [case testInvalidLvalueWithExplicitType2] a = 1 @@ -1299,7 +1299,7 @@ main:2: note: Did you forget to import it from "typing"? (Suggestion: "from typi def f(): pass with f() as 1: pass [out] -main:2: error: cannot assign to literal +main:2: error: Cannot assign to literal [case testInvalidTypeAnnotation] import typing @@ -1313,9 +1313,9 @@ import typing def f() -> None: f() = 1 # type: int [out] -main:3: error: cannot assign to function call +main:3: error: Cannot assign to function call [out version>=3.10] -main:3: error: cannot assign to function call here. Maybe you meant '==' instead of '='? +main:3: error: Cannot assign to function call here. Maybe you meant '==' instead of '='? [case testInvalidReferenceToAttributeOfOuterClass] class A: diff --git a/test-data/unit/semanal-statements.test b/test-data/unit/semanal-statements.test index f828e2a3263f..a2e8691733ef 100644 --- a/test-data/unit/semanal-statements.test +++ b/test-data/unit/semanal-statements.test @@ -557,9 +557,9 @@ MypyFile:1( def f(x, y) -> None: del x, y + 1 [out] -main:2: error: cannot delete operator +main:2: error: Cannot delete operator [out version>=3.10] -main:2: error: cannot delete expression +main:2: error: Cannot delete expression [case testTry] class c: pass From 250f0f2d5efdced36449899e7570254e856a1a10 Mon Sep 17 00:00:00 2001 From: amansomething Date: Mon, 19 May 2025 15:04:28 -0400 Subject: [PATCH 03/12] Update fastparse.py --- mypy/fastparse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index a119e357b944..fdadba030c2e 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -270,7 +270,7 @@ def parse( errors.report( e.lineno if e.lineno is not None else -1, e.offset, - re.sub(r"^(\s*\w)", lambda m: m.group(1).upper(), message), + re.sub(r"^(\s*\w)", lambda m: m.group(1).upper(), message), # Standardizing error message blocker=True, code=codes.SYNTAX, ) From a791f962477469766b3c14882471054336f4d94d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:06:28 +0000 Subject: [PATCH 04/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/fastparse.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index fdadba030c2e..6c59f44829bb 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -270,7 +270,9 @@ def parse( errors.report( e.lineno if e.lineno is not None else -1, e.offset, - re.sub(r"^(\s*\w)", lambda m: m.group(1).upper(), message), # Standardizing error message + re.sub( + r"^(\s*\w)", lambda m: m.group(1).upper(), message + ), # Standardizing error message blocker=True, code=codes.SYNTAX, ) From 45d0000c360a68a44ab853be737aa795f01784a1 Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Mon, 19 May 2025 15:52:55 -0400 Subject: [PATCH 05/12] Fix Test suite py39-windows-64, py39-ubuntu, mypyc-compiled --- test-data/unit/fine-grained-suggest.test | 4 +-- test-data/unit/parse-errors.test | 40 ++++++++++++------------ test-data/unit/semanal-errors.test | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/test-data/unit/fine-grained-suggest.test b/test-data/unit/fine-grained-suggest.test index 2539886229cf..ba6006300a4c 100644 --- a/test-data/unit/fine-grained-suggest.test +++ b/test-data/unit/fine-grained-suggest.test @@ -1035,10 +1035,10 @@ def foo(): ( [out] -foo.py:4: error: unexpected EOF while parsing +foo.py:4: error: Unexpected EOF while parsing Command 'suggest' is only valid after a 'check' command (that produces no parse errors) == -foo.py:4: error: unexpected EOF while parsing +foo.py:4: error: Unexpected EOF while parsing [out version>=3.10] foo.py:4: error: '(' was never closed Command 'suggest' is only valid after a 'check' command (that produces no parse errors) diff --git a/test-data/unit/parse-errors.test b/test-data/unit/parse-errors.test index 4ebcd358fa68..a192cc02d0cc 100644 --- a/test-data/unit/parse-errors.test +++ b/test-data/unit/parse-errors.test @@ -18,21 +18,21 @@ file:1: error: Invalid syntax 1 2 [out] -file:2: error: unexpected indent +file:2: error: Unexpected indent [case testInconsistentIndent] if x: 1 1 [out] -file:3: error: unexpected indent +file:3: error: Unexpected indent [case testInconsistentIndent2] if x: 1 1 [out] -file:3: error: unindent does not match any outer indentation level +file:3: error: Unindent does not match any outer indentation level [case testInvalidBinaryOp] 1> @@ -55,17 +55,17 @@ file:1: error: Invalid syntax [case testUnexpectedEof] if 1: [out] -file:1: error: expected an indented block +file:1: error: Expected an indented block [case testInvalidKeywordArguments1] f(x=y, z) [out] -file:1: error: positional argument follows keyword argument +file:1: error: Positional argument follows keyword argument [case testInvalidKeywordArguments2] f(**x, y) [out] -file:1: error: positional argument follows keyword argument unpacking +file:1: error: Positional argument follows keyword argument unpacking [case testInvalidBareAsteriskAndVarArgs2] def f(*x: A, *) -> None: pass @@ -80,22 +80,22 @@ file:1: error: Invalid syntax [case testInvalidBareAsteriskAndVarArgs4] def f(*, **x: A) -> None: pass [out] -file:1: error: named arguments must follow bare * +file:1: error: Named arguments must follow bare * [case testInvalidBareAsterisk1] def f(*) -> None: pass [out] -file:1: error: named arguments must follow bare * +file:1: error: Named arguments must follow bare * [case testInvalidBareAsterisk2] def f(x, *) -> None: pass [out] -file:1: error: named arguments must follow bare * +file:1: error: Named arguments must follow bare * [case testInvalidFuncDefArgs1] def f(x = y, x): pass [out] -file:1: error: non-default argument follows default argument +file:1: error: Non-default argument follows default argument [case testInvalidFuncDefArgs3] def f(**x, y): @@ -154,7 +154,7 @@ file:2: error: Syntax error in type comment "A B" [case testMissingBracket] def foo( [out] -file:1: error: unexpected EOF while parsing +file:1: error: Unexpected EOF while parsing [out version>=3.10] file:1: error: '(' was never closed @@ -362,48 +362,48 @@ file:1: error: Invalid syntax [case testParseErrorInExtendedSlicing] x[:, [out] -file:1: error: unexpected EOF while parsing +file:1: error: Unexpected EOF while parsing [case testParseErrorInExtendedSlicing2] x[:,:: [out] -file:1: error: unexpected EOF while parsing +file:1: error: Unexpected EOF while parsing [case testParseErrorInExtendedSlicing3] x[:,: [out] -file:1: error: unexpected EOF while parsing +file:1: error: Unexpected EOF while parsing [case testInvalidEncoding] # foo # coding: uft-8 [out] -file:0: error: unknown encoding: uft-8 +file:0: error: Unknown encoding: uft-8 [case testInvalidEncoding2] # coding=Uft.8 [out] -file:0: error: unknown encoding: Uft.8 +file:0: error: Unknown encoding: Uft.8 [case testInvalidEncoding3] #!/usr/bin python # vim: set fileencoding=uft8 : [out] -file:0: error: unknown encoding: uft8 +file:0: error: Unknown encoding: uft8 [case testDoubleEncoding] # coding: uft8 # coding: utf8 # The first coding cookie should be used and fail. [out] -file:0: error: unknown encoding: uft8 +file:0: error: Unknown encoding: uft8 [case testDoubleEncoding2] # Again the first cookie should be used and fail. # coding: uft8 # coding: utf8 [out] -file:0: error: unknown encoding: uft8 +file:0: error: Unknown encoding: uft8 [case testLongLiteralInPython3] 2L @@ -434,7 +434,7 @@ file:1: error: Invalid syntax [case testSmartQuotes] foo = ‘bar’ [out] -file:1: error: invalid character '‘' (U+2018) +file:1: error: Invalid character '‘' (U+2018) [case testExceptCommaInPython3] try: diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 6350c74cf662..fa5cec795931 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -498,7 +498,7 @@ main:2: error: Cannot delete function call x = 1 del x + 1 [out] -main:2: error: cannot delete operator +main:2: error: Cannot delete operator [out version>=3.10] main:2: error: Cannot delete expression From 0eb4a997f2b938487a528126299e8328e07b824b Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Wed, 21 May 2025 11:23:57 -0400 Subject: [PATCH 06/12] update check_for_missing_annotations to give note for None return type, give missing arg names in err msg --- mypy/checker.py | 79 ++++++++++++++++++++++++--------- mypy/message_registry.py | 2 +- test-data/unit/check-flags.test | 48 ++++++++++++++------ 3 files changed, 94 insertions(+), 35 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index aceb0291926a..a4c8880006ba 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1633,32 +1633,65 @@ def is_reverse_op_method(self, method_name: str) -> bool: def check_for_missing_annotations(self, fdef: FuncItem) -> None: # Check for functions with unspecified/not fully specified types. - def is_unannotated_any(t: Type) -> bool: + def is_unannotated_any(t: Type | None) -> bool: if not isinstance(t, ProperType): return False return isinstance(t, AnyType) and t.type_of_any == TypeOfAny.unannotated + unannotated_args = [ + a.variable.name + for a in fdef.arguments + if not (a.variable.is_cls or a.variable.is_self) + and is_unannotated_any(a.variable.type) + ] + has_explicit_annotation = isinstance(fdef.type, CallableType) and any( - not is_unannotated_any(t) for t in fdef.type.arg_types + [fdef.type.ret_type] + unannotated_args + [fdef.type.ret_type] ) show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation - if show_untyped and (self.options.disallow_untyped_defs or check_incomplete_defs): - if fdef.type is None and self.options.disallow_untyped_defs: - if not fdef.arguments or ( - len(fdef.arguments) == 1 - and (fdef.arg_names[0] == "self" or fdef.arg_names[0] == "cls") - ): - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) - if not has_return_statement(fdef) and not fdef.is_generator: - self.note( - 'Use "-> None" if function does not return a value', + + def handle_function_args_type_annotation() -> None: + if fdef.type is None: + if fdef.arguments: + if len(fdef.arguments) == 1 and ( + fdef.arguments[0].variable.is_cls or fdef.arguments[0].variable.is_self + ): + # its not an error + pass + else: + self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) + + elif isinstance(fdef.type, CallableType): + if unannotated_args: + if len(unannotated_args) < 5: + self.fail( + message_registry.ARGUMENT_TYPE_EXPECTED.format( + ", ".join(f'"{arg}"' for arg in unannotated_args) + ), fdef, - code=codes.NO_UNTYPED_DEF, ) - else: - self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) + else: + self.fail( + message_registry.ARGUMENT_TYPE_EXPECTED.format( + str(", ".join(f'"{arg}"' for arg in unannotated_args[:5]) + "...") + ), + fdef, + ) + + def handle_return_type_annotation() -> None: + if fdef.type is None: + has_return = has_return_statement(fdef) + if has_return: + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) + if not has_return and not fdef.is_generator: + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) + self.note( + 'Use "-> None" if function does not return a value', + fdef, + code=codes.NO_UNTYPED_DEF, + ) elif isinstance(fdef.type, CallableType): ret_type = get_proper_type(fdef.type.ret_type) if is_unannotated_any(ret_type): @@ -1671,8 +1704,13 @@ def is_unannotated_any(t: Type) -> bool: elif fdef.is_coroutine and isinstance(ret_type, Instance): if is_unannotated_any(self.get_coroutine_return_type(ret_type)): self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) - if any(is_unannotated_any(t) for t in fdef.type.arg_types): - self.fail(message_registry.ARGUMENT_TYPE_EXPECTED, fdef) + + if show_untyped and (self.options.disallow_untyped_defs or check_incomplete_defs): + if (isinstance(fdef.type, CallableType) and check_incomplete_defs) or ( + self.options.disallow_untyped_defs + ): + handle_return_type_annotation() + handle_function_args_type_annotation() def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None: self_type = fill_typevars_with_any(fdef.info) @@ -2079,8 +2117,7 @@ def check_method_override( and (self.options.check_untyped_defs or not defn.is_dynamic()) and ( # don't check override for synthesized __replace__ methods from dataclasses - defn.name != "__replace__" - or defn.info.metadata.get("dataclass_tag") is None + defn.name != "__replace__" or defn.info.metadata.get("dataclass_tag") is None ) ) found_method_base_classes: list[TypeInfo] = [] @@ -4254,7 +4291,8 @@ def check_lvalue( self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, (TupleExpr, ListExpr)): types = [ - self.check_lvalue(sub_expr)[0] or + self.check_lvalue(sub_expr)[0] + or # This type will be used as a context for further inference of rvalue, # we put Uninhabited if there is no information available from lvalue. UninhabitedType() @@ -6787,7 +6825,6 @@ def refine_away_none_in_comparison( if_map, else_map = {}, {} if not non_optional_types or (len(non_optional_types) != len(chain_indices)): - # Narrow e.g. `Optional[A] == "x"` or `Optional[A] is "x"` to `A` (which may be # convenient but is strictly not type-safe): for i in narrowable_operand_indices: diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 0c7464246990..90c34612d93a 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -126,7 +126,7 @@ def with_additional_msg(self, info: str) -> ErrorMessage: "Function is missing a return type annotation", codes.NO_UNTYPED_DEF ) ARGUMENT_TYPE_EXPECTED: Final = ErrorMessage( - "Function is missing a type annotation for one or more arguments", codes.NO_UNTYPED_DEF + "Function is missing a type annotation for one or more arguments: {}", code=codes.ASSIGNMENT ) KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE: Final = ErrorMessage( 'Keyword argument only valid with "str" key type in call to "dict"' diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index f628fdd68ce8..9574753124a8 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -2,19 +2,39 @@ # flags: --disallow-untyped-defs def f(x): pass [out] +main:2: error: Function is missing a return type annotation +main:2: note: Use "-> None" if function does not return a value main:2: error: Function is missing a type annotation -[case testUnannotatedArgument] +[case testUnannotatedArgumentSingle] +# flags: --disallow-untyped-defs +def f(x) -> int: return 1 +[out] +main:2: error: Function is missing a type annotation for one or more arguments: "x" + +[case testUnannotatedArgumentLessThan5] +# flags: --disallow-untyped-defs +def f(x, y, z, a:int, b) -> int: return 1 +[out] +main:2: error: Function is missing a type annotation for one or more arguments: "x", "y", "z", "b" + +[case testUnannotatedArgument5orMore] # flags: --disallow-untyped-defs -def f(x) -> int: pass +def f(x, y, z, a:int, b, c, d, e, f:int) -> int: return 1 [out] -main:2: error: Function is missing a type annotation for one or more arguments +main:2: error: Function is missing a type annotation for one or more arguments: "x", "y", "z", "b", "c"... -[case testNoArgumentFunction] +[case testNoArgumentValidReturnType] # flags: --disallow-untyped-defs -def f() -> int: pass +def f() -> int: return 1 [out] +[case testNoArgumentMissingReturnTypeFunction] +# flags: --disallow-untyped-defs +def f(): return 5 +[out] +main:2: error: Function is missing a return type annotation + [case testUnannotatedReturn] # flags: --disallow-untyped-defs def f(x: int): pass @@ -46,6 +66,7 @@ def f(self): pass [out] main:2: error: Function is missing a return type annotation main:2: note: Use "-> None" if function does not return a value +main:2: error: Function is missing a type annotation [case testUnannotatedReturnWithNontrivialReturn] # flags: --disallow-untyped-defs @@ -63,7 +84,7 @@ async def f(): # E: Function is missing a return type annotation \ [case testAsyncUnannotatedArgument] # flags: --disallow-untyped-defs -async def f(x) -> None: # E: Function is missing a type annotation for one or more arguments +async def f(x) -> None: # E: Function is missing a type annotation for one or more arguments: "x" pass [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] @@ -85,6 +106,7 @@ def get_tasks(self): return 'whatever' [out] main:2: error: Function is missing a return type annotation +main:2: error: Function is missing a type annotation [case testDisallowUntypedDefsUntypedDecorator] # flags: --disallow-untyped-decorators @@ -659,7 +681,7 @@ import standard, incomplete def incomplete(x) -> int: return 0 [file incomplete.py] -def incomplete(x) -> int: # E: Function is missing a type annotation for one or more arguments +def incomplete(x) -> int: # E: Function is missing a type annotation for one or more arguments: "x" return 0 [file mypy.ini] \[mypy] @@ -676,7 +698,7 @@ import standard, incomplete def incomplete(x) -> int: return 0 [file incomplete.py] -def incomplete(x) -> int: # E: Function is missing a type annotation for one or more arguments +def incomplete(x) -> int: # E: Function is missing a type annotation for one or more arguments: "x" return 0 [file pyproject.toml] \[tool.mypy] @@ -1351,7 +1373,7 @@ def g(m: Movie) -> Movie: def f(i: int): # E: Function is missing a return type annotation pass -def g(i) -> None: # E: Function is missing a type annotation for one or more arguments +def g(i) -> None: # E: Function is missing a type annotation for one or more arguments: "i" pass def h(i: int) -> int: # no error return i @@ -1378,7 +1400,7 @@ def f(i: int, s): [out] main:3: error: Function is missing a return type annotation -main:3: error: Function is missing a type annotation for one or more arguments +main:3: error: Function is missing a type annotation for one or more arguments: "s" [case testDisallowIncompleteDefsAttrsNoAnnotations] # flags: --disallow-incomplete-defs @@ -1405,7 +1427,7 @@ class Annotated: import attrs @attrs.define -class PartiallyAnnotated: # E: Function is missing a type annotation for one or more arguments +class PartiallyAnnotated: # E: Function is missing a type annotation for one or more arguments: "baz" bar: int = attrs.field() baz = attrs.field() @@ -2301,13 +2323,13 @@ ignore_errors = True # flags: --config-file tmp/mypy.ini import x, y, z [file x.py] -def f(a): ... # E: Function is missing a type annotation +def f(a): ... # E: Function is missing a return type annotation # N: Use "-> None" if function does not return a value # E: Function is missing a type annotation def g(a: int) -> int: return f(a) [file y.py] def f(a): pass def g(a: int) -> int: return f(a) [file z.py] -def f(a): pass # E: Function is missing a type annotation +def f(a): pass # E: Function is missing a return type annotation # N: Use "-> None" if function does not return a value # E: Function is missing a type annotation def g(a: int) -> int: return f(a) # E: Call to untyped function "f" in typed context [file mypy.ini] \[mypy] From 284fe23daa0ab3f3e98377c920c2e876a4917cfe Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 15:28:02 +0000 Subject: [PATCH 07/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/checker.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index a4c8880006ba..da18ac5df228 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2117,7 +2117,8 @@ def check_method_override( and (self.options.check_untyped_defs or not defn.is_dynamic()) and ( # don't check override for synthesized __replace__ methods from dataclasses - defn.name != "__replace__" or defn.info.metadata.get("dataclass_tag") is None + defn.name != "__replace__" + or defn.info.metadata.get("dataclass_tag") is None ) ) found_method_base_classes: list[TypeInfo] = [] @@ -4291,8 +4292,7 @@ def check_lvalue( self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, (TupleExpr, ListExpr)): types = [ - self.check_lvalue(sub_expr)[0] - or + self.check_lvalue(sub_expr)[0] or # This type will be used as a context for further inference of rvalue, # we put Uninhabited if there is no information available from lvalue. UninhabitedType() From 7b89fd9808ade98f26e53016efdd380113d5cd30 Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Wed, 21 May 2025 11:37:22 -0400 Subject: [PATCH 08/12] fix err code for ARGUMENT_TYPE_EXPECTED NO_UNTYPED_DEF --- mypy/message_registry.py | 3 ++- test-data/unit/check-errorcodes.test | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 90c34612d93a..d7ffc482aa05 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -126,7 +126,8 @@ def with_additional_msg(self, info: str) -> ErrorMessage: "Function is missing a return type annotation", codes.NO_UNTYPED_DEF ) ARGUMENT_TYPE_EXPECTED: Final = ErrorMessage( - "Function is missing a type annotation for one or more arguments: {}", code=codes.ASSIGNMENT + "Function is missing a type annotation for one or more arguments: {}", + code=codes.NO_UNTYPED_DEF, ) KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE: Final = ErrorMessage( 'Keyword argument only valid with "str" key type in call to "dict"' diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 0cd6dc081629..9b06e4ae6a54 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -685,6 +685,12 @@ g(p) # type: ignore[arg-type] def f(): # type: ignore[no-untyped-def] pass +[case testErrorCodeNoneReturnNoteIgnoreMultipleArgs] +# flags: --disallow-untyped-defs + +def f(a, b:int, c): # type: ignore[no-untyped-def] + pass + [case testErrorCodeVarianceNoteIgnore] from typing import List def f(x: List[object]) -> None: pass From 54eed1ae846f94bad1d8eaccff45b6676839069f Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Wed, 21 May 2025 16:48:10 -0400 Subject: [PATCH 09/12] update FUNCTION_TYPE_EXPECTED err handling, update tests --- mypy/checker.py | 51 +++++++++++---------------- test-data/unit/check-async-await.test | 2 +- test-data/unit/check-columns.test | 2 +- test-data/unit/check-errorcodes.test | 9 ++--- test-data/unit/check-flags.test | 20 +++++------ test-data/unit/check-ignore.test | 2 +- test-data/unit/check-python38.test | 4 +-- test-data/unit/cmdline.test | 2 ++ test-data/unit/daemon.test | 10 +++--- test-data/unit/fine-grained.test | 6 ++-- 10 files changed, 48 insertions(+), 60 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index da18ac5df228..438c96be5ec5 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1649,21 +1649,8 @@ def is_unannotated_any(t: Type | None) -> bool: unannotated_args + [fdef.type.ret_type] ) - show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub - check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation - def handle_function_args_type_annotation() -> None: - if fdef.type is None: - if fdef.arguments: - if len(fdef.arguments) == 1 and ( - fdef.arguments[0].variable.is_cls or fdef.arguments[0].variable.is_self - ): - # its not an error - pass - else: - self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) - - elif isinstance(fdef.type, CallableType): + if isinstance(fdef.type, CallableType): if unannotated_args: if len(unannotated_args) < 5: self.fail( @@ -1681,17 +1668,8 @@ def handle_function_args_type_annotation() -> None: ) def handle_return_type_annotation() -> None: - if fdef.type is None: - has_return = has_return_statement(fdef) - if has_return: - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) - if not has_return and not fdef.is_generator: - self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) - self.note( - 'Use "-> None" if function does not return a value', - fdef, - code=codes.NO_UNTYPED_DEF, - ) + if fdef.type is None and self.options.disallow_untyped_defs: + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) elif isinstance(fdef.type, CallableType): ret_type = get_proper_type(fdef.type.ret_type) if is_unannotated_any(ret_type): @@ -1705,10 +1683,21 @@ def handle_return_type_annotation() -> None: if is_unannotated_any(self.get_coroutine_return_type(ret_type)): self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) + show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub + check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation + if show_untyped and (self.options.disallow_untyped_defs or check_incomplete_defs): - if (isinstance(fdef.type, CallableType) and check_incomplete_defs) or ( - self.options.disallow_untyped_defs - ): + if fdef.type is None: + if not has_explicit_annotation and self.options.disallow_untyped_defs: + self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) + if not has_return_statement(fdef) and not fdef.is_generator: + self.note( + 'Use "-> None" if function does not return a value', + fdef, + code=codes.NO_UNTYPED_DEF, + ) + + elif isinstance(fdef.type, CallableType): handle_return_type_annotation() handle_function_args_type_annotation() @@ -2117,8 +2106,7 @@ def check_method_override( and (self.options.check_untyped_defs or not defn.is_dynamic()) and ( # don't check override for synthesized __replace__ methods from dataclasses - defn.name != "__replace__" - or defn.info.metadata.get("dataclass_tag") is None + defn.name != "__replace__" or defn.info.metadata.get("dataclass_tag") is None ) ) found_method_base_classes: list[TypeInfo] = [] @@ -4292,7 +4280,8 @@ def check_lvalue( self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, (TupleExpr, ListExpr)): types = [ - self.check_lvalue(sub_expr)[0] or + self.check_lvalue(sub_expr)[0] + or # This type will be used as a context for further inference of rvalue, # we put Uninhabited if there is no information available from lvalue. UninhabitedType() diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index 0ef08e5a0775..0b4e040d409d 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -705,7 +705,7 @@ async def f() -> AsyncGenerator[Any, Any]: async def h() -> Any: yield 0 -async def g(): # E: Function is missing a return type annotation +async def g(): # E: Function is missing a type annotation yield 0 [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi] diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index c18313bbc24f..de0c819ca176 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -175,7 +175,7 @@ if int(): def f(x: int): # E:5: Function is missing a return type annotation pass - def g(x): # E:5: Function is missing a type annotation + def g(x): # E:5: Function is missing a type annotation # N:5: Use "-> None" if function does not return a value pass [case testColumnNameIsNotDefined] diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 9b06e4ae6a54..a291f961efc0 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -362,26 +362,27 @@ a.x # E: Item "B" of "Union[A, B]" has no attribute "x" [union-attr] [case testErrorCodeFunctionHasNoAnnotation] # flags: --disallow-untyped-defs -def f(x): # E: Function is missing a type annotation [no-untyped-def] +def f(x): # E: Function is missing a type annotation [no-untyped-def] # N: Use "-> None" if function does not return a value pass def g(x: int): # E: Function is missing a return type annotation [no-untyped-def] pass -def h(x) -> None: # E: Function is missing a type annotation for one or more arguments [no-untyped-def] +def h(x) -> None: # E: Function is missing a type annotation for one or more arguments: "x" [no-untyped-def] pass -def gen(): # E: Function is missing a return type annotation [no-untyped-def] +def gen(): # E: Function is missing a type annotation [no-untyped-def] yield 1 def gen2(x: int): # E: Function is missing a return type annotation [no-untyped-def] yield 1 -async def asyncf(): # E: Function is missing a return type annotation [no-untyped-def] +async def asyncf(): # E: Function is missing a type annotation [no-untyped-def] return 0 async def asyncf2(x: int): # E: Function is missing a return type annotation [no-untyped-def] return 0 + [typing fixtures/typing-async.pyi] [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 9574753124a8..04496a468da5 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -2,9 +2,8 @@ # flags: --disallow-untyped-defs def f(x): pass [out] -main:2: error: Function is missing a return type annotation -main:2: note: Use "-> None" if function does not return a value main:2: error: Function is missing a type annotation +main:2: note: Use "-> None" if function does not return a value [case testUnannotatedArgumentSingle] # flags: --disallow-untyped-defs @@ -33,7 +32,7 @@ def f() -> int: return 1 # flags: --disallow-untyped-defs def f(): return 5 [out] -main:2: error: Function is missing a return type annotation +main:2: error: Function is missing a type annotation [case testUnannotatedReturn] # flags: --disallow-untyped-defs @@ -57,27 +56,25 @@ lambda x: x def f(): 1 + "str" [out] -main:2: error: Function is missing a return type annotation +main:2: error: Function is missing a type annotation main:2: note: Use "-> None" if function does not return a value [case testUnannotatedReturnWithOnlySelfArgument] # flags: --disallow-untyped-defs def f(self): pass [out] -main:2: error: Function is missing a return type annotation -main:2: note: Use "-> None" if function does not return a value main:2: error: Function is missing a type annotation +main:2: note: Use "-> None" if function does not return a value [case testUnannotatedReturnWithNontrivialReturn] # flags: --disallow-untyped-defs def f(): return 1 [out] -main:2: error: Function is missing a return type annotation +main:2: error: Function is missing a type annotation [case testUntypedAsyncDef] # flags: --disallow-untyped-defs -async def f(): # E: Function is missing a return type annotation \ - # N: Use "-> None" if function does not return a value +async def f(): # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value pass [builtins fixtures/async_await.pyi] [typing fixtures/typing-medium.pyi] @@ -105,7 +102,6 @@ async def g(x: int) -> Any: def get_tasks(self): return 'whatever' [out] -main:2: error: Function is missing a return type annotation main:2: error: Function is missing a type annotation [case testDisallowUntypedDefsUntypedDecorator] @@ -2323,13 +2319,13 @@ ignore_errors = True # flags: --config-file tmp/mypy.ini import x, y, z [file x.py] -def f(a): ... # E: Function is missing a return type annotation # N: Use "-> None" if function does not return a value # E: Function is missing a type annotation +def f(a): ... # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value def g(a: int) -> int: return f(a) [file y.py] def f(a): pass def g(a: int) -> int: return f(a) [file z.py] -def f(a): pass # E: Function is missing a return type annotation # N: Use "-> None" if function does not return a value # E: Function is missing a type annotation +def f(a): pass # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value def g(a: int) -> int: return f(a) # E: Call to untyped function "f" in typed context [file mypy.ini] \[mypy] diff --git a/test-data/unit/check-ignore.test b/test-data/unit/check-ignore.test index a4234e7a37a1..2a8234a243af 100644 --- a/test-data/unit/check-ignore.test +++ b/test-data/unit/check-ignore.test @@ -261,7 +261,7 @@ ERROR # E: Name "ERROR" is not defined [case testIgnoreInsideFunctionDoesntAffectWhole] # flags: --disallow-untyped-defs -def f(): # E: Function is missing a return type annotation +def f(): # E: Function is missing a type annotation 42 + 'no way' # type: ignore return 0 diff --git a/test-data/unit/check-python38.test b/test-data/unit/check-python38.test index f90baed0eb16..8ee4bdf0c7a1 100644 --- a/test-data/unit/check-python38.test +++ b/test-data/unit/check-python38.test @@ -10,7 +10,7 @@ class C: ... # E: Name "C" already defined on line 4 def d(f): ... # type: ignore @d -def f(): ... # E: Function is missing a return type annotation \ +def f(): ... # E: Function is missing a type annotation \ # N: Use "-> None" if function does not return a value [case testIgnoreDecoratedFunction1] @@ -116,7 +116,7 @@ def g(x: int): ... [case testPEP570ArgTypesMissing] # flags: --disallow-untyped-defs -def f(arg, /) -> None: ... # E: Function is missing a type annotation for one or more arguments +def f(arg, /) -> None: ... # E: Function is missing a type annotation for one or more arguments: "arg" [case testPEP570ArgTypesBadDefault] def f(arg: int = "ERROR", /) -> None: ... # E: Incompatible default for argument "arg" (default has type "str", argument has type "int") diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index fb2e0c01fe0e..46a789eb5deb 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -203,7 +203,9 @@ def f(a): pass def f(a): pass [out] z.py:1: error: Function is missing a type annotation +z.py:1: note: Use "-> None" if function does not return a value x.py:1: error: Function is missing a type annotation +x.py:1: note: Use "-> None" if function does not return a value [case testConfigErrorNoSection] # cmd: mypy -c pass diff --git a/test-data/unit/daemon.test b/test-data/unit/daemon.test index 19ffce0927ab..0009fe16254e 100644 --- a/test-data/unit/daemon.test +++ b/test-data/unit/daemon.test @@ -65,17 +65,17 @@ files = ./foo.py [case testDaemonRunMultipleStrict] $ dmypy run -- foo.py --strict --follow-imports=error Daemon started -foo.py:1: error: Function is missing a return type annotation +foo.py:1: error: Function is missing a type annotation foo.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 $ dmypy run -- bar.py --strict --follow-imports=error -bar.py:1: error: Function is missing a return type annotation +bar.py:1: error: Function is missing a type annotation bar.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 $ dmypy run -- foo.py --strict --follow-imports=error -foo.py:1: error: Function is missing a return type annotation +foo.py:1: error: Function is missing a type annotation foo.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 @@ -96,7 +96,7 @@ $ dmypy run -- foo.py --follow-imports=error Restarting: configuration changed Daemon stopped Daemon started -foo.py:1: error: Function is missing a return type annotation +foo.py:1: error: Function is missing a type annotation foo.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 @@ -120,7 +120,7 @@ $ dmypy run -- foo.py --follow-imports=error --pretty Restarting: configuration changed Daemon stopped Daemon started -foo.py:1: error: Function is missing a return type annotation +foo.py:1: error: Function is missing a type annotation def f(): ^ foo.py:1: note: Use "-> None" if function does not return a value diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index df244b3135e9..75275bec9c45 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -10485,13 +10485,13 @@ def f(): pass def f(): pass [file unrelated.txt.3] [out] -a.py:1: error: Function is missing a return type annotation +a.py:1: error: Function is missing a type annotation a.py:1: note: Use "-> None" if function does not return a value == -b.py:1: error: Function is missing a return type annotation +b.py:1: error: Function is missing a type annotation b.py:1: note: Use "-> None" if function does not return a value == -a.py:1: error: Function is missing a return type annotation +a.py:1: error: Function is missing a type annotation a.py:1: note: Use "-> None" if function does not return a value [case testModuleLevelGetAttrInStub] From 547b5466dcfd530ace2616da3d207c2074fa901f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 20:49:59 +0000 Subject: [PATCH 10/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/checker.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 438c96be5ec5..625e5728da18 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2106,7 +2106,8 @@ def check_method_override( and (self.options.check_untyped_defs or not defn.is_dynamic()) and ( # don't check override for synthesized __replace__ methods from dataclasses - defn.name != "__replace__" or defn.info.metadata.get("dataclass_tag") is None + defn.name != "__replace__" + or defn.info.metadata.get("dataclass_tag") is None ) ) found_method_base_classes: list[TypeInfo] = [] @@ -4280,8 +4281,7 @@ def check_lvalue( self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, (TupleExpr, ListExpr)): types = [ - self.check_lvalue(sub_expr)[0] - or + self.check_lvalue(sub_expr)[0] or # This type will be used as a context for further inference of rvalue, # we put Uninhabited if there is no information available from lvalue. UninhabitedType() From e3bba27feb87c9b0383f4c00d7683ea1310da4a7 Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Wed, 21 May 2025 17:34:20 -0400 Subject: [PATCH 11/12] fix logic for return type annotation vs type annotation for when fdef.type is None, update tests --- mypy/checker.py | 21 +++++++++++++-------- test-data/unit/check-errorcodes.test | 4 ++-- test-data/unit/check-flags.test | 8 ++++---- test-data/unit/check-ignore.test | 2 +- test-data/unit/check-python38.test | 2 +- test-data/unit/daemon.test | 10 +++++----- test-data/unit/fine-grained.test | 6 +++--- 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 438c96be5ec5..984005832ec5 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1687,16 +1687,21 @@ def handle_return_type_annotation() -> None: check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation if show_untyped and (self.options.disallow_untyped_defs or check_incomplete_defs): - if fdef.type is None: - if not has_explicit_annotation and self.options.disallow_untyped_defs: + if fdef.type is None and self.options.disallow_untyped_defs: + if not fdef.arguments or ( + len(fdef.arguments) == 1 + and (fdef.arguments[0].variable.is_self or fdef.arguments[0].variable.is_cls) + ): + self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef) + else: self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef) - if not has_return_statement(fdef) and not fdef.is_generator: - self.note( - 'Use "-> None" if function does not return a value', - fdef, - code=codes.NO_UNTYPED_DEF, - ) + if not has_return_statement(fdef) and not fdef.is_generator: + self.note( + 'Use "-> None" if function does not return a value', + fdef, + code=codes.NO_UNTYPED_DEF, + ) elif isinstance(fdef.type, CallableType): handle_return_type_annotation() handle_function_args_type_annotation() diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index a291f961efc0..4f47f52d5e74 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -371,13 +371,13 @@ def g(x: int): # E: Function is missing a return type annotation [no-untyped-d def h(x) -> None: # E: Function is missing a type annotation for one or more arguments: "x" [no-untyped-def] pass -def gen(): # E: Function is missing a type annotation [no-untyped-def] +def gen(): # E: Function is missing a return type annotation [no-untyped-def] yield 1 def gen2(x: int): # E: Function is missing a return type annotation [no-untyped-def] yield 1 -async def asyncf(): # E: Function is missing a type annotation [no-untyped-def] +async def asyncf(): # E: Function is missing a return type annotation [no-untyped-def] return 0 async def asyncf2(x: int): # E: Function is missing a return type annotation [no-untyped-def] diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 04496a468da5..f00863c87907 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -32,7 +32,7 @@ def f() -> int: return 1 # flags: --disallow-untyped-defs def f(): return 5 [out] -main:2: error: Function is missing a type annotation +main:2: error: Function is missing a return type annotation [case testUnannotatedReturn] # flags: --disallow-untyped-defs @@ -56,7 +56,7 @@ lambda x: x def f(): 1 + "str" [out] -main:2: error: Function is missing a type annotation +main:2: error: Function is missing a return type annotation main:2: note: Use "-> None" if function does not return a value [case testUnannotatedReturnWithOnlySelfArgument] @@ -70,11 +70,11 @@ main:2: note: Use "-> None" if function does not return a value # flags: --disallow-untyped-defs def f(): return 1 [out] -main:2: error: Function is missing a type annotation +main:2: error: Function is missing a return type annotation [case testUntypedAsyncDef] # flags: --disallow-untyped-defs -async def f(): # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value +async def f(): # E: Function is missing a return type annotation # N: Use "-> None" if function does not return a value pass [builtins fixtures/async_await.pyi] [typing fixtures/typing-medium.pyi] diff --git a/test-data/unit/check-ignore.test b/test-data/unit/check-ignore.test index 2a8234a243af..a4234e7a37a1 100644 --- a/test-data/unit/check-ignore.test +++ b/test-data/unit/check-ignore.test @@ -261,7 +261,7 @@ ERROR # E: Name "ERROR" is not defined [case testIgnoreInsideFunctionDoesntAffectWhole] # flags: --disallow-untyped-defs -def f(): # E: Function is missing a type annotation +def f(): # E: Function is missing a return type annotation 42 + 'no way' # type: ignore return 0 diff --git a/test-data/unit/check-python38.test b/test-data/unit/check-python38.test index 8ee4bdf0c7a1..bea8e9452874 100644 --- a/test-data/unit/check-python38.test +++ b/test-data/unit/check-python38.test @@ -10,7 +10,7 @@ class C: ... # E: Name "C" already defined on line 4 def d(f): ... # type: ignore @d -def f(): ... # E: Function is missing a type annotation \ +def f(): ... # E: Function is missing a return type annotation \ # N: Use "-> None" if function does not return a value [case testIgnoreDecoratedFunction1] diff --git a/test-data/unit/daemon.test b/test-data/unit/daemon.test index 0009fe16254e..19ffce0927ab 100644 --- a/test-data/unit/daemon.test +++ b/test-data/unit/daemon.test @@ -65,17 +65,17 @@ files = ./foo.py [case testDaemonRunMultipleStrict] $ dmypy run -- foo.py --strict --follow-imports=error Daemon started -foo.py:1: error: Function is missing a type annotation +foo.py:1: error: Function is missing a return type annotation foo.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 $ dmypy run -- bar.py --strict --follow-imports=error -bar.py:1: error: Function is missing a type annotation +bar.py:1: error: Function is missing a return type annotation bar.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 $ dmypy run -- foo.py --strict --follow-imports=error -foo.py:1: error: Function is missing a type annotation +foo.py:1: error: Function is missing a return type annotation foo.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 @@ -96,7 +96,7 @@ $ dmypy run -- foo.py --follow-imports=error Restarting: configuration changed Daemon stopped Daemon started -foo.py:1: error: Function is missing a type annotation +foo.py:1: error: Function is missing a return type annotation foo.py:1: note: Use "-> None" if function does not return a value Found 1 error in 1 file (checked 1 source file) == Return code: 1 @@ -120,7 +120,7 @@ $ dmypy run -- foo.py --follow-imports=error --pretty Restarting: configuration changed Daemon stopped Daemon started -foo.py:1: error: Function is missing a type annotation +foo.py:1: error: Function is missing a return type annotation def f(): ^ foo.py:1: note: Use "-> None" if function does not return a value diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 75275bec9c45..df244b3135e9 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -10485,13 +10485,13 @@ def f(): pass def f(): pass [file unrelated.txt.3] [out] -a.py:1: error: Function is missing a type annotation +a.py:1: error: Function is missing a return type annotation a.py:1: note: Use "-> None" if function does not return a value == -b.py:1: error: Function is missing a type annotation +b.py:1: error: Function is missing a return type annotation b.py:1: note: Use "-> None" if function does not return a value == -a.py:1: error: Function is missing a type annotation +a.py:1: error: Function is missing a return type annotation a.py:1: note: Use "-> None" if function does not return a value [case testModuleLevelGetAttrInStub] From d5cefb876f62499db50dd4df578f5cce3cd905fc Mon Sep 17 00:00:00 2001 From: Charulata Lodha Date: Wed, 21 May 2025 17:46:26 -0400 Subject: [PATCH 12/12] fix test --- test-data/unit/check-async-await.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/check-async-await.test b/test-data/unit/check-async-await.test index 0b4e040d409d..0ef08e5a0775 100644 --- a/test-data/unit/check-async-await.test +++ b/test-data/unit/check-async-await.test @@ -705,7 +705,7 @@ async def f() -> AsyncGenerator[Any, Any]: async def h() -> Any: yield 0 -async def g(): # E: Function is missing a type annotation +async def g(): # E: Function is missing a return type annotation yield 0 [builtins fixtures/async_await.pyi] [typing fixtures/typing-async.pyi]