8000 Fix per-file strict Optional interaction with default-None args (#3686) · python/mypy@8709da5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8709da5

Browse files
ddfishergvanrossum
authored andcommitted
Fix per-file strict Optional interaction with default-None args (#3686)
With per-file strict Optional, default-None args should always be interpreted as Optional (except with --no-implicit-optional), instead of only in strict Optional files.
1 parent b2f91ea commit 8709da5

File tree

7 files changed

+37
-18
lines changed

7 files changed

+37
-18
lines changed

mypy/fastparse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef],
392392
return func_def
393393

394394
def set_type_optional(self, type: Type, initializer: Expression) -> None:
395-
if self.options.no_implicit_optional or not experiments.STRICT_OPTIONAL:
395+
if self.options.no_implicit_optional:
396396
return
397397
# Indicate that type should be wrapped in an Optional if arg is initialized to None.
398398
optional = isinstance(initializer, NameExpr) and initializer.name == 'None'

mypy/fastparse2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
366366
return func_def
367367

368368
def set_type_optional(self, type: Type, initializer: Expression) -> None:
369-
if self.options.no_implicit_optional or not experiments.STRICT_OPTIONAL:
369+
if self.options.no_implicit_optional:
370370
return
371371
# Indicate that type should be wrapped in an Optional if arg is initialized to None.
372372
optional = isinstance(initializer, NameExpr) and initializer.name == 'None'

test-data/unit/check-fastparse.test

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ def f(a, # type: A
124124
**kwargs # type: F
125125
):
126126
reveal_type(a) # E: Revealed type is '__main__.A'
127-
reveal_type(b) # E: Revealed type is '__main__.B'
127+
reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]'
128128
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
129-
reveal_type(d) # E: Revealed type is '__main__.D'
129+
reveal_type(d) # E: Revealed type is 'Union[__main__.D, builtins.None]'
130130
reveal_type(e) # E: Revealed type is '__main__.E'
131131
reveal_type(kwargs) # E: Revealed type is 'builtins.dict[builtins.str, __main__.F]'
132132
[builtins fixtures/dict.pyi]
@@ -149,9 +149,9 @@ def f(a, # type: A
149149
):
150150
# type: (...) -> int
151151
reveal_type(a) # E: Revealed type is '__main__.A'
152-
reveal_type(b) # E: Revealed type is '__main__.B'
152+
reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]'
153153
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
154-
reveal_type(d) # E: Revealed type is '__main__.D'
154+
reveal_type(d) # E: Revealed type is 'Union[__main__.D, builtins.None]'
155155
reveal_type(e) # E: Revealed type is '__main__.E'
156156
reveal_type(kwargs) # E: Revealed type is 'builtins.dict[builtins.str, __main__.F]'
157157
return "not an int" # E: Incompatible return value type (got "str", expected "int")
@@ -191,7 +191,7 @@ def f(a, # type: A
191191
# kwargs not tested due to lack of 2.7 dict fixtures
192192
):
193193
reveal_type(a) # E: Revealed type is '__main__.A'
194-
reveal_type(b) # E: Revealed type is '__main__.B'
194+
reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]'
195195
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
196196
[builtins fixtures/dict.pyi]
197197
[out]
@@ -209,7 +209,7 @@ def f(a, # type: A
209209
):
210210
# type: (...) -> int
211211
reveal_type(a) # E: Revealed type is '__main__.A'
212-
reveal_type(b) # E: Revealed type is '__main__.B'
212+
reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]'
213213
reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]'
214214
return "not an int" # E: Incompatible return value type (got "str", expected "int")
215215
[builtins fixtures/dict.pyi]

test-data/unit/check-flags.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,24 @@ def f() -> None:
482482
x = [] # type: Union[List[Optional[str]], str]
483483
[builtins fixtures/list.pyi]
484484

485+
[case testPerFileStrictOptionalNoneArguments]
486+
# flags: --config-file tmp/mypy.ini
487+
import standard, optional
488+
489+
[file standard.py]
490+
def f(x: int = None) -> None: pass
491+
492+
[file optional.py]
493+
import standard
494+
def f(x: int = None) -> None: pass
495+
standard.f(None)
496+
497+
[file mypy.ini]
498+
[[mypy]
499+
strict_optional = False
500+
[[mypy-optional]
501+
strict_optional = True
502+
485503
[case testDisallowImplicitTypesIgnoreMissingTypes]
486504
# flags: --ignore-missing-imports --disallow-any=unimported
487505
from missing import MyType

test-data/unit/check-functions.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ y = x # E: Incompatible types in assignment (expression has type Callable[...,
363363

364364
a, b = None, None # type: (A, B)
365365
a = f() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
366-
b = f(b) # E: Argument 1 to "f" has incompatible type "B"; expected "A"
366+
b = f(b) # E: Argument 1 to "f" has incompatible type "B"; expected "Optional[A]"
367367
b = f(a, a) # E: Too many arguments for "f"
368368

369369
b = f()

test-data/unit/check-kwargs.test

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ f(a=A())
3030
f(b=B())
3131
f(c=C())
3232
f(b=B(), c=C())
33-
f(a=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A"
34-
f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "B"
35-
f(c=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "C"
36-
f(b=B(), c=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "C"
33+
f(a=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "Optional[A]"
34+
f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "Optional[B]"
35+
f(c=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "Optional[C]"
36+
f(b=B(), c=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "Optional[C]"
3737
class A: pass
3838
class B: pass
3939
class C: pass
@@ -182,7 +182,7 @@ f(A(), b=B())
182182
f(A(), A(), b=B())
183183
f(B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A"
184184
f(A(), B()) # E: Argument 2 to "f" has incompatible type "B"; expected "A"
185-
f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "B"
185+
f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "Optional[B]"
186186
class A: pass
187187
class B: pass
188188
[builtins fixtures/list.pyi]
@@ -197,8 +197,8 @@ f(b=B())
197197
f(*a, b=B())
198198
f(A(), *a, b=B())
199199
f(A(), B()) # E: Argument 2 to "f" has incompatible type "B"; expected "A"
200-
f(A(), b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "B"
201-
f(*a, b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "B"
200+
f(A(), b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "Optional[B]"
201+
f(*a, b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "Optional[B]"
202202
class A: pass
203203
class B: pass
204204
[builtins fixtures/list.pyi]

test-data/unit/check-varargs.test

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ a = None # type: A
8686
b = None # type: B
8787
c = None # type: C
8888

89-
f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "C"
89+
f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "Optional[C]"
9090
f(c, c) # E: Argument 2 to "f" has incompatible type "C"; expected "A"
9191
f(c, a, b, c) # E: Argument 4 to "f" has incompatible type "C"; expected "A"
9292
f()
@@ -377,9 +377,10 @@ class B: pass
377377
[builtins fixtures/list.pyi]
378378
[out]
379379
main:3: error: Too few arguments for "f"
380+
main:4: error: Argument 2 to "f" has incompatible type *List[A]; expected "Optional[B]"
380381
main:4: error: Argument 2 to "f" has incompatible type *List[A]; expected "B"
381382
main:5: error: Argument 3 to "f" has incompatible type *List[A]; expected "B"
382-
main:6: error: Argument 1 to "f" has incompatible type *"Tuple[A, A, B]"; expected "B"
383+
main:6: error: Argument 1 to "f" has incompatible type *"Tuple[A, A, B]"; expected "Optional[B]"
383384

384385
[case testVarArgsAfterKeywordArgInCall1-skip]
385386
# see: mypy issue #2729

0 commit comments

Comments
 (0)
0