From 50259d7ce69b1a9ec47caff25b94704817336c8c Mon Sep 17 00:00:00 2001 From: David Montague <35119617+dmontagu@users.noreply.github.com> Date: Tue, 30 Jan 2024 06:23:54 -0700 Subject: [PATCH] Fix bug with mypy plugin and `no_strict_optional = True` (#8666) --- pydantic/mypy.py | 4 +-- .../pyproject-plugin-no-strict-optional.toml | 36 +++++++++++++++++++ tests/mypy/modules/no_strict_optional.py | 7 ++++ .../no_strict_optional.py | 7 ++++ tests/mypy/test_mypy.py | 1 + 5 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/mypy/configs/pyproject-plugin-no-strict-optional.toml create mode 100644 tests/mypy/modules/no_strict_optional.py create mode 100644 tests/mypy/outputs/1.0.1/pyproject-plugin-no-strict-optional_toml/no_strict_optional.py diff --git a/pydantic/mypy.py b/pydantic/mypy.py index bfa82d8cfb..3b85396179 100644 --- a/pydantic/mypy.py +++ b/pydantic/mypy.py @@ -475,9 +475,9 @@ def transform(self) -> bool: return False is_settings = any(base.fullname == BASESETTINGS_FULLNAME for base in info.mro[:-1]) - self.add_initializer(fields, config, is_settings, is_root_model) - self.add_model_construct_method(fields, config, is_settings) try: + self.add_initializer(fields, config, is_settings, is_root_model) + self.add_model_construct_method(fields, config, is_settings) self.set_frozen(fields, frozen=config.frozen is True) except _DeferAnalysis: if not self._api.final_iteration: diff --git a/tests/mypy/configs/pyproject-plugin-no-strict-optional.toml b/tests/mypy/configs/pyproject-plugin-no-strict-optional.toml new file mode 100644 index 0000000000..f646735e84 --- /dev/null +++ b/tests/mypy/configs/pyproject-plugin-no-strict-optional.toml @@ -0,0 +1,36 @@ +[build-system] +requires = ["poetry>=0.12"] +build_backend = "poetry.masonry.api" + +[tool.poetry] +name = "test" +version = "0.0.1" +readme = "README.md" +authors = [ + "author@example.com" +] + +[tool.poetry.dependencies] +python = "*" + +[tool.pytest.ini_options] +addopts = "-v -p no:warnings" + +[tool.mypy] +plugins = [ + "pydantic.mypy" +] +follow_imports = "silent" +no_strict_optional = true +warn_redundant_casts = true +warn_unused_ignores = true +disallow_any_generics = true +check_untyped_defs = true +no_implicit_reexport = true +disallow_untyped_defs = true + +[[tool.mypy.overrides]] +module = [ + 'pydantic_core.*', +] +follow_imports = "skip" diff --git a/tests/mypy/modules/no_strict_optional.py b/tests/mypy/modules/no_strict_optional.py new file mode 100644 index 0000000000..f07f968630 --- /dev/null +++ b/tests/mypy/modules/no_strict_optional.py @@ -0,0 +1,7 @@ +from typing import Union + +from pydantic import BaseModel + + +class MongoSettings(BaseModel): + MONGO_PASSWORD: Union[str, None] diff --git a/tests/mypy/outputs/1.0.1/pyproject-plugin-no-strict-optional_toml/no_strict_optional.py b/tests/mypy/outputs/1.0.1/pyproject-plugin-no-strict-optional_toml/no_strict_optional.py new file mode 100644 index 0000000000..f07f968630 --- /dev/null +++ b/tests/mypy/outputs/1.0.1/pyproject-plugin-no-strict-optional_toml/no_strict_optional.py @@ -0,0 +1,7 @@ +from typing import Union + +from pydantic import BaseModel + + +class MongoSettings(BaseModel): + MONGO_PASSWORD: Union[str, None] diff --git a/tests/mypy/test_mypy.py b/tests/mypy/test_mypy.py index dd2dce9ce4..3d83bb0b09 100644 --- a/tests/mypy/test_mypy.py +++ b/tests/mypy/test_mypy.py @@ -110,6 +110,7 @@ def build(self) -> List[Union[Tuple[str, str], Any]]: ('mypy-plugin-strict-no-any.ini', 'dataclass_no_any.py'), ('mypy-plugin-very-strict.ini', 'metaclass_args.py'), ('pyproject-default.toml', 'computed_fields.py'), + ('pyproject-plugin-no-strict-optional.toml', 'no_strict_optional.py'), ] )