10000 Move the C code to Python. · python/cpython@a7efb91 · GitHub
[go: up one dir, main page]

Skip to content

Commit a7efb91

Browse files
Move the C code to Python.
1 parent 40ba6ca commit a7efb91

File tree

4 files changed

+86
-170
lines changed

4 files changed

+86
-170
lines changed

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ struct _Py_global_strings {
202202
STRUCT_FOR_ID(__truediv__)
203203
STRUCT_FOR_ID(__trunc__)
204204
STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__)
205+
STRUCT_FOR_ID(__typing_prepare_subst__)
205206
STRUCT_FOR_ID(__typing_subst__)
206207
STRUCT_FOR_ID(__typing_unpacked_tuple_args__)
207208
STRUCT_FOR_ID(__warningregistry__)

Include/internal/pycore_runtime_init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ extern "C" {
824824
INIT_ID(__truediv__), \
825825
INIT_ID(__trunc__), \
826826
INIT_ID(__typing_is_unpacked_typevartuple__), \
827+
INIT_ID(__typing_prepare_subst__), \
827828
INIT_ID(__typing_subst__), \
828829
INIT_ID(__typing_unpacked_tuple_args__), \
829830
INIT_ID(__warningregistry__), \

Lib/typing.py

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,42 @@ def __repr__(self):
10651065
def __typing_subst__(self, arg):
10661066
raise TypeError("Substitution of bare TypeVarTuple is not supported")
10671067

1068+
def __typing_prepare_subst__(self, alias, args):
1069+
params = alias.__parameters__
1070+
typevartuple_index = params.index(self)
1071+
for param in enumerate(params[typevartuple_index + 1:]):
1072+
if isinstance(param, TypeVarTuple):
1073+
raise TypeError(f"More than one TypeVarTuple parameter in {alias}")
1074+
1075+
alen = len(args)
1076+
plen = len(params)
1077+
left = typevartuple_index
1078+
right = plen - typevartuple_index - 1
1079+
var_tuple_index = None
1080+
fillarg = None
1081+
for k, arg in enumerate(args):
1082+
if not (isinstance(arg, type) and not isinstance(arg, GenericAlias)):
1083+
subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
1084+
if subargs and len(subargs) == 2 and subargs[-1] is ...:
1085+
if var_tuple_index is not None:
1086+
raise TypeError("More than one unpacked arbitrary-length tuple argument")
1087+
var_tuple_index = k
1088+
fillarg = subargs[0]
1089+
if var_tuple_index is not None:
1090+
left = min(left, var_tuple_index)
1091+
right = min(right, alen - var_tuple_index - 1)
1092+
elif left + right > alen:
1093+
raise TypeError(f"Too few arguments for {alias};"
1094+
f" actual {alen}, expected at least {plen-1}")
1095+
1096+
return (
1097+
*args[:left],
1098+
*([fillarg]*(typevartuple_index - left)),
1099+
tuple(args[left: alen - right]),
1100+
*([fillarg]*(plen - right - left - typevartuple_index - 1)),
1101+
*args[alen - right:],
1102+
)
1103+
10681104

10691105
class ParamSpecArgs(_Final, _Immutable, _root=True):
10701106
"""The args for a ParamSpec object.
@@ -1184,6 +1220,8 @@ def __typing_subst__(self, arg):
11841220
f"ParamSpec, or Concatenate. Got {arg}")
11851221
return arg
11861222

1223+
def __typing_prepare_subst__(self, alias, args):
1224+
return _prepare_paramspec_params(alias, args)
11871225

11881226
def _is_dunder(attr):
11891227
return attr.startswith('__') and attr.endswith('__')
@@ -1347,10 +1385,6 @@ def __getitem__(self, args):
13471385
args = (args,)
13481386
args = tuple(_type_convert(p) for p in args)
13491387
args = _unpack_args(args)
1350-
if (self._paramspec_tvars
1351-
and any(isinstance(t, ParamSpec) for t in self.__parameters__)):
1352-
args = _prepare_paramspec_params(self, args)
1353-
13541388
new_args = self._determine_new_args(args)
13551389
r = self.copy_with(new_args)
13561390
return r
@@ -1372,47 +1406,16 @@ def _determine_new_args(self, args):
13721406

13731407
params = self.__parameters__
13741408
# In the example above, this would be {T3: str}
1375-
new_arg_by_param = {}
1376-
typevartuple_index = None
1377-
for i, param in enumerate(params):
1378-
if isinstance(param, TypeVarTuple):
1379-
if typevartuple_index is not None:
1380-
raise TypeError(f"More than one TypeVarTuple parameter in {self}")
1381-
typevartuple_index = i
1382-
1409+
for param in params:
1410+
prepare = getattr(param, '__typing_prepare_subst__', None)
1411+
if prepare is not None:
1412+
args = prepare(self, args)
13831413
alen = len(args)
13841414
plen = len(params)
1385-
if typevartuple_index is not None:
1386-
left = typevartuple_index
1387-
right = plen - typevartuple_index - 1
1388-
var_tuple_index = None
1389-
for k, arg in enumerate(args):
1390-
if not (isinstance(arg, type) and not isinstance(arg, GenericAlias)):
1391-
subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
1392-
if subargs and len(subargs) == 2 and subargs[-1] is ...:
1393-
if var_tuple_index is not None:
1394-
raise TypeError("More than one unpacked arbitrary-length tuple argument")
1395-
var_tuple_index = k
1396-
fillarg = subargs[0]
1397-
if var_tuple_index is not None:
1398-
left = min(left, var_tuple_index)
1399-
right = min(right, alen - var_tuple_index - 1)
1400-
elif left + right > alen:
1401-
raise TypeError(f"Too few arguments for {self};"
1402-
f" actual {alen}, expected at least {plen-1}")
1403-
1404-
new_arg_by_param.update(zip(params[:left], args[:left]))
1405-
for k in range(left, typevartuple_index):
1406-
new_arg_by_param[params[k]] = fillarg
1407-
new_arg_by_param[params[typevartuple_index]] = tuple(args[left: alen - right])
1408-
for k in range(typevartuple_index + 1, plen - right):
1409-
new_arg_by_param[params[k]] = fillarg
1410-
new_arg_by_param.update(zip(params[plen - right:], args[alen - right:]))
1411-
else:
1412-
if alen != plen:
1413-
raise TypeError(f"Too {'many' if alen > plen else 'few'} arguments for {self};"
1414-
f" actual {alen}, expected {plen}")
1415-
new_arg_by_param.update(zip(params, args))
1415+
if alen != plen:
1416+
raise TypeError(f"Too {'many' if alen > plen else 'few'} arguments for {self};"
1417+
f" actual {alen}, expected {plen}")
1418+
new_arg_by_param = dict(zip(params, args))
14161419

14171420
new_args = []
14181421
for old_arg in self.__args__:

Objects/genericaliasobject.c

Lines changed: 38 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,7 @@ _Py_make_parameters(PyObject *args)
269269
a non-empty tuple, return a new reference to obj. */
270270
static PyObject *
271271
subs_tvars(PyObject *obj, PyObject *params,
272-
PyObject **argitems, Py_ssize_t nargs,
273-
Py_ssize_t varparam, Py_ssize_t left, Py_ssize_t right,
274-
PyObject *fillarg)
272+
PyObject **argitems, Py_ssize_t nargs)
275273
{
276274
PyObject *subparams;
277275
if (_PyObject_LookupAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
@@ -289,30 +287,22 @@ subs_tvars(PyObject *obj, PyObject *params,
289287
for (Py_ssize_t i = 0; i < nsubargs; ++i) {
290288
PyObject *arg = PyTuple_GET_ITEM(subparams, i);
291289
Py_ssize_t iparam = tuple_index(params, nparams, arg);
292-
if (iparam == varparam) {
293-
j = tuple_extend(&subargs, j,
294-
argitems + left, nargs - left - right);
295-
if (j < 0) {
296-
return NULL;
297-
}
298-
}
299-
else {
300-
if (iparam >= 0) {
301-
if (iparam < left) {
302-
arg = argitems[iparam];
303-
}
304-
else if (iparam >= nparams - right) {
305-
iparam += nargs - nparams;
306-
arg = argitems[iparam];
307-
}
308-
else {
309-
arg = fillarg;
290+
if (iparam >= 0) {
291+
PyObject *param = PyTuple_GET_ITEM(params, iparam);
292+
arg = argitems[iparam];
293+
if (Py_TYPE(param)->tp_iter && PyTuple_Check(arg)) { // TypeVarTuple
294+
j = tuple_extend(&subargs, j,
295+
&PyTuple_GET_ITEM(arg, 0),
296+
PyTuple_GET_SIZE(arg));
297+
if (j < 0) {
298+
return NULL;
310299
}
300+
continue;
311301
}
312-
Py_INCREF(arg);
313-
PyTuple_SET_ITEM(subargs, j, arg);
314-
j++;
315302
}
303+
Py_INCREF(arg);
304+
PyTuple_SET_ITEM(subargs, j, arg);
305+
j++;
316306
}
317307
assert(j == PyTuple_GET_SIZE(subargs));
318308

@@ -409,27 +399,6 @@ _unpack_args(PyObject *item)
409399
return newargs;
410400
}
411401

412-
static PyObject *
413-
_get_unpacked_var_tuple_arg(PyObject *arg)
414-
{
415-
if (PyType_Check(arg)) {
416-
return NULL;
417-
}
418-
PyObject *subargs = _unpacked_tuple_args(arg);
419-
if (subargs != NULL &&
420-
PyTuple_Check(subargs) &&
421-
PyTuple_GET_SIZE(subargs) == 2 &&
422-
PyTuple_GET_ITEM(subargs, 1) == Py_Ellipsis)
423-
{
424-
PyObject *subarg = PyTuple_GET_ITEM(subargs, 0);
425-
Py_INCREF(subarg);
426-
Py_DECREF(subargs);
427-
return subarg;
428-
}
429-
Py_XDECREF(subargs);
430-
return NULL;
431-
}
432-
433402
PyObject *
434403
_Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item)
435404
{
@@ -440,67 +409,36 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
440409
self);
441410
}
442411
item = _unpack_args(item);
443-
int is_tuple = PyTuple_Check(item);
444-
Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
445-
PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
446-
Py_ssize_t varparam = nparams;
447412
for (Py_ssize_t i = 0; i < nparams; i++) {
448413
PyObject *param = PyTuple_GET_ITEM(parameters, i);
449-
if (Py_TYPE(param)->tp_iter) { // TypeVarTuple
450-
if (varparam < nparams) {
451-
Py_DECREF(item);
452-
return PyErr_Format(PyExc_TypeError,
453-
"More than one TypeVarTuple parameter in %S",
454-
self);
455-
}
456-
varparam = i;
414+
PyObject *prepare, *tmp;
415+
if (_PyObject_LookupAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) {
416+
Py_DECREF(item);
417+
return NULL;
457418
}
458-
}
459-
PyObject *fillarg = NULL;
460-
Py_ssize_t vartuplearg = nitems;
461-
Py_ssize_t left = varparam;
462-
Py_ssize_t right = nparams - varparam - 1;
463-
if (varparam < nparams) {
464-
for (Py_ssize_t i = 0; i < nitems; i++) {
465-
PyObject *arg = _get_unpacked_var_tuple_arg(argitems[i]);
466-
if (arg) {
467-
if (vartuplearg < nitems) {
468-
Py_DECREF(arg);
469-
Py_DECREF(fillarg);
470-
Py_DECREF(item);
471-
return PyErr_Format(PyExc_TypeError,
472-
"More than one unpacked arbitrary-length tuple argument",
473-
self);
474-
}
475-
vartuplearg = i;
476-
fillarg = arg;
419+
if (prepare && prepare != Py_None) {
420+
if (PyTuple_Check(item)) {
421+
tmp = PyObject_CallFunction(prepare, "OO", self, item);
477422
}
478-
else if (PyErr_Occurred()) {
479-
Py_XDECREF(fillarg);
480-
Py_DECREF(item);
423+
else {
424+
tmp = PyObject_CallFunction(prepare, "O(O)", self, item);
425+
}
426+
Py_DECREF(prepare);
427+
Py_SETREF(item, tmp);
428+
if (item == NULL) {
481429
return NULL;
482430
}
483431
}
484-
if (vartuplearg < nitems) {
485-
assert(fillarg);
486-
left = Py_MIN(left, vartuplearg);
487-
right = Py_MIN(right, nitems - vartuplearg - 1);
488-
}
489-
else if (left + right > nitems) {
490-
Py_DECREF(item);
491-
return PyErr_Format(PyExc_TypeError,
492-
"Too few arguments for %R",
493-
self);
494-
}
495432
}
496-
else {
497-
if (nitems != nparams) {
498-
Py_DECREF(item);
499-
return PyErr_Format(PyExc_TypeError,
500-
"Too %s arguments for %R; actual %zd, expected %zd",
501-
nitems > nparams ? "many" : "few",
502-
self, nitems, nparams);
503-
}
433+
int is_tuple = PyTuple_Check(item);
434+
Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
435+
PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
436+
if (nitems != nparams) {
437+
Py_DECREF(item);
438+
return PyErr_Format(PyExc_TypeError,
439+
"Too %s arguments for %R; actual %zd, expected %zd",
440+
nitems > nparams ? "many" : "few",
441+
self, nitems, nparams);
504442
}
505443
/* Replace all type variables (specified by parameters)
506444
with corresponding values specified by argitems.
@@ -511,7 +449,6 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
511449
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
512450
PyObject *newargs = PyTuple_New(nargs);
513451
if (newargs == NULL) {
514-
Py_XDECREF(fillarg);
515452
Py_DECREF(item);
516453
return NULL;
517454
}
@@ -520,50 +457,26 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
520457
int unpack = _is_unpacked_typevartuple(arg);
521458
if (unpack < 0) {
522459
Py_DECREF(newargs);
523-
Py_XDECREF(fillarg);
524460
Py_DECREF(item);
525461
return NULL;
526462
}
527463
PyObject *subst;
528464
if (_PyObject_LookupAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
529465
Py_DECREF(newargs);
530-
Py_XDECREF(fillarg);
531466
Py_DECREF(item);
532467
return NULL;
533468
}
534469
if (subst) {
535470
Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
536471
assert(iparam >= 0);
537-
if (iparam == varparam) {
538-
Py_DECREF(subst);
539-
Py_DECREF(newargs);
540-
Py_XDECREF(fillarg);
541-
Py_DECREF(item);
542-
PyErr_SetString(PyExc_TypeError,
543-
"Substitution of bare TypeVarTuple is not supported");
544-
return NULL;
545-
}
546-
if (iparam < left) {
547-
arg = argitems[iparam];
548-
}
549-
else if (iparam >= nparams - right) {
550-
iparam += nitems - nparams;
551-
arg = argitems[iparam];
552-
}
553-
else {
554-
assert(fillarg);
555-
arg = fillarg;
556-
}
557-
arg = PyObject_CallOneArg(subst, arg);
472+
arg = PyObject_CallOneArg(subst, argitems[iparam]);
558473
Py_DECREF(subst);
559474
}
560475
else {
561-
arg = subs_tvars(arg, parameters, argitems, nitems,
562-
varparam, left, right, fillarg);
476+
arg = subs_tvars(arg, parameters, argitems, nitems);
563477
}
564478
if (arg == NULL) {
565479
Py_DECREF(newargs);
566-
Py_XDECREF(fillarg);
567480
Py_DECREF(item);
568481
return NULL;
569482
}
@@ -572,7 +485,6 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
572485
&PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
573486
Py_DECREF(arg);
574487
if (jarg < 0) {
575-
Py_XDECREF(fillarg);
576488
Py_DECREF(item);
577489
return NULL;
578490
}
@@ -583,7 +495,6 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
583495
}
584496
}
585497

586-
Py_XDECREF(fillarg);
587498
Py_DECREF(item);
588499
return newargs;
589500
}

0 commit comments

Comments
 (0)
0