Skip to content

Allow dynamic models created with create_model() to be used as annotations in the Mypy plugin#12879

Merged
Viicos merged 4 commits intopydantic:mainfrom
Br1an67:fix/issue-12031-create-model-mypy
Mar 7, 2026
Merged

Allow dynamic models created with create_model() to be used as annotations in the Mypy plugin#12879
Viicos merged 4 commits intopydantic:mainfrom
Br1an67:fix/issue-12031-create-model-mypy

Conversation

@Br1an67
Copy link
Copy Markdown
Contributor

@Br1an67 Br1an67 commented Mar 1, 2026

Change Summary

Add a get_dynamic_class_hook to the pydantic mypy plugin so that variables assigned from create_model() are recognized as proper class types. This allows them to be used in type annotations, isinstance() checks, and as function parameter types without mypy errors.

The hook also handles the __base__ keyword argument so the synthetic class inherits from the correct base when specified.

Related issue number

fix #12031

Checklist

  • The pull request title is a good description of the changes made and is prefixed with the relevant project
  • I have run make lint and make format
  • tests - I have added / edited tests to verify my changes work
  • docs - N/A (code-only change)
  • changes - changes are backward-compatible and do not introduce breaking changes

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 1, 2026

Merging this PR will not alter performance

✅ 212 untouched benchmarks


Comparing Br1an67:fix/issue-12031-create-model-mypy (796db88) with main (0b7b855)

Open in CodSpeed

Implement a dynamic class hook so that variables assigned from
create_model() are recognized by mypy as proper class types rather than
plain variables. This allows them to be used in type annotations,
isinstance() checks, and as function parameter types.

The hook handles the __base__ keyword argument so the synthetic class
inherits from the correct base when specified.
@Br1an67 Br1an67 force-pushed the fix/issue-12031-create-model-mypy branch from 3d14ef8 to 3dd07ba Compare March 2, 2026 07:30
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 2, 2026

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  pydantic
  mypy.py 193-194, 199-201
Project Total  

This report was generated by python-coverage-comment-action

Copy link
Copy Markdown
Member

@Viicos Viicos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also apply the following diff:

diff --git a/tests/mypy/modules/create_model_var.py b/tests/mypy/modules/create_model_var.py
new file mode 100644
index 000000000..cc2c72b1b
--- /dev/null
+++ b/tests/mypy/modules/create_model_var.py
@@ -0,0 +1,12 @@
+from pydantic import BaseModel, create_model
+
+
+class Model(BaseModel):
+    a: int
+
+
+SubModel = create_model('SubModel', __base__=Model)
+
+
+class Main(BaseModel):
+    sub: SubModel
diff --git a/tests/mypy/outputs/mypy-plugin_ini/create_model_var.py b/tests/mypy/outputs/mypy-plugin_ini/create_model_var.py
new file mode 100644
index 000000000..cc2c72b1b
--- /dev/null
+++ b/tests/mypy/outputs/mypy-plugin_ini/create_model_var.py
@@ -0,0 +1,12 @@
+from pydantic import BaseModel, create_model
+
+
+class Model(BaseModel):
+    a: int
+
+
+SubModel = create_model('SubModel', __base__=Model)
+
+
+class Main(BaseModel):
+    sub: SubModel
diff --git a/tests/mypy/test_mypy.py b/tests/mypy/test_mypy.py
index 679d184f9..4fa052776 100644
--- a/tests/mypy/test_mypy.py
+++ b/tests/mypy/test_mypy.py
@@ -109,6 +109,7 @@ cases: list[ParameterSet | tuple[str, str]] = [
         ('mypy-plugin.ini', 'root_models.py'),
         ('mypy-plugin.ini', 'plugin_strict_fields.py'),
         ('mypy-plugin.ini', 'final_with_default.py'),
+        ('mypy-plugin.ini', 'create_model_var.py'),
         ('mypy-plugin-strict-no-any.ini', 'dataclass_no_any.py'),
         ('mypy-plugin-very-strict.ini', 'metaclass_args.py'),
         ('pyproject-plugin-no-strict-optional.toml', 'no_strict_optional.py'),```

Comment thread pydantic/mypy.py Outdated
@pydantic-hooky pydantic-hooky Bot added the awaiting author revision awaiting changes from the PR author label Mar 5, 2026
@Viicos Viicos changed the title Add get_dynamic_class_hook for create_model in mypy plugin Add get_dynamic_class_hook() for create_model() in mypy plugin Mar 5, 2026
@Br1an67
Copy link
Copy Markdown
Contributor Author

Br1an67 commented Mar 6, 2026

Thanks for the feedback! Updated: Added test cases for create_model_var as requested. Let me know if there's anything else.

@Br1an67 Br1an67 force-pushed the fix/issue-12031-create-model-mypy branch from b68db51 to abe4228 Compare March 6, 2026 04:40
Viicos and others added 2 commits March 6, 2026 20:35
Fix typo where CREATE_MODEL_FULLNAMES (plural) was used instead of
CREATE_MODEL_FULLNAME (singular), which was causing F821 lint errors.
@Br1an67 Br1an67 force-pushed the fix/issue-12031-create-model-mypy branch from 7ef81c1 to 796db88 Compare March 7, 2026 02:29
@Viicos Viicos changed the title Add get_dynamic_class_hook() for create_model() in mypy plugin Allow dynamic models created with create_model() to be used as annotations in the Mypy plugin Mar 7, 2026
@Viicos Viicos merged commit b59bcae into pydantic:main Mar 7, 2026
81 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting author revision awaiting changes from the PR author relnotes-fix Used for bugfixes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add get_dynamic_class_hook to create_model in pydantic mypy plugin

2 participants