Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit39b4a57

Browse files
committed
gh-119180: Add evaluate functions for type params and type aliases
1 parente91ef13 commit39b4a57

File tree

10 files changed

+379
-160
lines changed

10 files changed

+379
-160
lines changed

‎Include/internal/pycore_global_objects.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ struct _Py_interp_cached_objects {
8181
PyTypeObject*paramspec_type;
8282
PyTypeObject*paramspecargs_type;
8383
PyTypeObject*paramspeckwargs_type;
84+
PyTypeObject*constevaluator_type;
8485
};
8586

8687
#define_Py_INTERP_STATIC_OBJECT(interp,NAME) \

‎Include/internal/pycore_typevarobject.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern PyObject *_Py_subscript_generic(PyThreadState *, PyObject *);
1616
externPyObject*_Py_set_typeparam_default(PyThreadState*,PyObject*,PyObject*);
1717
externint_Py_initialize_generic(PyInterpreterState*);
1818
externvoid_Py_clear_generic_types(PyInterpreterState*);
19+
externint_Py_typing_type_repr(_PyUnicodeWriter*,PyObject*);
1920

2021
externPyTypeObject_PyTypeAlias_Type;
2122
externPyTypeObject_PyNoDefault_Type;

‎Lib/annotationlib.py‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,16 @@ def __missing__(self, key):
413413
returnfwdref
414414

415415

416-
defcall_annotate_function(annotate,format,owner=None):
416+
defcall_evaluate_function(evaluate,format,*,owner=None):
417+
"""Call an evaluate function. Evaluate functions are normally generated for
418+
the value of type aliases and the bounds, constraints, and defaults of
419+
type parameter objects.
420+
"""
421+
returncall_annotate_function(evaluate,format,owner=owner,_is_evaluate=True)
422+
423+
424+
defcall_annotate_function(annotate,format,*,owner=None,
425+
_is_evaluate=False):
417426
"""Call an __annotate__ function. __annotate__ functions are normally
418427
generated by the compiler to defer the evaluation of annotations. They
419428
can be called with any of the format arguments in the Format enum, but
@@ -459,8 +468,11 @@ def call_annotate_function(annotate, format, owner=None):
459468
closure=tuple(new_closure)
460469
else:
461470
closure=None
462-
func=types.FunctionType(annotate.__code__,globals,closure=closure)
471+
func=types.FunctionType(annotate.__code__,globals,closure=closure,
472+
argdefs=annotate.__defaults__,kwdefaults=annotate.__kwdefaults__)
463473
annos=func(Format.VALUE)
474+
if_is_evaluate:
475+
returnannosifisinstance(annos,str)elserepr(annos)
464476
return {
465477
key:valifisinstance(val,str)elserepr(val)
466478
forkey,valinannos.items()
@@ -511,7 +523,8 @@ def call_annotate_function(annotate, format, owner=None):
511523
closure=tuple(new_closure)
512524
else:
513525
closure=None
514-
func=types.FunctionType(annotate.__code__,globals,closure=closure)
526+
func=types.FunctionType(annotate.__code__,globals,closure=closure,
527+
argdefs=annotate.__defaults__,kwdefaults=annotate.__kwdefaults__)
515528
result=func(Format.VALUE)
516529
forobjinglobals.stringifiers:
517530
obj.__class__=ForwardRef

‎Lib/test/test_annotationlib.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,3 +769,22 @@ def test_pep_695_generics_with_future_annotations_nested_in_function(self):
769769
set(results.generic_func_annotations.values()),
770770
set(results.generic_func.__type_params__)
771771
)
772+
773+
774+
classTestCallEvaluateFunction(unittest.TestCase):
775+
deftest_evaluation(self):
776+
defevaluate(format,exc=NotImplementedError):
777+
ifformat!=1:
778+
raiseexc
779+
returnundefined
780+
781+
withself.assertRaises(NameError):
782+
annotationlib.call_evaluate_function(evaluate,annotationlib.Format.VALUE)
783+
self.assertEqual(
784+
annotationlib.call_evaluate_function(evaluate,annotationlib.Format.FORWARDREF),
785+
annotationlib.ForwardRef("undefined"),
786+
)
787+
self.assertEqual(
788+
annotationlib.call_evaluate_function(evaluate,annotationlib.Format.SOURCE),
789+
"undefined",
790+
)

‎Lib/test/test_type_params.py‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
importannotationlib
12
importasyncio
23
importtextwrap
34
importtypes
@@ -6,7 +7,7 @@
67
importweakref
78
fromtest.supportimportrequires_working_socket,check_syntax_error,run_code
89

9-
fromtypingimportGeneric,NoDefault,Sequence,TypeVar,TypeVarTuple,ParamSpec,get_args
10+
fromtypingimportGeneric,NoDefault,Sequence,TypeAliasType,TypeVar,TypeVarTuple,ParamSpec,get_args
1011

1112

1213
classTypeParamsInvalidTest(unittest.TestCase):
@@ -1394,3 +1395,43 @@ def test_symtable_key_regression_name(self):
13941395

13951396
self.assertEqual(ns["X1"].__type_params__[0].__default__,"A")
13961397
self.assertEqual(ns["X2"].__type_params__[0].__default__,"B")
1398+
1399+
1400+
classTestEvaluateFunctions(unittest.TestCase):
1401+
deftest_general(self):
1402+
typeAlias=int
1403+
Alias2=TypeAliasType("Alias2",int)
1404+
deff[T:int=int,**P=int,*Ts=int]():pass
1405+
T,P,Ts=f.__type_params__
1406+
T2=TypeVar("T2",bound=int,default=int)
1407+
P2=ParamSpec("P2",default=int)
1408+
Ts2=TypeVarTuple("Ts2",default=int)
1409+
cases= [
1410+
Alias.evaluate_value,
1411+
Alias2.evaluate_value,
1412+
T.evaluate_bound,
1413+
T.evaluate_default,
1414+
P.evaluate_default,
1415+
Ts.evaluate_default,
1416+
T2.evaluate_bound,
1417+
T2.evaluate_default,
1418+
P2.evaluate_default,
1419+
Ts2.evaluate_default,
1420+
]
1421+
forcaseincases:
1422+
withself.subTest(case=case):
1423+
self.assertIs(case(1),int)
1424+
self.assertIs(annotationlib.call_evaluate_function(case,annotationlib.Format.VALUE),int)
1425+
self.assertIs(annotationlib.call_evaluate_function(case,annotationlib.Format.FORWARDREF),int)
1426+
self.assertEqual(annotationlib.call_evaluate_function(case,annotationlib.Format.SOURCE),'int')
1427+
1428+
deftest_constraints(self):
1429+
deff[T: (int,str)]():pass
1430+
T,=f.__type_params__
1431+
T2=TypeVar("T2",int,str)
1432+
forcasein [T,T2]:
1433+
withself.subTest(case=case):
1434+
self.assertEqual(case.evaluate_constraints(1), (int,str))
1435+
self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints,annotationlib.Format.VALUE), (int,str))
1436+
self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints,annotationlib.Format.FORWARDREF), (int,str))
1437+
self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints,annotationlib.Format.SOURCE),'(int, str)')

‎Objects/genericaliasobject.c‎

Lines changed: 5 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include"pycore_ceval.h"// _PyEval_GetBuiltin()
55
#include"pycore_modsupport.h"// _PyArg_NoKeywords()
66
#include"pycore_object.h"
7+
#include"pycore_typevarobject.h"// _Py_typing_type_repr
78
#include"pycore_unionobject.h"// _Py_union_type_or, _PyGenericAlias_Check
89

910

@@ -51,70 +52,7 @@ ga_traverse(PyObject *self, visitproc visit, void *arg)
5152
}
5253

5354
staticint
54-
ga_repr_item(PyUnicodeWriter*writer,PyObject*p)
55-
{
56-
PyObject*qualname=NULL;
57-
PyObject*module=NULL;
58-
intrc;
59-
60-
if (p==Py_Ellipsis) {
61-
// The Ellipsis object
62-
rc=PyUnicodeWriter_WriteUTF8(writer,"...",3);
63-
gotodone;
64-
}
65-
66-
if ((rc=PyObject_HasAttrWithError(p,&_Py_ID(__origin__)))>0&&
67-
(rc=PyObject_HasAttrWithError(p,&_Py_ID(__args__)))>0)
68-
{
69-
// It looks like a GenericAlias
70-
gotouse_repr;
71-
}
72-
if (rc<0) {
73-
gotoerror;
74-
}
75-
76-
if (PyObject_GetOptionalAttr(p,&_Py_ID(__qualname__),&qualname)<0) {
77-
gotoerror;
78-
}
79-
if (qualname==NULL) {
80-
gotouse_repr;
81-
}
82-
if (PyObject_GetOptionalAttr(p,&_Py_ID(__module__),&module)<0) {
83-
gotoerror;
84-
}
85-
if (module==NULL||module==Py_None) {
86-
gotouse_repr;
87-
}
88-
89-
// Looks like a class
90-
if (PyUnicode_Check(module)&&
91-
_PyUnicode_EqualToASCIIString(module,"builtins"))
92-
{
93-
// builtins don't need a module name
94-
rc=PyUnicodeWriter_WriteStr(writer,qualname);
95-
gotodone;
96-
}
97-
else {
98-
rc=PyUnicodeWriter_Format(writer,"%S.%S",module,qualname);
99-
gotodone;
100-
}
101-
102-
error:
103-
rc=-1;
104-
gotodone;
105-
106-
use_repr:
107-
rc=PyUnicodeWriter_WriteRepr(writer,p);
108-
gotodone;
109-
110-
done:
111-
Py_XDECREF(qualname);
112-
Py_XDECREF(module);
113-
returnrc;
114-
}
115-
116-
staticint
117-
ga_repr_items_list(PyUnicodeWriter*writer,PyObject*p)
55+
ga_repr_items_list(_PyUnicodeWriter*writer,PyObject*p)
11856
{
11957
assert(PyList_CheckExact(p));
12058

@@ -131,7 +69,7 @@ ga_repr_items_list(PyUnicodeWriter *writer, PyObject *p)
13169
}
13270
}
13371
PyObject*item=PyList_GET_ITEM(p,i);
134-
if (ga_repr_item(writer,item)<0) {
72+
if (_Py_typing_type_repr(writer,item)<0) {
13573
return-1;
13674
}
13775
}
@@ -162,7 +100,7 @@ ga_repr(PyObject *self)
162100
gotoerror;
163101
}
164102
}
165-
if (ga_repr_item(writer,alias->origin)<0) {
103+
if (_Py_typing_type_repr(writer,alias->origin)<0) {
166104
gotoerror;
167105
}
168106
if (PyUnicodeWriter_WriteChar(writer,'[')<0) {
@@ -181,7 +119,7 @@ ga_repr(PyObject *self)
181119
gotoerror;
182120
}
183121
}
184-
elseif (ga_repr_item(writer,p)<0) {
122+
elseif (_Py_typing_type_repr(writer,p)<0) {
185123
gotoerror;
186124
}
187125
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp