mirror of
https://github.com/gentoo-mirror/gentoo.git
synced 2026-09-24 04:59:14 -07:00
dev-python/typing-extensions: add missing patch
Couldn't test w/ py3.14 as don't have it installed yet, but passes tests otherwise. Closes: https://bugs.gentoo.org/955647 Signed-off-by: Sam James <sam@gentoo.org>
This commit is contained in:
@@ -0,0 +1,596 @@
|
||||
https://github.com/python/typing_extensions/pull/566
|
||||
https://github.com/python/typing_extensions/pull/592
|
||||
(CI bits dropped, test_fwdref_value_is_cached hunk added at the end as
|
||||
didn't apply cleanly.)
|
||||
|
||||
From 32dde8e38975df88336107b112300483325010ef Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Tue, 1 Apr 2025 08:26:52 -0700
|
||||
Subject: [PATCH 1/3] Fix test failures on Python 3.14
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -882,10 +882,12 @@ async def coro(self):
|
||||
|
||||
class DeprecatedCoroTests(BaseTestCase):
|
||||
def test_asyncio_iscoroutinefunction(self):
|
||||
- self.assertFalse(asyncio.coroutines.iscoroutinefunction(func))
|
||||
- self.assertFalse(asyncio.coroutines.iscoroutinefunction(Cls.func))
|
||||
- self.assertTrue(asyncio.coroutines.iscoroutinefunction(coro))
|
||||
- self.assertTrue(asyncio.coroutines.iscoroutinefunction(Cls.coro))
|
||||
+ with warnings.catch_warnings():
|
||||
+ warnings.simplefilter("ignore", DeprecationWarning)
|
||||
+ self.assertFalse(asyncio.coroutines.iscoroutinefunction(func))
|
||||
+ self.assertFalse(asyncio.coroutines.iscoroutinefunction(Cls.func))
|
||||
+ self.assertTrue(asyncio.coroutines.iscoroutinefunction(coro))
|
||||
+ self.assertTrue(asyncio.coroutines.iscoroutinefunction(Cls.coro))
|
||||
|
||||
@skipUnless(TYPING_3_12_ONLY or TYPING_3_13_0_RC, "inspect.iscoroutinefunction works differently on Python < 3.12")
|
||||
def test_inspect_iscoroutinefunction(self):
|
||||
@@ -7209,7 +7211,7 @@ def test_cannot_instantiate_vars(self):
|
||||
|
||||
def test_bound_errors(self):
|
||||
with self.assertRaises(TypeError):
|
||||
- TypeVar('X', bound=Union)
|
||||
+ TypeVar('X', bound=Optional)
|
||||
with self.assertRaises(TypeError):
|
||||
TypeVar('X', str, float, bound=Employee)
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
@@ -8190,19 +8192,25 @@ def f2(a: "undefined"): # noqa: F821
|
||||
get_annotations(f2, format=Format.FORWARDREF),
|
||||
{"a": "undefined"},
|
||||
)
|
||||
- self.assertEqual(get_annotations(f2, format=2), {"a": "undefined"})
|
||||
+ self.assertEqual(
|
||||
+ get_annotations(f2, format=Format.FORWARDREF.value),
|
||||
+ {"a": "undefined"},
|
||||
+ )
|
||||
|
||||
self.assertEqual(
|
||||
get_annotations(f1, format=Format.STRING),
|
||||
{"a": "int"},
|
||||
)
|
||||
- self.assertEqual(get_annotations(f1, format=3), {"a": "int"})
|
||||
+ self.assertEqual(
|
||||
+ get_annotations(f1, format=Format.STRING.value),
|
||||
+ {"a": "int"},
|
||||
+ )
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
get_annotations(f1, format=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
- get_annotations(f1, format=4)
|
||||
+ get_annotations(f1, format=42)
|
||||
|
||||
def test_custom_object_with_annotations(self):
|
||||
class C:
|
||||
@@ -8240,6 +8248,8 @@ def foo(a: int, b: str):
|
||||
|
||||
foo.__annotations__ = {"a": "foo", "b": "str"}
|
||||
for format in Format:
|
||||
+ if format is Format.VALUE_WITH_FAKE_GLOBALS:
|
||||
+ continue
|
||||
with self.subTest(format=format):
|
||||
self.assertEqual(
|
||||
get_annotations(foo, format=format),
|
||||
--- a/src/typing_extensions.py
|
||||
+++ b/src/typing_extensions.py
|
||||
@@ -4139,8 +4139,9 @@ def __eq__(self, other: object) -> bool:
|
||||
|
||||
class Format(enum.IntEnum):
|
||||
VALUE = 1
|
||||
- FORWARDREF = 2
|
||||
- STRING = 3
|
||||
+ VALUE_WITH_FAKE_GLOBALS = 2
|
||||
+ FORWARDREF = 3
|
||||
+ STRING = 4
|
||||
|
||||
|
||||
if _PEP_649_OR_749_IMPLEMENTED:
|
||||
@@ -4184,6 +4185,8 @@ def get_annotations(obj, *, globals=None, locals=None, eval_str=False,
|
||||
|
||||
"""
|
||||
format = Format(format)
|
||||
+ if format is Format.VALUE_WITH_FAKE_GLOBALS:
|
||||
+ raise ValueError("The VALUE_WITH_FAKE_GLOBALS format is for internal use only")
|
||||
|
||||
if eval_str and format is not Format.VALUE:
|
||||
raise ValueError("eval_str=True is only supported with format=Format.VALUE")
|
||||
|
||||
From c98e556ee2e4c7b9964297d827ef57da4d916b3d Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Tue, 1 Apr 2025 08:31:01 -0700
|
||||
Subject: [PATCH 2/3] test & lint
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -8248,13 +8248,18 @@ def foo(a: int, b: str):
|
||||
|
||||
foo.__annotations__ = {"a": "foo", "b": "str"}
|
||||
for format in Format:
|
||||
- if format is Format.VALUE_WITH_FAKE_GLOBALS:
|
||||
- continue
|
||||
with self.subTest(format=format):
|
||||
- self.assertEqual(
|
||||
- get_annotations(foo, format=format),
|
||||
- {"a": "foo", "b": "str"},
|
||||
- )
|
||||
+ if format is Format.VALUE_WITH_FAKE_GLOBALS:
|
||||
+ with self.assertRaisesRegex(
|
||||
+ ValueError,
|
||||
+ "The VALUE_WITH_FAKE_GLOBALS format is for internal use only"
|
||||
+ ):
|
||||
+ get_annotations(foo, format=format)
|
||||
+ else:
|
||||
+ self.assertEqual(
|
||||
+ get_annotations(foo, format=format),
|
||||
+ {"a": "foo", "b": "str"},
|
||||
+ )
|
||||
|
||||
self.assertEqual(
|
||||
get_annotations(foo, eval_str=True, locals=locals()),
|
||||
--- a/src/typing_extensions.py
|
||||
+++ b/src/typing_extensions.py
|
||||
@@ -4186,7 +4186,9 @@ def get_annotations(obj, *, globals=None, locals=None, eval_str=False,
|
||||
"""
|
||||
format = Format(format)
|
||||
if format is Format.VALUE_WITH_FAKE_GLOBALS:
|
||||
- raise ValueError("The VALUE_WITH_FAKE_GLOBALS format is for internal use only")
|
||||
+ raise ValueError(
|
||||
+ "The VALUE_WITH_FAKE_GLOBALS format is for internal use only"
|
||||
+ )
|
||||
|
||||
if eval_str and format is not Format.VALUE:
|
||||
raise ValueError("eval_str=True is only supported with format=Format.VALUE")
|
||||
|
||||
From adfb57a83f358e26905531407edf99a7346e22fc Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Thu, 10 Apr 2025 07:09:20 -0700
|
||||
Subject: [PATCH 3/3] Update src/test_typing_extensions.py
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -8196,6 +8196,7 @@ def f2(a: "undefined"): # noqa: F821
|
||||
get_annotations(f2, format=Format.FORWARDREF),
|
||||
{"a": "undefined"},
|
||||
)
|
||||
+ # Test that the raw int also works
|
||||
self.assertEqual(
|
||||
get_annotations(f2, format=Format.FORWARDREF.value),
|
||||
{"a": "undefined"},
|
||||
From 610ad76f7c4b8ff67deb6d688c00ccc7530ef363 Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Mon, 5 May 2025 07:52:14 -0700
|
||||
Subject: [PATCH 1/5] Fix 3.14
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -5152,6 +5152,65 @@ def test_inline(self):
|
||||
self.assertIs(type(inst), dict)
|
||||
self.assertEqual(inst["a"], 1)
|
||||
|
||||
+ def test_annotations(self):
|
||||
+ # _type_check is applied
|
||||
+ with self.assertRaisesRegex(TypeError, "Plain typing.Final is not valid as type argument"):
|
||||
+ class X(TypedDict):
|
||||
+ a: Final
|
||||
+
|
||||
+ # _type_convert is applied
|
||||
+ class Y(TypedDict):
|
||||
+ a: None
|
||||
+ b: "int"
|
||||
+ if sys.version_info >= (3, 14):
|
||||
+ import annotationlib
|
||||
+ from test.support import EqualToForwardRef
|
||||
+
|
||||
+ fwdref = EqualToForwardRef('int', module=__name__)
|
||||
+ self.assertEqual(Y.__annotations__, {'a': type(None), 'b': fwdref})
|
||||
+ self.assertEqual(Y.__annotate__(annotationlib.Format.FORWARDREF), {'a': type(None), 'b': fwdref})
|
||||
+ else:
|
||||
+ self.assertEqual(Y.__annotations__, {'a': type(None), 'b': typing.ForwardRef('int', module=__name__)})
|
||||
+
|
||||
+ @skipUnless(TYPING_3_14_0, "Only supported on 3.14")
|
||||
+ def test_delayed_type_check(self):
|
||||
+ # _type_check is also applied later
|
||||
+ class Z(TypedDict):
|
||||
+ a: undefined
|
||||
+
|
||||
+ with self.assertRaises(NameError):
|
||||
+ Z.__annotations__
|
||||
+
|
||||
+ undefined = Final
|
||||
+ with self.assertRaisesRegex(TypeError, "Plain typing.Final is not valid as type argument"):
|
||||
+ Z.__annotations__
|
||||
+
|
||||
+ undefined = None
|
||||
+ self.assertEqual(Z.__annotations__, {'a': type(None)})
|
||||
+
|
||||
+ @skipUnless(TYPING_3_14_0, "Only supported on 3.14")
|
||||
+ def test_deferred_evaluation(self):
|
||||
+ class A(TypedDict):
|
||||
+ x: NotRequired[undefined]
|
||||
+ y: ReadOnly[undefined]
|
||||
+ z: Required[undefined]
|
||||
+
|
||||
+ self.assertEqual(A.__required_keys__, frozenset({'y', 'z'}))
|
||||
+ self.assertEqual(A.__optional_keys__, frozenset({'x'}))
|
||||
+ self.assertEqual(A.__readonly_keys__, frozenset({'y'}))
|
||||
+ self.assertEqual(A.__mutable_keys__, frozenset({'x', 'z'}))
|
||||
+
|
||||
+ with self.assertRaises(NameError):
|
||||
+ A.__annotations__
|
||||
+
|
||||
+ import annotationlib
|
||||
+ self.assertEqual(
|
||||
+ A.__annotate__(annotationlib.Format.STRING),
|
||||
+ {'x': 'NotRequired[undefined]', 'y': 'ReadOnly[undefined]',
|
||||
+ 'z': 'Required[undefined]'},
|
||||
+ )
|
||||
+
|
||||
+
|
||||
class AnnotatedTests(BaseTestCase):
|
||||
|
||||
def test_repr(self):
|
||||
@@ -8956,7 +9008,7 @@ class Y(Generic[Tx]):
|
||||
self.assertEqual(get_args(evaluated_ref1b), (Y[Tx],))
|
||||
|
||||
with self.subTest("nested string of TypeVar"):
|
||||
- evaluated_ref2 = evaluate_forward_ref(typing.ForwardRef("""Y["Y['Tx']"]"""), locals={"Y": Y})
|
||||
+ evaluated_ref2 = evaluate_forward_ref(typing.ForwardRef("""Y["Y['Tx']"]"""), locals={"Y": Y, "Tx": Tx})
|
||||
self.assertEqual(get_origin(evaluated_ref2), Y)
|
||||
self.assertEqual(get_args(evaluated_ref2), (Y[Tx],))
|
||||
|
||||
--- a/src/typing_extensions.py
|
||||
+++ b/src/typing_extensions.py
|
||||
@@ -14,6 +14,9 @@
|
||||
import typing
|
||||
import warnings
|
||||
|
||||
+if sys.version_info >= (3, 14):
|
||||
+ import annotationlib
|
||||
+
|
||||
__all__ = [
|
||||
# Super-special typing primitives.
|
||||
'Any',
|
||||
@@ -1018,21 +1021,27 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None,
|
||||
tp_dict.__orig_bases__ = bases
|
||||
|
||||
annotations = {}
|
||||
+ own_annotate = None
|
||||
if "__annotations__" in ns:
|
||||
own_annotations = ns["__annotations__"]
|
||||
- elif "__annotate__" in ns:
|
||||
- # TODO: Use inspect.VALUE here, and make the annotations lazily evaluated
|
||||
- own_annotations = ns["__annotate__"](1)
|
||||
+ elif sys.version_info >= (3, 14):
|
||||
+ own_annotate = annotationlib.get_annotate_from_class_namespace(ns)
|
||||
+ if own_annotate is not None:
|
||||
+ own_annotations = annotationlib.call_annotate_function(
|
||||
+ own_annotate, annotationlib.Format.FORWARDREF, owner=tp_dict
|
||||
+ )
|
||||
+ else:
|
||||
+ own_annotations = {}
|
||||
else:
|
||||
own_annotations = {}
|
||||
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
|
||||
if _TAKES_MODULE:
|
||||
- own_annotations = {
|
||||
+ own_checked_annotations = {
|
||||
n: typing._type_check(tp, msg, module=tp_dict.__module__)
|
||||
for n, tp in own_annotations.items()
|
||||
}
|
||||
else:
|
||||
- own_annotations = {
|
||||
+ own_checked_annotations = {
|
||||
n: typing._type_check(tp, msg)
|
||||
for n, tp in own_annotations.items()
|
||||
}
|
||||
@@ -1045,7 +1054,8 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None,
|
||||
for base in bases:
|
||||
base_dict = base.__dict__
|
||||
|
||||
- annotations.update(base_dict.get('__annotations__', {}))
|
||||
+ if sys.version_info <= (3, 14):
|
||||
+ annotations.update(base_dict.get('__annotations__', {}))
|
||||
required_keys.update(base_dict.get('__required_keys__', ()))
|
||||
optional_keys.update(base_dict.get('__optional_keys__', ()))
|
||||
readonly_keys.update(base_dict.get('__readonly_keys__', ()))
|
||||
@@ -1055,8 +1065,8 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None,
|
||||
# is retained for backwards compatibility, but only for Python
|
||||
# 3.13 and lower.
|
||||
if (closed and sys.version_info < (3, 14)
|
||||
- and "__extra_items__" in own_annotations):
|
||||
- annotation_type = own_annotations.pop("__extra_items__")
|
||||
+ and "__extra_items__" in own_checked_annotations):
|
||||
+ annotation_type = own_checked_annotations.pop("__extra_items__")
|
||||
qualifiers = set(_get_typeddict_qualifiers(annotation_type))
|
||||
if Required in qualifiers:
|
||||
raise TypeError(
|
||||
@@ -1070,8 +1080,8 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None,
|
||||
)
|
||||
extra_items_type = annotation_type
|
||||
|
||||
- annotations.update(own_annotations)
|
||||
- for annotation_key, annotation_type in own_annotations.items():
|
||||
+ annotations.update(own_checked_annotations)
|
||||
+ for annotation_key, annotation_type in own_checked_annotations.items():
|
||||
qualifiers = set(_get_typeddict_qualifiers(annotation_type))
|
||||
|
||||
if Required in qualifiers:
|
||||
@@ -1089,7 +1099,38 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None,
|
||||
mutable_keys.add(annotation_key)
|
||||
readonly_keys.discard(annotation_key)
|
||||
|
||||
- tp_dict.__annotations__ = annotations
|
||||
+ if sys.version_info >= (3, 14):
|
||||
+ def __annotate__(format):
|
||||
+ annos = {}
|
||||
+ for base in bases:
|
||||
+ if base is Generic:
|
||||
+ continue
|
||||
+ base_annotate = base.__annotate__
|
||||
+ if base_annotate is None:
|
||||
+ continue
|
||||
+ base_annos = annotationlib.call_annotate_function(
|
||||
+ base.__annotate__, format, owner=base)
|
||||
+ annos.update(base_annos)
|
||||
+ if own_annotate is not None:
|
||||
+ own = annotationlib.call_annotate_function(
|
||||
+ own_annotate, format, owner=tp_dict)
|
||||
+ if format != annotationlib.Format.STRING:
|
||||
+ own = {
|
||||
+ n: typing._type_check(tp, msg, module=tp_dict.__module__)
|
||||
+ for n, tp in own.items()
|
||||
+ }
|
||||
+ elif format == annotationlib.Format.STRING:
|
||||
+ own = annotationlib.annotations_to_string(own_annotations)
|
||||
+ elif format in (annotationlib.Format.FORWARDREF, annotationlib.Format.VALUE):
|
||||
+ own = own_checked_annotations
|
||||
+ else:
|
||||
+ raise NotImplementedError(format)
|
||||
+ annos.update(own)
|
||||
+ return annos
|
||||
+
|
||||
+ tp_dict.__annotate__ = __annotate__
|
||||
+ else:
|
||||
+ tp_dict.__annotations__ = annotations
|
||||
tp_dict.__required_keys__ = frozenset(required_keys)
|
||||
tp_dict.__optional_keys__ = frozenset(optional_keys)
|
||||
tp_dict.__readonly_keys__ = frozenset(readonly_keys)
|
||||
|
||||
From 83ff33aad4e53ecbd026bfdd683b3c460708e045 Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Mon, 5 May 2025 08:03:32 -0700
|
||||
Subject: [PATCH 2/5] fix lint
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -5176,7 +5176,7 @@ class Y(TypedDict):
|
||||
def test_delayed_type_check(self):
|
||||
# _type_check is also applied later
|
||||
class Z(TypedDict):
|
||||
- a: undefined
|
||||
+ a: undefined # noqa: F821
|
||||
|
||||
with self.assertRaises(NameError):
|
||||
Z.__annotations__
|
||||
@@ -5185,15 +5185,15 @@ class Z(TypedDict):
|
||||
with self.assertRaisesRegex(TypeError, "Plain typing.Final is not valid as type argument"):
|
||||
Z.__annotations__
|
||||
|
||||
- undefined = None
|
||||
+ undefined = None # noqa: F841
|
||||
self.assertEqual(Z.__annotations__, {'a': type(None)})
|
||||
|
||||
@skipUnless(TYPING_3_14_0, "Only supported on 3.14")
|
||||
def test_deferred_evaluation(self):
|
||||
class A(TypedDict):
|
||||
- x: NotRequired[undefined]
|
||||
- y: ReadOnly[undefined]
|
||||
- z: Required[undefined]
|
||||
+ x: NotRequired[undefined] # noqa: F821
|
||||
+ y: ReadOnly[undefined] # noqa: F821
|
||||
+ z: Required[undefined] # noqa: F821
|
||||
|
||||
self.assertEqual(A.__required_keys__, frozenset({'y', 'z'}))
|
||||
self.assertEqual(A.__optional_keys__, frozenset({'x'}))
|
||||
--- a/src/typing_extensions.py
|
||||
+++ b/src/typing_extensions.py
|
||||
@@ -1025,10 +1025,14 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None,
|
||||
if "__annotations__" in ns:
|
||||
own_annotations = ns["__annotations__"]
|
||||
elif sys.version_info >= (3, 14):
|
||||
- own_annotate = annotationlib.get_annotate_from_class_namespace(ns)
|
||||
+ if hasattr(annotationlib, "get_annotate_from_class_namespace"):
|
||||
+ own_annotate = annotationlib.get_annotate_from_class_namespace(ns)
|
||||
+ else:
|
||||
+ # 3.14.0a7 and earlier
|
||||
+ own_annotate = ns.get("__annotate__")
|
||||
if own_annotate is not None:
|
||||
own_annotations = annotationlib.call_annotate_function(
|
||||
- own_annotate, annotationlib.Format.FORWARDREF, owner=tp_dict
|
||||
+ own_annotate, Format.FORWARDREF, owner=tp_dict
|
||||
)
|
||||
else:
|
||||
own_annotations = {}
|
||||
@@ -1114,14 +1118,14 @@ def __annotate__(format):
|
||||
if own_annotate is not None:
|
||||
own = annotationlib.call_annotate_function(
|
||||
own_annotate, format, owner=tp_dict)
|
||||
- if format != annotationlib.Format.STRING:
|
||||
+ if format != Format.STRING:
|
||||
own = {
|
||||
n: typing._type_check(tp, msg, module=tp_dict.__module__)
|
||||
for n, tp in own.items()
|
||||
}
|
||||
- elif format == annotationlib.Format.STRING:
|
||||
+ elif format == Format.STRING:
|
||||
own = annotationlib.annotations_to_string(own_annotations)
|
||||
- elif format in (annotationlib.Format.FORWARDREF, annotationlib.Format.VALUE):
|
||||
+ elif format in (Format.FORWARDREF, Format.VALUE):
|
||||
own = own_checked_annotations
|
||||
else:
|
||||
raise NotImplementedError(format)
|
||||
|
||||
From d932665dc4a97d25e06b77063521baf97e89aceb Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Mon, 5 May 2025 08:06:31 -0700
|
||||
Subject: [PATCH 3/5] fix 3.9/3.10
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -5154,9 +5154,9 @@ def test_inline(self):
|
||||
|
||||
def test_annotations(self):
|
||||
# _type_check is applied
|
||||
- with self.assertRaisesRegex(TypeError, "Plain typing.Final is not valid as type argument"):
|
||||
+ with self.assertRaisesRegex(TypeError, "Plain typing.Optional is not valid as type argument"):
|
||||
class X(TypedDict):
|
||||
- a: Final
|
||||
+ a: Optional
|
||||
|
||||
# _type_convert is applied
|
||||
class Y(TypedDict):
|
||||
|
||||
From 34293d775b66bc6c6370b517d11f80719fb4d316 Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Mon, 5 May 2025 08:20:26 -0700
|
||||
Subject: [PATCH 4/5] fix a7?
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -103,6 +103,11 @@
|
||||
runtime_checkable,
|
||||
)
|
||||
|
||||
+if sys.version_info >= (3, 14):
|
||||
+ from test.support import EqualToForwardRef
|
||||
+else:
|
||||
+ EqualToForwardRef = typing.ForwardRef
|
||||
+
|
||||
NoneType = type(None)
|
||||
T = TypeVar("T")
|
||||
KT = TypeVar("KT")
|
||||
@@ -5164,7 +5169,6 @@ class Y(TypedDict):
|
||||
b: "int"
|
||||
if sys.version_info >= (3, 14):
|
||||
import annotationlib
|
||||
- from test.support import EqualToForwardRef
|
||||
|
||||
fwdref = EqualToForwardRef('int', module=__name__)
|
||||
self.assertEqual(Y.__annotations__, {'a': type(None), 'b': fwdref})
|
||||
@@ -6022,7 +6026,7 @@ def test_substitution(self):
|
||||
U2 = Unpack[Ts]
|
||||
self.assertEqual(C2[U1], (str, int, str))
|
||||
self.assertEqual(C2[U2], (str, Unpack[Ts]))
|
||||
- self.assertEqual(C2["U2"], (str, typing.ForwardRef("U2")))
|
||||
+ self.assertEqual(C2["U2"], (str, EqualToForwardRef("U2")))
|
||||
|
||||
if (3, 12, 0) <= sys.version_info < (3, 12, 4):
|
||||
with self.assertRaises(AssertionError):
|
||||
@@ -7309,8 +7313,8 @@ def test_or(self):
|
||||
self.assertEqual(X | "x", Union[X, "x"])
|
||||
self.assertEqual("x" | X, Union["x", X])
|
||||
# make sure the order is correct
|
||||
- self.assertEqual(get_args(X | "x"), (X, typing.ForwardRef("x")))
|
||||
- self.assertEqual(get_args("x" | X), (typing.ForwardRef("x"), X))
|
||||
+ self.assertEqual(get_args(X | "x"), (X, EqualToForwardRef("x")))
|
||||
+ self.assertEqual(get_args("x" | X), (EqualToForwardRef("x"), X))
|
||||
|
||||
def test_union_constrained(self):
|
||||
A = TypeVar('A', str, bytes)
|
||||
@@ -8878,7 +8882,7 @@ class X:
|
||||
type_params=None,
|
||||
format=Format.FORWARDREF,
|
||||
)
|
||||
- self.assertEqual(evaluated_ref, typing.ForwardRef("doesnotexist2"))
|
||||
+ self.assertEqual(evaluated_ref, EqualToForwardRef("doesnotexist2"))
|
||||
|
||||
def test_evaluate_with_type_params(self):
|
||||
# Use a T name that is not in globals
|
||||
|
||||
From 993ac2fd77b89577a137819ffdb8478d25958742 Mon Sep 17 00:00:00 2001
|
||||
From: Jelle Zijlstra <jelle.zijlstra@gmail.com>
|
||||
Date: Mon, 5 May 2025 08:24:26 -0700
|
||||
Subject: [PATCH 5/5] no support
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -103,11 +103,6 @@
|
||||
runtime_checkable,
|
||||
)
|
||||
|
||||
-if sys.version_info >= (3, 14):
|
||||
- from test.support import EqualToForwardRef
|
||||
-else:
|
||||
- EqualToForwardRef = typing.ForwardRef
|
||||
-
|
||||
NoneType = type(None)
|
||||
T = TypeVar("T")
|
||||
KT = TypeVar("KT")
|
||||
@@ -444,6 +439,48 @@ def assertNotIsSubclass(self, cls, class_or_tuple, msg=None):
|
||||
raise self.failureException(message)
|
||||
|
||||
|
||||
+class EqualToForwardRef:
|
||||
+ """Helper to ease use of annotationlib.ForwardRef in tests.
|
||||
+
|
||||
+ This checks only attributes that can be set using the constructor.
|
||||
+
|
||||
+ """
|
||||
+
|
||||
+ def __init__(
|
||||
+ self,
|
||||
+ arg,
|
||||
+ *,
|
||||
+ module=None,
|
||||
+ owner=None,
|
||||
+ is_class=False,
|
||||
+ ):
|
||||
+ self.__forward_arg__ = arg
|
||||
+ self.__forward_is_class__ = is_class
|
||||
+ self.__forward_module__ = module
|
||||
+ self.__owner__ = owner
|
||||
+
|
||||
+ def __eq__(self, other):
|
||||
+ if not isinstance(other, (EqualToForwardRef, typing.ForwardRef)):
|
||||
+ return NotImplemented
|
||||
+ if sys.version_info >= (3, 14) and self.__owner__ != other.__owner__:
|
||||
+ return False
|
||||
+ return (
|
||||
+ self.__forward_arg__ == other.__forward_arg__
|
||||
+ and self.__forward_module__ == other.__forward_module__
|
||||
+ and self.__forward_is_class__ == other.__forward_is_class__
|
||||
+ )
|
||||
+
|
||||
+ def __repr__(self):
|
||||
+ extra = []
|
||||
+ if self.__forward_module__ is not None:
|
||||
+ extra.append(f", module={self.__forward_module__!r}")
|
||||
+ if self.__forward_is_class__:
|
||||
+ extra.append(", is_class=True")
|
||||
+ if sys.version_info >= (3, 14) and self.__owner__ is not None:
|
||||
+ extra.append(f", owner={self.__owner__!r}")
|
||||
+ return f"EqualToForwardRef({self.__forward_arg__!r}{''.join(extra)})"
|
||||
+
|
||||
+
|
||||
class Employee:
|
||||
pass
|
||||
|
||||
--- a/src/test_typing_extensions.py
|
||||
+++ b/src/test_typing_extensions.py
|
||||
@@ -8957,13 +8957,6 @@ class TestEvaluateForwardRefs(BaseTestCase):
|
||||
obj = object()
|
||||
self.assertIs(evaluate_forward_ref(typing.ForwardRef("int"), globals={"int": obj}), obj)
|
||||
|
||||
- def test_fwdref_value_is_cached(self):
|
||||
- fr = typing.ForwardRef("hello")
|
||||
- with self.assertRaises(NameError):
|
||||
- evaluate_forward_ref(fr)
|
||||
- self.assertIs(evaluate_forward_ref(fr, globals={"hello": str}), str)
|
||||
- self.assertIs(evaluate_forward_ref(fr), str)
|
||||
-
|
||||
@skipUnless(TYPING_3_9_0, "Needs PEP 585 support")
|
||||
def test_fwdref_with_owner(self):
|
||||
self.assertEqual(
|
||||
Reference in New Issue
Block a user