Skip to content

Commit 54eed1a

Browse files
author
Charulata Lodha
committed
update FUNCTION_TYPE_EXPECTED err handling, update tests
1 parent a14d4a2 commit 54eed1a

File tree

10 files changed

+48
-60
lines changed

10 files changed

+48
-60
lines changed

mypy/checker.py

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,21 +1649,8 @@ def is_unannotated_any(t: Type | None) -> bool:
16491649
unannotated_args + [fdef.type.ret_type]
16501650
)
16511651

1652-
show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub
1653-
check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation
1654-
16551652
def handle_function_args_type_annotation() -> None:
1656-
if fdef.type is None:
1657-
if fdef.arguments:
1658-
if len(fdef.arguments) == 1 and (
1659-
fdef.arguments[0].variable.is_cls or fdef.arguments[0].variable.is_self
1660-
):
1661-
# its not an error
1662-
pass
1663-
else:
1664-
self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef)
1665-
1666-
elif isinstance(fdef.type, CallableType):
1653+
if isinstance(fdef.type, CallableType):
16671654
if unannotated_args:
16681655
if len(unannotated_args) < 5:
16691656
self.fail(
@@ -1681,17 +1668,8 @@ def handle_function_args_type_annotation() -> None:
16811668
)
16821669

16831670
def handle_return_type_annotation() -> None:
1684-
if fdef.type is None:
1685-
has_return = has_return_statement(fdef)
1686-
if has_return:
1687-
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
1688-
if not has_return and not fdef.is_generator:
1689-
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
1690-
self.note(
1691-
'Use "-> None" if function does not return a value',
1692-
fdef,
1693-
code=codes.NO_UNTYPED_DEF,
1694-
)
1671+
if fdef.type is None and self.options.disallow_untyped_defs:
1672+
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
16951673
elif isinstance(fdef.type, CallableType):
16961674
ret_type = get_proper_type(fdef.type.ret_type)
16971675
if is_unannotated_any(ret_type):
@@ -1705,10 +1683,21 @@ def handle_return_type_annotation() -> None:
17051683
if is_unannotated_any(self.get_coroutine_return_type(ret_type)):
17061684
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
17071685

1686+
show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub
1687+
check_incomplete_defs = self.options.disallow_incomplete_defs and has_explicit_annotation
1688+
17081689
if show_untyped and (self.options.disallow_untyped_defs or check_incomplete_defs):
1709-
if (isinstance(fdef.type, CallableType) and check_incomplete_defs) or (
1710-
self.options.disallow_untyped_defs
1711-
):
1690+
if fdef.type is None:
1691+
if not has_explicit_annotation and self.options.disallow_untyped_defs:
1692+
self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef)
1693+
if not has_return_statement(fdef) and not fdef.is_generator:
1694+
self.note(
1695+
'Use "-> None" if function does not return a value',
1696+
fdef,
1697+
code=codes.NO_UNTYPED_DEF,
1698+
)
1699+
1700+
elif isinstance(fdef.type, CallableType):
17121701
handle_return_type_annotation()
17131702
handle_function_args_type_annotation()
17141703

@@ -2117,8 +2106,7 @@ def check_method_override(
21172106
and (self.options.check_untyped_defs or not defn.is_dynamic())
21182107
and (
21192108
# don't check override for synthesized __replace__ methods from dataclasses
2120-
defn.name != "__replace__"
2121-
or defn.info.metadata.get("dataclass_tag") is None
2109+
defn.name != "__replace__" or defn.info.metadata.get("dataclass_tag") is None
21222110
)
21232111
)
21242112
found_method_base_classes: list[TypeInfo] = []
@@ -4292,7 +4280,8 @@ def check_lvalue(
42924280
self.store_type(lvalue, lvalue_type)
42934281
elif isinstance(lvalue, (TupleExpr, ListExpr)):
42944282
types = [
4295-
self.check_lvalue(sub_expr)[0] or
4283+
self.check_lvalue(sub_expr)[0]
4284+
or
42964285
# This type will be used as a context for further inference of rvalue,
42974286
# we put Uninhabited if there is no information available from lvalue.
42984287
UninhabitedType()

test-data/unit/check-async-await.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ async def f() -> AsyncGenerator[Any, Any]:
705705
async def h() -> Any:
706706
yield 0
707707

708-
async def g(): # E: Function is missing a return type annotation
708+
async def g(): # E: Function is missing a type annotation
709709
yield 0
710710
[builtins fixtures/async_await.pyi]
711711
[typing fixtures/typing-async.pyi]

test-data/unit/check-columns.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ if int():
175175
def f(x: int): # E:5: Function is missing a return type annotation
176176
pass
177177

178-
def g(x): # E:5: Function is missing a type annotation
178+
def g(x): # E:5: Function is missing a type annotation # N:5: Use "-> None" if function does not return a value
179179
pass
180180

181181
[case testColumnNameIsNotDefined]

test-data/unit/check-errorcodes.test

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,26 +362,27 @@ a.x # E: Item "B" of "Union[A, B]" has no attribute "x" [union-attr]
362362
[case testErrorCodeFunctionHasNoAnnotation]
363363
# flags: --disallow-untyped-defs
364364

365-
def f(x): # E: Function is missing a type annotation [no-untyped-def]
365+
def f(x): # E: Function is missing a type annotation [no-untyped-def] # N: Use "-> None" if function does not return a value
366366
pass
367367

368368
def g(x: int): # E: Function is missing a return type annotation [no-untyped-def]
369369
pass
370370

371-
def h(x) -> None: # E: Function is missing a type annotation for one or more arguments [no-untyped-def]
371+
def h(x) -> None: # E: Function is missing a type annotation for one or more arguments: "x" [no-untyped-def]
372372
pass
373373

374-
def gen(): # E: Function is missing a return type annotation [no-untyped-def]
374+
def gen(): # E: Function is missing a type annotation [no-untyped-def]
375375
yield 1
376376

377377
def gen2(x: int): # E: Function is missing a return type annotation [no-untyped-def]
378378
yield 1
379379

380-
async def asyncf(): # E: Function is missing a return type annotation [no-untyped-def]
380+
async def asyncf(): # E: Function is missing a type annotation [no-untyped-def]
381381
return 0
382382

383383
async def asyncf2(x: int): # E: Function is missing a return type annotation [no-untyped-def]
384384
return 0
385+
385386
[typing fixtures/typing-async.pyi]
386387
[builtins fixtures/tuple.pyi]
387388

test-data/unit/check-flags.test

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
# flags: --disallow-untyped-defs
33
def f(x): pass
44
[out]
5-
main:2: error: Function is missing a return type annotation
6-
main:2: note: Use "-> None" if function does not return a value
75
main:2: error: Function is missing a type annotation
6+
main:2: note: Use "-> None" if function does not return a value
87

98
[case testUnannotatedArgumentSingle]
109
# flags: --disallow-untyped-defs
@@ -33,7 +32,7 @@ def f() -> int: return 1
3332
# flags: --disallow-untyped-defs
3433
def f(): return 5
3534
[out]
36-
main:2: error: Function is missing a return type annotation
35+
main:2: error: Function is missing a type annotation
3736

3837
[case testUnannotatedReturn]
3938
# flags: --disallow-untyped-defs
@@ -57,27 +56,25 @@ lambda x: x
5756
def f():
5857
1 + "str"
5958
[out]
60-
main:2: error: Function is missing a return type annotation
59+
main:2: error: Function is missing a type annotation
6160
main:2: note: Use "-> None" if function does not return a value
6261

6362
[case testUnannotatedReturnWithOnlySelfArgument]
6463
# flags: --disallow-untyped-defs
6564
def f(self): pass
6665
[out]
67-
main:2: error: Function is missing a return type annotation
68-
main:2: note: Use "-> None" if function does not return a value
6966
main:2: error: Function is missing a type annotation
67+
main:2: note: Use "-> None" if function does not return a value
7068

7169
[case testUnannotatedReturnWithNontrivialReturn]
7270
# flags: --disallow-untyped-defs
7371
def f(): return 1
7472
[out]
75-
main:2: error: Function is missing a return type annotation
73+
main:2: error: Function is missing a type annotation
7674

7775
[case testUntypedAsyncDef]
7876
# flags: --disallow-untyped-defs
79-
async def f(): # E: Function is missing a return type annotation \
80-
# N: Use "-> None" if function does not return a value
77+
async def f(): # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value
8178
pass
8279
[builtins fixtures/async_await.pyi]
8380
[typing fixtures/typing-medium.pyi]
@@ -105,7 +102,6 @@ async def g(x: int) -> Any:
105102
def get_tasks(self):
106103
return 'whatever'
107104
[out]
108-
main:2: error: Function is missing a return type annotation
109105
main:2: error: Function is missing a type annotation
110106

111107
[case testDisallowUntypedDefsUntypedDecorator]
@@ -2323,13 +2319,13 @@ ignore_errors = True
23232319
# flags: --config-file tmp/mypy.ini
23242320
import x, y, z
23252321
[file x.py]
2326-
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
2322+
def f(a): ... # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value
23272323
def g(a: int) -> int: return f(a)
23282324
[file y.py]
23292325
def f(a): pass
23302326
def g(a: int) -> int: return f(a)
23312327
[file z.py]
2332-
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
2328+
def f(a): pass # E: Function is missing a type annotation # N: Use "-> None" if function does not return a value
23332329
def g(a: int) -> int: return f(a) # E: Call to untyped function "f" in typed context
23342330
[file mypy.ini]
23352331
\[mypy]

test-data/unit/check-ignore.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ ERROR # E: Name "ERROR" is not defined
261261
[case testIgnoreInsideFunctionDoesntAffectWhole]
262262
# flags: --disallow-untyped-defs
263263

264-
def f(): # E: Function is missing a return type annotation
264+
def f(): # E: Function is missing a type annotation
265265
42 + 'no way' # type: ignore
266266
return 0
267267

test-data/unit/check-python38.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class C: ... # E: Name "C" already defined on line 4
1010
def d(f): ... # type: ignore
1111
@d
1212

13-
def f(): ... # E: Function is missing a return type annotation \
13+
def f(): ... # E: Function is missing a type annotation \
1414
# N: Use "-> None" if function does not return a value
1515

1616
[case testIgnoreDecoratedFunction1]
@@ -116,7 +116,7 @@ def g(x: int): ...
116116

117117
[case testPEP570ArgTypesMissing]
118118
# flags: --disallow-untyped-defs
119-
def f(arg, /) -> None: ... # E: Function is missing a type annotation for one or more arguments
119+
def f(arg, /) -> None: ... # E: Function is missing a type annotation for one or more arguments: "arg"
120120

121121
[case testPEP570ArgTypesBadDefault]
122122
def f(arg: int = "ERROR", /) -> None: ... # E: Incompatible default for argument "arg" (default has type "str", argument has type "int")

test-data/unit/cmdline.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ def f(a): pass
203203
def f(a): pass
204204
[out]
205205
z.py:1: error: Function is missing a type annotation
206+
z.py:1: note: Use "-> None" if function does not return a value
206207
x.py:1: error: Function is missing a type annotation
208+
x.py:1: note: Use "-> None" if function does not return a value
207209

208210
[case testConfigErrorNoSection]
209211
# cmd: mypy -c pass

test-data/unit/daemon.test

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,17 @@ files = ./foo.py
6565
[case testDaemonRunMultipleStrict]
6666
$ dmypy run -- foo.py --strict --follow-imports=error
6767
Daemon started
68-
foo.py:1: error: Function is missing a return type annotation
68+
foo.py:1: error: Function is missing a type annotation
6969
foo.py:1: note: Use "-> None" if function does not return a value
7070
Found 1 error in 1 file (checked 1 source file)
7171
== Return code: 1
7272
$ dmypy run -- bar.py --strict --follow-imports=error
73-
bar.py:1: error: Function is missing a return type annotation
73+
bar.py:1: error: Function is missing a type annotation
7474
bar.py:1: note: Use "-> None" if function does not return a value
7575
Found 1 error in 1 file (checked 1 source file)
7676
== Return code: 1
7777
$ dmypy run -- foo.py --strict --follow-imports=error
78-
foo.py:1: error: Function is missing a return type annotation
78+
foo.py:1: error: Function is missing a type annotation
7979
foo.py:1: note: Use "-> None" if function does not return a value
8080
Found 1 error in 1 file (checked 1 source file)
8181
== Return code: 1
@@ -96,7 +96,7 @@ $ dmypy run -- foo.py --follow-imports=error
9696
Restarting: configuration changed
9797
Daemon stopped
9898
Daemon started
99-
foo.py:1: error: Function is missing a return type annotation
99+
foo.py:1: error: Function is missing a type annotation
100100
foo.py:1: note: Use "-> None" if function does not return a value
101101
Found 1 error in 1 file (checked 1 source file)
102102
== Return code: 1
@@ -120,7 +120,7 @@ $ dmypy run -- foo.py --follow-imports=error --pretty
120120
Restarting: configuration changed
121121
Daemon stopped
122122
Daemon started
123-
foo.py:1: error: Function is missing a return type annotation
123+
foo.py:1: error: Function is missing a type annotation
124124
def f():
125125
^
126126
foo.py:1: note: Use "-> None" if function does not return a value

test-data/unit/fine-grained.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10485,13 +10485,13 @@ def f(): pass
1048510485
def f(): pass
1048610486
[file unrelated.txt.3]
1048710487
[out]
10488-
a.py:1: error: Function is missing a return type annotation
10488+
a.py:1: error: Function is missing a type annotation
1048910489
a.py:1: note: Use "-> None" if function does not return a value
1049010490
==
10491-
b.py:1: error: Function is missing a return type annotation
10491+
b.py:1: error: Function is missing a type annotation
1049210492
b.py:1: note: Use "-> None" if function does not return a value
1049310493
==
10494-
a.py:1: error: Function is missing a return type annotation
10494+
a.py:1: error: Function is missing a type annotation
1049510495
a.py:1: note: Use "-> None" if function does not return a value
1049610496

1049710497
[case testModuleLevelGetAttrInStub]

0 commit comments

Comments
 (0)