gh-103763: Implement PEP 695 (#103764)

This implements PEP 695, Type Parameter Syntax. It adds support for:

- Generic functions (def func[T](): ...)
- Generic classes (class X[T](): ...)
- Type aliases (type X = ...)
- New scoping when the new syntax is used within a class body
- Compiler and interpreter changes to support the new syntax and scoping rules 

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Co-authored-by: Eric Traut <eric@traut.com>
Co-authored-by: Larry Hastings <larry@hastings.org>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Jelle Zijlstra 2023-05-15 20:36:23 -07:00 • committed by GitHub
parent fdafdc235e
commit 24d8b88420
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 11405 additions and 5469 deletions

786
Objects/clinic/typevarobject.c.h generated Normal file
View file

@ -0,0 +1,786 @@
/*[clinic input]
preserve
[clinic start generated code]*/
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
PyDoc_STRVAR(typevar_new__doc__,
"typevar(name, *constraints, *, bound=None, covariant=False,\n"
" contravariant=False, infer_variance=False)\n"
"--\n"
"\n"
"Create a TypeVar.");
static PyObject *
typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints,
PyObject *bound, int covariant, int contravariant,
int infer_variance);
static PyObject *
typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 5
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typevar",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[6];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
PyObject *name;
PyObject *constraints = NULL;
PyObject *bound = Py_None;
int covariant = 0;
int contravariant = 0;
int infer_variance = 0;
fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, 1, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("typevar", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
constraints = fastargs[1];
if (!noptargs) {
goto skip_optional_kwonly;
}
if (fastargs[2]) {
bound = fastargs[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[3]) {
covariant = PyObject_IsTrue(fastargs[3]);
if (covariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[4]) {
contravariant = PyObject_IsTrue(fastargs[4]);
if (contravariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
infer_variance = PyObject_IsTrue(fastargs[5]);
if (infer_variance < 0) {
goto exit;
}
skip_optional_kwonly:
return_value = typevar_new_impl(type, name, constraints, bound, covariant, contravariant, infer_variance);
exit:
Py_XDECREF(constraints);
return return_value;
}
PyDoc_STRVAR(typevar_typing_subst__doc__,
"__typing_subst__($self, /, arg)\n"
"--\n"
"\n");
#define TYPEVAR_TYPING_SUBST_METHODDEF \
{"__typing_subst__", _PyCFunction_CAST(typevar_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevar_typing_subst__doc__},
static PyObject *
typevar_typing_subst_impl(typevarobject *self, PyObject *arg);
static PyObject *
typevar_typing_subst(typevarobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(arg), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"arg", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *arg;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
arg = args[0];
return_value = typevar_typing_subst_impl(self, arg);
exit:
return return_value;
}
PyDoc_STRVAR(typevar_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define TYPEVAR_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)typevar_reduce, METH_NOARGS, typevar_reduce__doc__},
static PyObject *
typevar_reduce_impl(typevarobject *self);
static PyObject *
typevar_reduce(typevarobject *self, PyObject *Py_UNUSED(ignored))
{
return typevar_reduce_impl(self);
}
PyDoc_STRVAR(paramspecargs_new__doc__,
"paramspecargs(origin)\n"
"--\n"
"\n"
"Create a ParamSpecArgs object.");
static PyObject *
paramspecargs_new_impl(PyTypeObject *type, PyObject *origin);
static PyObject *
paramspecargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(origin), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"origin", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "paramspecargs",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *origin;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
origin = fastargs[0];
return_value = paramspecargs_new_impl(type, origin);
exit:
return return_value;
}
PyDoc_STRVAR(paramspeckwargs_new__doc__,
"paramspeckwargs(origin)\n"
"--\n"
"\n"
"Create a ParamSpecKwargs object.");
static PyObject *
paramspeckwargs_new_impl(PyTypeObject *type, PyObject *origin);
static PyObject *
paramspeckwargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(origin), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"origin", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "paramspeckwargs",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *origin;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
origin = fastargs[0];
return_value = paramspeckwargs_new_impl(type, origin);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_new__doc__,
"paramspec(name, *, bound=None, covariant=False, contravariant=False,\n"
" infer_variance=False)\n"
"--\n"
"\n"
"Create a ParamSpec object.");
static PyObject *
paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound,
int covariant, int contravariant, int infer_variance);
static PyObject *
paramspec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 5
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "paramspec",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[5];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
PyObject *name;
PyObject *bound = Py_None;
int covariant = 0;
int contravariant = 0;
int infer_variance = 0;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("paramspec", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
if (!noptargs) {
goto skip_optional_kwonly;
}
if (fastargs[1]) {
bound = fastargs[1];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[2]) {
covariant = PyObject_IsTrue(fastargs[2]);
if (covariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
if (fastargs[3]) {
contravariant = PyObject_IsTrue(fastargs[3]);
if (contravariant < 0) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
infer_variance = PyObject_IsTrue(fastargs[4]);
if (infer_variance < 0) {
goto exit;
}
skip_optional_kwonly:
return_value = paramspec_new_impl(type, name, bound, covariant, contravariant, infer_variance);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_typing_subst__doc__,
"__typing_subst__($self, /, arg)\n"
"--\n"
"\n");
#define PARAMSPEC_TYPING_SUBST_METHODDEF \
{"__typing_subst__", _PyCFunction_CAST(paramspec_typing_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_subst__doc__},
static PyObject *
paramspec_typing_subst_impl(paramspecobject *self, PyObject *arg);
static PyObject *
paramspec_typing_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(arg), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"arg", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *arg;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
arg = args[0];
return_value = paramspec_typing_subst_impl(self, arg);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_typing_prepare_subst__doc__,
"__typing_prepare_subst__($self, /, alias, args)\n"
"--\n"
"\n");
#define PARAMSPEC_TYPING_PREPARE_SUBST_METHODDEF \
{"__typing_prepare_subst__", _PyCFunction_CAST(paramspec_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_prepare_subst__doc__},
static PyObject *
paramspec_typing_prepare_subst_impl(paramspecobject *self, PyObject *alias,
PyObject *args);
static PyObject *
paramspec_typing_prepare_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(alias), &_Py_ID(args), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"alias", "args", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_prepare_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject *alias;
PyObject *__clinic_args;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
if (!args) {
goto exit;
}
alias = args[0];
__clinic_args = args[1];
return_value = paramspec_typing_prepare_subst_impl(self, alias, __clinic_args);
exit:
return return_value;
}
PyDoc_STRVAR(paramspec_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define PARAMSPEC_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)paramspec_reduce, METH_NOARGS, paramspec_reduce__doc__},
static PyObject *
paramspec_reduce_impl(paramspecobject *self);
static PyObject *
paramspec_reduce(paramspecobject *self, PyObject *Py_UNUSED(ignored))
{
return paramspec_reduce_impl(self);
}
PyDoc_STRVAR(typevartuple__doc__,
"typevartuple(name)\n"
"--\n"
"\n"
"Create a new TypeVarTuple with the given name.");
static PyObject *
typevartuple_impl(PyTypeObject *type, PyObject *name);
static PyObject *
typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typevartuple",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *name;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("typevartuple", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
return_value = typevartuple_impl(type, name);
exit:
return return_value;
}
PyDoc_STRVAR(typevartuple_typing_subst__doc__,
"__typing_subst__($self, /, arg)\n"
"--\n"
"\n");
#define TYPEVARTUPLE_TYPING_SUBST_METHODDEF \
{"__typing_subst__", _PyCFunction_CAST(typevartuple_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_subst__doc__},
static PyObject *
typevartuple_typing_subst_impl(typevartupleobject *self, PyObject *arg);
static PyObject *
typevartuple_typing_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(arg), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"arg", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[1];
PyObject *arg;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
arg = args[0];
return_value = typevartuple_typing_subst_impl(self, arg);
exit:
return return_value;
}
PyDoc_STRVAR(typevartuple_typing_prepare_subst__doc__,
"__typing_prepare_subst__($self, /, alias, args)\n"
"--\n"
"\n");
#define TYPEVARTUPLE_TYPING_PREPARE_SUBST_METHODDEF \
{"__typing_prepare_subst__", _PyCFunction_CAST(typevartuple_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_prepare_subst__doc__},
static PyObject *
typevartuple_typing_prepare_subst_impl(typevartupleobject *self,
PyObject *alias, PyObject *args);
static PyObject *
typevartuple_typing_prepare_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(alias), &_Py_ID(args), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"alias", "args", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "__typing_prepare_subst__",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[2];
PyObject *alias;
PyObject *__clinic_args;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
if (!args) {
goto exit;
}
alias = args[0];
__clinic_args = args[1];
return_value = typevartuple_typing_prepare_subst_impl(self, alias, __clinic_args);
exit:
return return_value;
}
PyDoc_STRVAR(typevartuple_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define TYPEVARTUPLE_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)typevartuple_reduce, METH_NOARGS, typevartuple_reduce__doc__},
static PyObject *
typevartuple_reduce_impl(typevartupleobject *self);
static PyObject *
typevartuple_reduce(typevartupleobject *self, PyObject *Py_UNUSED(ignored))
{
return typevartuple_reduce_impl(self);
}
PyDoc_STRVAR(typealias_reduce__doc__,
"__reduce__($self, /)\n"
"--\n"
"\n");
#define TYPEALIAS_REDUCE_METHODDEF \
{"__reduce__", (PyCFunction)typealias_reduce, METH_NOARGS, typealias_reduce__doc__},
static PyObject *
typealias_reduce_impl(typealiasobject *self);
static PyObject *
typealias_reduce(typealiasobject *self, PyObject *Py_UNUSED(ignored))
{
return typealias_reduce_impl(self);
}
PyDoc_STRVAR(typealias_new__doc__,
"typealias(name, value, *, type_params=<unrepresentable>)\n"
"--\n"
"\n"
"Create a TypeAliasType.");
static PyObject *
typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
PyObject *type_params);
static PyObject *
typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "value", "type_params", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typealias",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[3];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2;
PyObject *name;
PyObject *value;
PyObject *type_params = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf);
if (!fastargs) {
goto exit;
}
if (!PyUnicode_Check(fastargs[0])) {
_PyArg_BadArgument("typealias", "argument 'name'", "str", fastargs[0]);
goto exit;
}
name = fastargs[0];
value = fastargs[1];
if (!noptargs) {
goto skip_optional_kwonly;
}
type_params = fastargs[2];
skip_optional_kwonly:
return_value = typealias_new_impl(type, name, value, type_params);
exit:
return return_value;
}
/*[clinic end generated code: output=807bcd30ebd10ac3 input=a9049054013a1b77]*/

View file

@ -127,6 +127,7 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr)
PyErr_Clear();
}
op->func_annotations = NULL;
op->func_typeparams = NULL;
op->vectorcall = _PyFunction_Vectorcall;
op->func_version = 0;
_PyObject_GC_TRACK(op);
@ -202,6 +203,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
op->func_weakreflist = NULL;
op->func_module = module;
op->func_annotations = NULL;
op->func_typeparams = NULL;
op->vectorcall = _PyFunction_Vectorcall;
op->func_version = 0;
_PyObject_GC_TRACK(op);
@ -652,6 +654,28 @@ func_set_annotations(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(igno
return 0;
}
static PyObject *
func_get_type_params(PyFunctionObject *op, void *Py_UNUSED(ignored))
{
if (op->func_typeparams == NULL) {
return PyTuple_New(0);
}
assert(PyTuple_Check(op->func_typeparams));
return Py_NewRef(op->func_typeparams);
}
PyObject *
_Py_set_function_type_params(PyThreadState *Py_UNUSED(ignored), PyObject *func,
PyObject *type_params)
{
assert(PyFunction_Check(func));
assert(PyTuple_Check(type_params));
PyFunctionObject *f = (PyFunctionObject *)func;
Py_XSETREF(f->func_typeparams, Py_NewRef(type_params));
return Py_NewRef(func);
}
static PyGetSetDef func_getsetlist[] = {
{"__code__", (getter)func_get_code, (setter)func_set_code},
{"__defaults__", (getter)func_get_defaults,
@ -663,6 +687,7 @@ static PyGetSetDef func_getsetlist[] = {
{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
{"__name__", (getter)func_get_name, (setter)func_set_name},
{"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname},
{"__type_params__", (getter)func_get_type_params, NULL},
{NULL} /* Sentinel */
};
@ -783,6 +808,7 @@ func_clear(PyFunctionObject *op)
Py_CLEAR(op->func_dict);
Py_CLEAR(op->func_closure);
Py_CLEAR(op->func_annotations);
Py_CLEAR(op->func_typeparams);
// Don't Py_CLEAR(op->func_code), since code is always required
// to be non-NULL. Similarly, name and qualname shouldn't be NULL.
// However, name and qualname could be str subclasses, so they
@ -837,6 +863,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
Py_VISIT(f->func_dict);
Py_VISIT(f->func_closure);
Py_VISIT(f->func_annotations);
Py_VISIT(f->func_typeparams);
Py_VISIT(f->func_qualname);
return 0;
}

View file

@ -14,6 +14,7 @@
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_symtable.h" // PySTEntry_Type
#include "pycore_typevarobject.h" // _PyTypeVar_Type etc., _Py_initialize_generic
#include "pycore_typeobject.h" // _PyBufferWrapper_Type
#include "pycore_unionobject.h" // _PyUnion_Type
#include "pycore_interpreteridobject.h" // _PyInterpreterID_Type
@ -2139,6 +2140,11 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
}
}
// Must be after static types are initialized
if (_Py_initialize_generic(interp) < 0) {
return _PyStatus_ERR("Can't initialize generic types");
}
return _PyStatus_OK();
}

View file

@ -1460,6 +1460,18 @@ type_get_annotations(PyTypeObject *type, void *context)
return annotations;
}
static PyObject *
type_get_type_params(PyTypeObject *type, void *context)
{
PyObject *params = PyDict_GetItem(lookup_tp_dict(type), &_Py_ID(__type_params__));
if (params) {
return Py_NewRef(params);
}
return PyTuple_New(0);
}
static int
type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
{
@ -1536,6 +1548,7 @@ static PyGetSetDef type_getsets[] = {
{"__doc__", (getter)type_get_doc, (setter)type_set_doc, NULL},
{"__text_signature__", (getter)type_get_text_signature, NULL, NULL},
{"__annotations__", (getter)type_get_annotations, (setter)type_set_annotations, NULL},
{"__type_params__", (getter)type_get_type_params, NULL, NULL},
{0}
};
@ -3130,11 +3143,12 @@ type_new_copy_slots(type_new_ctx *ctx, PyObject *dict)
goto error;
}
if (r > 0) {
/* CPython inserts __qualname__ and __classcell__ (when needed)
/* CPython inserts these names (when needed)
into the namespace when creating a class. They will be deleted
below so won't act as class variables. */
if (!_PyUnicode_Equal(slot, &_Py_ID(__qualname__)) &&
!_PyUnicode_Equal(slot, &_Py_ID(__classcell__)))
!_PyUnicode_Equal(slot, &_Py_ID(__classcell__)) &&
!_PyUnicode_Equal(slot, &_Py_ID(__classdictcell__)))
{
PyErr_Format(PyExc_ValueError,
"%R in __slots__ conflicts with class variable",
@ -3585,6 +3599,32 @@ type_new_set_classcell(PyTypeObject *type)
return 0;
}
static int
type_new_set_classdictcell(PyTypeObject *type)
{
PyObject *dict = lookup_tp_dict(type);
PyObject *cell = PyDict_GetItemWithError(dict, &_Py_ID(__classdictcell__));
if (cell == NULL) {
if (PyErr_Occurred()) {
return -1;
}
return 0;
}
/* At least one method requires a reference to the dict of its defining class */
if (!PyCell_Check(cell)) {
PyErr_Format(PyExc_TypeError,
"__classdictcell__ must be a nonlocal cell, not %.200R",
Py_TYPE(cell));
return -1;
}
(void)PyCell_Set(cell, (PyObject *)dict);
if (PyDict_DelItem(dict, &_Py_ID(__classdictcell__)) < 0) {
return -1;
}
return 0;
}
static int
type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type)
@ -3629,6 +3669,9 @@ type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type)
if (type_new_set_classcell(type) < 0) {
return -1;
}
if (type_new_set_classdictcell(type) < 0) {
return -1;
}
return 0;
}

1620
Objects/typevarobject.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -147,10 +147,14 @@ get_types(PyObject **obj, Py_ssize_t *size)
static int
is_unionable(PyObject *obj)
{
return (obj == Py_None ||
if (obj == Py_None ||
PyType_Check(obj) ||
_PyGenericAlias_Check(obj) ||
_PyUnion_Check(obj));
_PyUnion_Check(obj)) {
return 1;
}
PyInterpreterState *interp = PyInterpreterState_Get();
return Py_IS_TYPE(obj, interp->cached_objects.typealias_type);
}
PyObject *