Repository: pydantic/pydantic

Issue:
`pydantic.mypy` plugin error using `pydantic_settings` `SettingsConfigDict`
### Initial Checks

- [X] I confirm that I'm using Pydantic V2

### Description

`pydantic` mypy crashes when providing a `model_config` `SettingsConfigDict` within the `BaseSettings` class. `mypy` continues to crash even after commenting out the `model_config` until the virtual environment is rebuilt.

Traceback:
```bash
$ mypy test.py --show-traceback
test.py:3: error: INTERNAL ERROR -- Please try using mypy master on GitHub:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 1.4.1
Traceback (most recent call last):
  File "mypy/semanal.py", line 6451, in accept
  File "mypy/nodes.py", line 1139, in accept
  File "mypy/semanal.py", line 1582, in visit_class_def
  File "mypy/semanal.py", line 1667, in analyze_class
  File "mypy/semanal.py", line 1694, in analyze_class_body_common
  File "mypy/semanal.py", line 1777, in apply_class_plugin_hooks
  File "[redacted]/.venv/lib64/python3.8/site-packages/pydantic/mypy.py", line 182, in _pydantic_model_class_maker_callback
    return transformer.transform()
  File "[redacted]/.venv/lib64/python3.8/site-packages/pydantic/mypy.py", line 443, in transform
    self.add_initializer(fields, config, is_settings)
  File "[redacted]/.venv/lib64/python3.8/site-packages/pydantic/mypy.py", line 804, in add_initializer
    base_settings_init_arguments = base_settings_info.names['__init__'].node.arguments
AttributeError: attribute 'names' of 'TypeInfo' undefined
test.py:3: : note: use --pdb to drop into pdb
```

When running the command with `pdb` to print the `base_settings_info` we get the following:
```
-> base_settings_init_arguments = base_settings_info.names['__init__'].node.arguments
(Pdb) base_settings_info
*** AttributeError: attribute '_fullname' of 'TypeInfo' undefined
```

Requirements to reproduce:
```
annotated-types==0.5.0
mypy==1.4.1
mypy-extensions==1.0.0
pydantic==2.1.1
pydantic-core==2.4.0
pydantic-settings==2.0.2
python-dotenv==1.0.0
tomli==2.0.1
typing-extensions==4.7.1
```

mypy config:
```
[tool.mypy]
files = ["api", "tests"]

plugins = [
    "pydantic.mypy"
]
strict = true
```

### Example Code

```Python
from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
    API_HOST: str = "0.0.0.0"

    model_config = SettingsConfigDict(
        env_file=".env", env_file_encoding="utf-8"
    )
```


### Python, Pydantic & OS Version

```Text
pydantic version: 2.1.1
        pydantic-core version: 2.4.0
          pydantic-core build: profile=release pgo=true mimalloc=true
                 install path: [REDACTED]/.venv/lib/python3.8/site-packages/pydantic
               python version: 3.8.6 (default, Oct 27 2020, 09:13:12)  [GCC 9.3.1 20200408 (Red Hat 9.3.1-2)]
                     platform: Linux-3.10.0-1160.15.2.el7.x86_64-x86_64-with-glibc2.2.5
     optional deps. installed: ['typing-extensions']
```


Selected Assignee: @Kludex


Discussion:
I've tried your provided code but didn't get the mypy error you've reported.

maybe it's something related to your environment
Hello 👋 ,

 I have the same issue on my project with mypy and 
```
"pydantic[email]==2.1.1",
"pydantic-settings==2.0.2"
```
on Python 3.11.3.

The first time I run mypy it works fine but when I relaunch several times the error appears:

```
` base_settings_init_arguments = base_settings_info.names['__init__'].node.arguments
                                   ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: attribute 'names' of 'TypeInfo' undefined
`
```
It also happens when I restart it multiple times (usually when there’s a modification to the file from what I’ve noticed)

Resolving patch:
diff --git a/pydantic/mypy.py b/pydantic/mypy.py
--- a/pydantic/mypy.py
+++ b/pydantic/mypy.py
@@ -800,17 +800,17 @@ def add_initializer(self, fields: list[PydanticModelField], config: ModelConfigD
                 is_settings=is_settings,
             )
             if is_settings:
-                base_settings_info = self._api.lookup_fully_qualified(BASESETTINGS_FULLNAME).node.defn.info
-                base_settings_init_arguments = base_settings_info.names['__init__'].node.arguments
-                settings_init_arguments = []
-                a: Argument
-                for a in base_settings_init_arguments:
-                    if a.variable.name.startswith('__') or not a.variable.name.startswith('_'):
-                        continue
-                    analyzed_variable_type = self._api.anal_type(a.variable.type)
-                    variable = Var(a.variable.name, analyzed_variable_type)
-                    settings_init_arguments.append(Argument(variable, analyzed_variable_type, None, ARG_OPT))
-                args.extend(settings_init_arguments)
+                base_settings_node = self._api.lookup_fully_qualified(BASESETTINGS_FULLNAME).node
+                if '__init__' in base_settings_node.names:
+                    base_settings_init_node = base_settings_node.names['__init__'].node
+                    if base_settings_init_node is not None and base_settings_init_node.type is not None:
+                        func_type = base_settings_init_node.type
+                        for arg_idx, arg_name in enumerate(func_type.arg_names):
+                            if arg_name.startswith('__') or not arg_name.startswith('_'):
+                                continue
+                            analyzed_variable_type = self._api.anal_type(func_type.arg_types[arg_idx])
+                            variable = Var(arg_name, analyzed_variable_type)
+                            args.append(Argument(variable, analyzed_variable_type, None, ARG_OPT))
 
         if not self.should_init_forbid_extra(fields, config):
             var = Var('kwargs')


Test patch:
diff --git a/tests/mypy/modules/pydantic_settings.py b/tests/mypy/modules/pydantic_settings.py
--- a/tests/mypy/modules/pydantic_settings.py
+++ b/tests/mypy/modules/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -10,3 +10,12 @@ class Settings(BaseSettings):
 s = Settings(foo='test', _case_sensitive=True, _env_prefix='test__', _env_file='test')
 
 s = Settings(foo='test', _case_sensitive=1, _env_prefix=2, _env_file=3)
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
diff --git a/tests/mypy/outputs/1.0.1/mypy-default_ini/pydantic_settings.py b/tests/mypy/outputs/1.0.1/mypy-default_ini/pydantic_settings.py
--- a/tests/mypy/outputs/1.0.1/mypy-default_ini/pydantic_settings.py
+++ b/tests/mypy/outputs/1.0.1/mypy-default_ini/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -13,3 +13,12 @@ class Settings(BaseSettings):
 # MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "Optional[bool]"  [arg-type]
 # MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "Optional[str]"  [arg-type]
 # MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Optional[Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]]"  [arg-type]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
diff --git a/tests/mypy/outputs/1.0.1/mypy-plugin_ini/pydantic_settings.py b/tests/mypy/outputs/1.0.1/mypy-plugin_ini/pydantic_settings.py
--- a/tests/mypy/outputs/1.0.1/mypy-plugin_ini/pydantic_settings.py
+++ b/tests/mypy/outputs/1.0.1/mypy-plugin_ini/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -13,3 +13,12 @@ class Settings(BaseSettings):
 # MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "Optional[bool]"  [arg-type]
 # MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "Optional[str]"  [arg-type]
 # MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Optional[Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]]"  [arg-type]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
diff --git a/tests/mypy/outputs/1.0.1/pyproject-default_toml/pydantic_settings.py b/tests/mypy/outputs/1.0.1/pyproject-default_toml/pydantic_settings.py
--- a/tests/mypy/outputs/1.0.1/pyproject-default_toml/pydantic_settings.py
+++ b/tests/mypy/outputs/1.0.1/pyproject-default_toml/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -13,3 +13,12 @@ class Settings(BaseSettings):
 # MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "Optional[bool]"  [arg-type]
 # MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "Optional[str]"  [arg-type]
 # MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Optional[Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]]"  [arg-type]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
diff --git a/tests/mypy/outputs/1.0.1/pyproject-plugin_toml/pydantic_settings.py b/tests/mypy/outputs/1.0.1/pyproject-plugin_toml/pydantic_settings.py
--- a/tests/mypy/outputs/1.0.1/pyproject-plugin_toml/pydantic_settings.py
+++ b/tests/mypy/outputs/1.0.1/pyproject-plugin_toml/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -13,3 +13,12 @@ class Settings(BaseSettings):
 # MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "Optional[bool]"  [arg-type]
 # MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "Optional[str]"  [arg-type]
 # MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Optional[Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]]"  [arg-type]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
diff --git a/tests/mypy/outputs/1.1.1/mypy-default_ini/pydantic_settings.py b/tests/mypy/outputs/1.1.1/mypy-default_ini/pydantic_settings.py
--- a/tests/mypy/outputs/1.1.1/mypy-default_ini/pydantic_settings.py
+++ b/tests/mypy/outputs/1.1.1/mypy-default_ini/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -17,3 +17,13 @@ class Settings(BaseSettings):
 # MYPY: error: Unexpected keyword argument "_case_sensitive" for "Settings"  [call-arg]
 # MYPY: error: Unexpected keyword argument "_env_prefix" for "Settings"  [call-arg]
 # MYPY: error: Unexpected keyword argument "_env_file" for "Settings"  [call-arg]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
+# MYPY: error: Missing named argument "bar" for "SettingsWithConfigDict"  [call-arg]
diff --git a/tests/mypy/outputs/1.1.1/mypy-plugin_ini/pydantic_settings.py b/tests/mypy/outputs/1.1.1/mypy-plugin_ini/pydantic_settings.py
deleted file mode 100644
--- a/tests/mypy/outputs/1.1.1/mypy-plugin_ini/pydantic_settings.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from pydantic_settings import BaseSettings
-
-
-class Settings(BaseSettings):
-    foo: str
-
-
-s = Settings()
-
-s = Settings(foo='test', _case_sensitive=True, _env_prefix='test__', _env_file='test')
-
-s = Settings(foo='test', _case_sensitive=1, _env_prefix=2, _env_file=3)
-# MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "Optional[bool]"  [arg-type]
-# MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "Optional[str]"  [arg-type]
-# MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Optional[Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]]"  [arg-type]
diff --git a/tests/mypy/outputs/1.1.1/pyproject-default_toml/pydantic_settings.py b/tests/mypy/outputs/1.1.1/pyproject-default_toml/pydantic_settings.py
--- a/tests/mypy/outputs/1.1.1/pyproject-default_toml/pydantic_settings.py
+++ b/tests/mypy/outputs/1.1.1/pyproject-default_toml/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -17,3 +17,13 @@ class Settings(BaseSettings):
 # MYPY: error: Unexpected keyword argument "_case_sensitive" for "Settings"  [call-arg]
 # MYPY: error: Unexpected keyword argument "_env_prefix" for "Settings"  [call-arg]
 # MYPY: error: Unexpected keyword argument "_env_file" for "Settings"  [call-arg]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
+# MYPY: error: Missing named argument "bar" for "SettingsWithConfigDict"  [call-arg]
diff --git a/tests/mypy/outputs/1.1.1/pyproject-plugin_toml/pydantic_settings.py b/tests/mypy/outputs/1.1.1/pyproject-plugin_toml/pydantic_settings.py
deleted file mode 100644
--- a/tests/mypy/outputs/1.1.1/pyproject-plugin_toml/pydantic_settings.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from pydantic_settings import BaseSettings
-
-
-class Settings(BaseSettings):
-    foo: str
-
-
-s = Settings()
-
-s = Settings(foo='test', _case_sensitive=True, _env_prefix='test__', _env_file='test')
-
-s = Settings(foo='test', _case_sensitive=1, _env_prefix=2, _env_file=3)
-# MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "Optional[bool]"  [arg-type]
-# MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "Optional[str]"  [arg-type]
-# MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Optional[Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]]"  [arg-type]
diff --git a/tests/mypy/outputs/1.4.1/mypy-plugin_ini/pydantic_settings.py b/tests/mypy/outputs/1.4.1/mypy-plugin_ini/pydantic_settings.py
--- a/tests/mypy/outputs/1.4.1/mypy-plugin_ini/pydantic_settings.py
+++ b/tests/mypy/outputs/1.4.1/mypy-plugin_ini/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -13,3 +13,12 @@ class Settings(BaseSettings):
 # MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "bool | None"  [arg-type]
 # MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "str | None"  [arg-type]
 # MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Path | str | list[Path | str] | tuple[Path | str, ...] | None"  [arg-type]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()
diff --git a/tests/mypy/outputs/1.4.1/pyproject-plugin_toml/pydantic_settings.py b/tests/mypy/outputs/1.4.1/pyproject-plugin_toml/pydantic_settings.py
--- a/tests/mypy/outputs/1.4.1/pyproject-plugin_toml/pydantic_settings.py
+++ b/tests/mypy/outputs/1.4.1/pyproject-plugin_toml/pydantic_settings.py
@@ -1,4 +1,4 @@
-from pydantic_settings import BaseSettings
+from pydantic_settings import BaseSettings, SettingsConfigDict
 
 
 class Settings(BaseSettings):
@@ -13,3 +13,12 @@ class Settings(BaseSettings):
 # MYPY: error: Argument "_case_sensitive" to "Settings" has incompatible type "int"; expected "bool | None"  [arg-type]
 # MYPY: error: Argument "_env_prefix" to "Settings" has incompatible type "int"; expected "str | None"  [arg-type]
 # MYPY: error: Argument "_env_file" to "Settings" has incompatible type "int"; expected "Path | str | list[Path | str] | tuple[Path | str, ...] | None"  [arg-type]
+
+
+class SettingsWithConfigDict(BaseSettings):
+    bar: str
+
+    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8')
+
+
+scd = SettingsWithConfigDict()