From 6cd8c00983a294b4b142ee0f01e91912363d3450 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Fri, 7 Jul 2023 20:40:01 +0200 Subject: [PATCH] Enable strict optional for more test files (3) (#15597) --- mypy/test/helpers.py | 11 ++---- mypy/test/testfinegrained.py | 7 +--- test-data/unit/fine-grained-suggest.test | 2 +- test-data/unit/fine-grained.test | 46 +++++++++++++----------- 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/mypy/test/helpers.py b/mypy/test/helpers.py index 1e034f94dd92..d2c92614048a 100644 --- a/mypy/test/helpers.py +++ b/mypy/test/helpers.py @@ -7,7 +7,7 @@ import shutil import sys import time -from typing import Any, Callable, Collection, Iterable, Iterator, Pattern +from typing import Any, Callable, Iterable, Iterator, Pattern # Exporting Suite as alias to TestCase for backwards compatibility # TODO: avoid aliasing - import and subclass TestCase directly @@ -317,10 +317,7 @@ def assert_type(typ: type, value: object) -> None: def parse_options( - program_text: str, - testcase: DataDrivenTestCase, - incremental_step: int, - no_strict_optional_files: Collection[str] = (), + program_text: str, testcase: DataDrivenTestCase, incremental_step: int ) -> Options: """Parse comments like '# flags: --foo' in a test case.""" options = Options() @@ -342,10 +339,6 @@ def parse_options( else: flag_list = [] options = Options() - # TODO: Enable strict optional in test cases by default (requires *many* test case changes) - if os.path.basename(testcase.file) in no_strict_optional_files: - options.strict_optional = False - options.error_summary = False options.hide_error_codes = True options.force_uppercase_builtins = True diff --git a/mypy/test/testfinegrained.py b/mypy/test/testfinegrained.py index a1dde823cb5f..ba0526d32558 100644 --- a/mypy/test/testfinegrained.py +++ b/mypy/test/testfinegrained.py @@ -45,9 +45,6 @@ # Set to True to perform (somewhat expensive) checks for duplicate AST nodes after merge CHECK_CONSISTENCY = False -# TODO: Enable strict optional in test cases by default. Remove files here, once test cases are updated -no_strict_optional_files = {"fine-grained.test", "fine-grained-suggest.test"} - class FineGrainedSuite(DataSuite): files = find_test_files( @@ -143,9 +140,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: def get_options(self, source: str, testcase: DataDrivenTestCase, build_cache: bool) -> Options: # This handles things like '# flags: --foo'. - options = parse_options( - source, testcase, incremental_step=1, no_strict_optional_files=no_strict_optional_files - ) + options = parse_options(source, testcase, incremental_step=1) options.incremental = True options.use_builtins_fixtures = True options.show_traceback = True diff --git a/test-data/unit/fine-grained-suggest.test b/test-data/unit/fine-grained-suggest.test index a28e3204b93f..47de16b8d765 100644 --- a/test-data/unit/fine-grained-suggest.test +++ b/test-data/unit/fine-grained-suggest.test @@ -1090,7 +1090,7 @@ optional2(10) optional2('test') def optional3(x: Optional[List[Any]]): - assert not x + assert x return x[0] optional3(test) diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 3cb234364a58..7d854bab424c 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -191,7 +191,7 @@ main:3: error: "A" has no attribute "x" [case testVariableTypeBecomesInvalid] import m def f() -> None: - a = None # type: m.A + a: m.A [file m.py] class A: pass [file m.py.2] @@ -1724,15 +1724,15 @@ f = 1 main:1: error: Module "a" has no attribute "f" [case testDecoratedMethodRefresh] -from typing import Iterator, Callable, List +from typing import Iterator, Callable, List, Optional from a import f import a -def dec(f: Callable[['A'], Iterator[int]]) -> Callable[[int], int]: pass +def dec(f: Callable[['A'], Optional[Iterator[int]]]) -> Callable[[int], int]: pass class A: @dec - def f(self) -> Iterator[int]: + def f(self) -> Optional[Iterator[int]]: self.x = a.g() # type: int return None [builtins fixtures/list.pyi] @@ -4626,6 +4626,7 @@ class User: == [case testNoStrictOptionalModule] +# flags: --no-strict-optional import a a.y = a.x [file a.py] @@ -4643,9 +4644,10 @@ y: int [out] == == -main:2: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "int") +main:3: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "int") [case testNoStrictOptionalFunction] +# flags: --no-strict-optional import a from typing import Optional def f() -> None: @@ -4666,9 +4668,10 @@ def g(x: str) -> None: [out] == == -main:5: error: Argument 1 to "g" has incompatible type "Optional[int]"; expected "str" +main:6: error: Argument 1 to "g" has incompatible type "Optional[int]"; expected "str" [case testNoStrictOptionalMethod] +# flags: --no-strict-optional import a from typing import Optional class C: @@ -4693,7 +4696,7 @@ class B: [out] == == -main:6: error: Argument 1 to "g" of "B" has incompatible type "Optional[int]"; expected "str" +main:7: error: Argument 1 to "g" of "B" has incompatible type "Optional[int]"; expected "str" [case testStrictOptionalModule] # flags: --strict-optional @@ -5276,10 +5279,11 @@ class I(metaclass=ABCMeta): @abstractmethod def f(self) -> None: pass [file b.py] +from typing import Optional from z import I class Foo(I): pass -def x() -> Foo: return None +def x() -> Optional[Foo]: return None [file z.py.2] from abc import abstractmethod, ABCMeta class I(metaclass=ABCMeta): @@ -5301,10 +5305,11 @@ class I(metaclass=ABCMeta): @abstractmethod def f(self) -> None: pass [file b.py] +from typing import Optional from a import I class Foo(I): pass -def x() -> Foo: return None +def x() -> Optional[Foo]: return None [file a.py.2] from abc import abstractmethod, ABCMeta class I(metaclass=ABCMeta): @@ -7769,7 +7774,8 @@ from typing import List import b class A(b.B): def meth(self) -> None: - self.x, *self.y = None, None # type: str, List[str] + self.x: str + self.y: List[str] [file b.py] from typing import List class B: @@ -7781,7 +7787,7 @@ class B: [builtins fixtures/list.pyi] [out] == -main:5: error: Incompatible types in assignment (expression has type "List[str]", base class "B" defined the type as "List[int]") +main:6: error: Incompatible types in assignment (expression has type "List[str]", base class "B" defined the type as "List[int]") [case testLiskovFineVariableCleanDefInMethodNested-only_when_nocache] from b import B @@ -9109,27 +9115,27 @@ import a [file a.py] # mypy: no-warn-no-return -from typing import List -def foo() -> List: +from typing import List, Optional +def foo() -> Optional[List]: 20 [file a.py.2] # mypy: disallow-any-generics, no-warn-no-return -from typing import List -def foo() -> List: +from typing import List, Optional +def foo() -> Optional[List]: 20 [file a.py.3] # mypy: no-warn-no-return -from typing import List -def foo() -> List: +from typing import List, Optional +def foo() -> Optional[List]: 20 [file a.py.4] -from typing import List -def foo() -> List: +from typing import List, Optional +def foo() -> Optional[List]: 20 [out] == @@ -9867,7 +9873,7 @@ x = 0 # Arbitrary change to trigger reprocessing [builtins fixtures/dict.pyi] [out] == -a.py:5: note: Revealed type is "def (x: builtins.int) -> builtins.str" +a.py:5: note: Revealed type is "def (x: builtins.int) -> Union[builtins.str, None]" [case testTypeVarTupleCached] import a