python-pydantic/0001-Bug-fix-for-forward-refs-in-generics.patch
2024-05-22 16:42:38 +08:00

75 lines
2.6 KiB
Diff

From 51b4751b1d594e7e6c48b13c6be06df15181c6e4 Mon Sep 17 00:00:00 2001
From: mark-todd <60781787+mark-todd@users.noreply.github.com>
Date: Fri, 23 Jun 2023 17:06:59 +0100
Subject: [PATCH] Bug fix for forward refs in generics (#6157)
pr:https://github.com/pydantic/pydantic/pull/6157/
---
changes/6130-mark-todd.md | 1 +
pydantic/generics.py | 14 ++++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
create mode 100644 changes/6130-mark-todd.md
diff --git a/changes/6130-mark-todd.md b/changes/6130-mark-todd.md
new file mode 100644
index 00000000..bb27325a
--- /dev/null
+++ b/changes/6130-mark-todd.md
@@ -0,0 +1 @@
+Fixed bug with generics receiving forward refs
diff --git a/pydantic/generics.py b/pydantic/generics.py
index 5dcda6df..a75b6b98 100644
--- a/pydantic/generics.py
+++ b/pydantic/generics.py
@@ -6,6 +6,7 @@ from typing import (
Any,
ClassVar,
Dict,
+ ForwardRef,
Generic,
Iterator,
List,
@@ -19,7 +20,7 @@ from typing import (
)
from weakref import WeakKeyDictionary, WeakValueDictionary
-from typing_extensions import Annotated
+from typing_extensions import Annotated, Literal as ExtLiteral
from .class_validators import gather_all_validators
from .fields import DeferredType
@@ -30,6 +31,8 @@ from .utils import all_identical, lenient_issubclass
if sys.version_info >= (3, 10):
from typing import _UnionGenericAlias
+if sys.version_info >= (3, 8):
+ from typing import Literal
GenericModelT = TypeVar('GenericModelT', bound='GenericModel')
TypeVarType = Any # since mypy doesn't allow the use of TypeVar as a type
@@ -267,6 +270,8 @@ def replace_types(type_: Any, type_map: Mapping[Any, Any]) -> Any:
annotated_type, *annotations = type_args
return Annotated[replace_types(annotated_type, type_map), tuple(annotations)]
+ if (origin_type is ExtLiteral) or (sys.version_info >= (3, 8) and origin_type is Literal):
+ return type_map.get(type_, type_)
# Having type args is a good indicator that this is a typing module
# class instantiation or a generic alias of some sort.
if type_args:
@@ -317,7 +322,12 @@ def replace_types(type_: Any, type_map: Mapping[Any, Any]) -> Any:
# If all else fails, we try to resolve the type directly and otherwise just
# return the input with no modifications.
- return type_map.get(type_, type_)
+ new_type = type_map.get(type_, type_)
+ # Convert string to ForwardRef
+ if isinstance(new_type, str):
+ return ForwardRef(new_type)
+ else:
+ return new_type
def check_parameters_count(cls: Type[GenericModel], parameters: Tuple[Any, ...]) -> None:
--
2.43.0