From d1a014542a1907bc77ccecedc672111dec944d50 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 9 Dec 2021 07:33:43 +0900 Subject: [PATCH] fix: collect only valid fields in mypy plugin (#3247) * fix: collect only valid fields in mypy plugin * Fix flake8 C901 in `PydanticModelTransformer.collect_fields` --- changes/3146-hi-ogawa.md | 1 + pydantic/mypy.py | 4 +++- tests/mypy/modules/plugin_success.py | 14 +++++++++++++- tests/mypy/outputs/plugin-success-strict.txt | 3 +-- 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 changes/3146-hi-ogawa.md diff --git a/changes/3146-hi-ogawa.md b/changes/3146-hi-ogawa.md new file mode 100644 index 0000000..d0f3cb4 --- /dev/null +++ b/changes/3146-hi-ogawa.md @@ -0,0 +1 @@ +Fix mypy plugin to collect fields based on `pydantic.utils.is_valid_field` so that it ignores untyped private variables diff --git a/pydantic/mypy.py b/pydantic/mypy.py index 1dfd49e..9aa0878 100644 --- a/pydantic/mypy.py +++ b/pydantic/mypy.py @@ -1,6 +1,8 @@ from configparser import ConfigParser from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type as TypingType, Union +from pydantic.utils import is_valid_field + try: import toml except ImportError: # pragma: no cover @@ -247,7 +249,7 @@ class PydanticModelTransformer: continue lhs = stmt.lvalues[0] - if not isinstance(lhs, NameExpr): + if not isinstance(lhs, NameExpr) or not is_valid_field(lhs.name): continue if not stmt.new_syntax and self.plugin_config.warn_untyped_fields: diff --git a/tests/mypy/modules/plugin_success.py b/tests/mypy/modules/plugin_success.py index 6fb6d63..217eebc 100644 --- a/tests/mypy/modules/plugin_success.py +++ b/tests/mypy/modules/plugin_success.py @@ -1,6 +1,6 @@ from typing import ClassVar, Optional, Union -from pydantic import BaseModel, BaseSettings, Field, create_model +from pydantic import BaseModel, BaseSettings, Field, create_model, validator from pydantic.dataclasses import dataclass @@ -169,3 +169,15 @@ class SettingsModel(BaseSettings): settings = SettingsModel.construct() + + +def f(name: str) -> str: + return name + + +class ModelWithAllowReuseValidator(BaseModel): + name: str + _normalize_name = validator('name', allow_reuse=True)(f) + + +model_with_allow_reuse_validator = ModelWithAllowReuseValidator(name='xyz') diff --git a/tests/mypy/outputs/plugin-success-strict.txt b/tests/mypy/outputs/plugin-success-strict.txt index 8e61a4a..80365a9 100644 --- a/tests/mypy/outputs/plugin-success-strict.txt +++ b/tests/mypy/outputs/plugin-success-strict.txt @@ -1,4 +1,3 @@ 29: error: Unexpected keyword argument "z" for "Model" [call-arg] 64: error: Untyped fields disallowed [pydantic-field] -79: error: Argument "x" to "OverrideModel" has incompatible type "float"; expected "int" [arg-type] -125: error: Untyped fields disallowed [pydantic-field] \ No newline at end of file +79: error: Argument "x" to "OverrideModel" has incompatible type "float"; expected "int" [arg-type] \ No newline at end of file