mirror of
https://github.com/python/cpython.git
synced 2025-10-19 07:53:46 +00:00
Compare commits
8 commits
0c66da8de4
...
7f371ed84b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7f371ed84b | ||
![]() |
65d1a14d59 | ||
![]() |
bcced02604 | ||
![]() |
f673f0e7b4 | ||
![]() |
5213f1b684 | ||
![]() |
1624c646b0 | ||
![]() |
728d239e57 | ||
![]() |
d301587369 |
20 changed files with 188 additions and 63 deletions
|
@ -47,7 +47,7 @@ for ((i, prefix) in prefixes.withIndex()) {
|
|||
val libDir = file("$prefix/lib")
|
||||
val version = run {
|
||||
for (filename in libDir.list()!!) {
|
||||
"""python(\d+\.\d+)""".toRegex().matchEntire(filename)?.let {
|
||||
"""python(\d+\.\d+[a-z]*)""".toRegex().matchEntire(filename)?.let {
|
||||
return@run it.groupValues[1]
|
||||
}
|
||||
}
|
||||
|
@ -64,9 +64,10 @@ for ((i, prefix) in prefixes.withIndex()) {
|
|||
val libPythonDir = file("$libDir/python$pythonVersion")
|
||||
val triplet = run {
|
||||
for (filename in libPythonDir.list()!!) {
|
||||
"""_sysconfigdata__android_(.+).py""".toRegex().matchEntire(filename)?.let {
|
||||
return@run it.groupValues[1]
|
||||
}
|
||||
"""_sysconfigdata_[a-z]*_android_(.+).py""".toRegex()
|
||||
.matchEntire(filename)?.let {
|
||||
return@run it.groupValues[1]
|
||||
}
|
||||
}
|
||||
throw GradleException("Failed to find Python triplet in $libPythonDir")
|
||||
}
|
||||
|
|
|
@ -2243,7 +2243,7 @@ without the dedicated syntax, as documented below.
|
|||
.. versionadded:: 3.10
|
||||
|
||||
|
||||
.. class:: TypeAliasType(name, value, *, type_params=())
|
||||
.. class:: TypeAliasType(name, value, *, type_params=(), qualname=None)
|
||||
|
||||
The type of type aliases created through the :keyword:`type` statement.
|
||||
|
||||
|
@ -2267,6 +2267,20 @@ without the dedicated syntax, as documented below.
|
|||
>>> Alias.__name__
|
||||
'Alias'
|
||||
|
||||
.. attribute:: __qualname__
|
||||
|
||||
The :term:`qualified name` of the type alias:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> class Class:
|
||||
... type Alias = int
|
||||
...
|
||||
>>> Class.Alias.__qualname__
|
||||
'Class.Alias'
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. attribute:: __module__
|
||||
|
||||
The name of the module in which the type alias was defined::
|
||||
|
|
|
@ -1308,8 +1308,8 @@ The parts are separated by a decimal point, ``.``::
|
|||
2.71828
|
||||
4.0
|
||||
|
||||
Unlike in integer literals, leading zeros are allowed in the numeric parts.
|
||||
For example, ``077.010`` is legal, and denotes the same number as ``77.10``.
|
||||
Unlike in integer literals, leading zeros are allowed.
|
||||
For example, ``077.010`` is legal, and denotes the same number as ``77.01``.
|
||||
|
||||
As in integer literals, single underscores may occur between digits to help
|
||||
readability::
|
||||
|
|
|
@ -1974,6 +1974,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
|||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ps1));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ps2));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(qid));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(qualname));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(query));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(queuetype));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(quotetabs));
|
||||
|
|
|
@ -697,6 +697,7 @@ struct _Py_global_strings {
|
|||
STRUCT_FOR_ID(ps1)
|
||||
STRUCT_FOR_ID(ps2)
|
||||
STRUCT_FOR_ID(qid)
|
||||
STRUCT_FOR_ID(qualname)
|
||||
STRUCT_FOR_ID(query)
|
||||
STRUCT_FOR_ID(queuetype)
|
||||
STRUCT_FOR_ID(quotetabs)
|
||||
|
|
1
Include/internal/pycore_runtime_init_generated.h
generated
1
Include/internal/pycore_runtime_init_generated.h
generated
|
@ -1972,6 +1972,7 @@ extern "C" {
|
|||
INIT_ID(ps1), \
|
||||
INIT_ID(ps2), \
|
||||
INIT_ID(qid), \
|
||||
INIT_ID(qualname), \
|
||||
INIT_ID(query), \
|
||||
INIT_ID(queuetype), \
|
||||
INIT_ID(quotetabs), \
|
||||
|
|
|
@ -2576,6 +2576,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
|
|||
_PyUnicode_InternStatic(interp, &string);
|
||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||
string = &_Py_ID(qualname);
|
||||
_PyUnicode_InternStatic(interp, &string);
|
||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||
string = &_Py_ID(query);
|
||||
_PyUnicode_InternStatic(interp, &string);
|
||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||
|
|
|
@ -114,6 +114,8 @@ PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
|
|||
}
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
|
||||
# define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST(ob))
|
||||
#else
|
||||
# define Py_REFCNT(ob) _Py_REFCNT(ob)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""create and manipulate C data types in Python"""
|
||||
|
||||
import os as _os, sys as _sys
|
||||
import os as _os
|
||||
import sys as _sys
|
||||
import sysconfig as _sysconfig
|
||||
import types as _types
|
||||
|
||||
__version__ = "1.1.0"
|
||||
|
@ -550,10 +552,9 @@ def LoadLibrary(self, name):
|
|||
|
||||
if _os.name == "nt":
|
||||
pythonapi = PyDLL("python dll", None, _sys.dllhandle)
|
||||
elif _sys.platform == "android":
|
||||
pythonapi = PyDLL("libpython%d.%d.so" % _sys.version_info[:2])
|
||||
elif _sys.platform == "cygwin":
|
||||
pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
|
||||
elif _sys.platform in ["android", "cygwin"]:
|
||||
# These are Unix-like platforms which use a dynamically-linked libpython.
|
||||
pythonapi = PyDLL(_sysconfig.get_config_var("LDLIBRARY"))
|
||||
else:
|
||||
pythonapi = PyDLL(None)
|
||||
|
||||
|
|
|
@ -457,7 +457,7 @@ def from_name(cls, name: str) -> Distribution:
|
|||
try:
|
||||
return next(iter(cls._prefer_valid(cls.discover(name=name))))
|
||||
except StopIteration:
|
||||
raise PackageNotFoundError(name)
|
||||
raise PackageNotFoundError(name) from None
|
||||
|
||||
@classmethod
|
||||
def discover(
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
Callable, TypeAliasType, TypeVar, TypeVarTuple, ParamSpec, Unpack, get_args,
|
||||
)
|
||||
|
||||
type GlobalTypeAlias = int
|
||||
|
||||
def get_type_alias():
|
||||
type TypeAliasInFunc = str
|
||||
return TypeAliasInFunc
|
||||
|
||||
class TypeParamsInvalidTest(unittest.TestCase):
|
||||
def test_name_collisions(self):
|
||||
|
@ -70,6 +75,8 @@ def inner[B](self):
|
|||
|
||||
|
||||
class TypeParamsAliasValueTest(unittest.TestCase):
|
||||
type TypeAliasInClass = dict
|
||||
|
||||
def test_alias_value_01(self):
|
||||
type TA1 = int
|
||||
|
||||
|
@ -142,33 +149,67 @@ def test_subscripting(self):
|
|||
self.assertIs(specialized2.__origin__, VeryGeneric)
|
||||
self.assertEqual(specialized2.__args__, (int, str, float, [bool, range]))
|
||||
|
||||
def test___name__(self):
|
||||
type TypeAliasLocal = GlobalTypeAlias
|
||||
|
||||
self.assertEqual(GlobalTypeAlias.__name__, 'GlobalTypeAlias')
|
||||
self.assertEqual(get_type_alias().__name__, 'TypeAliasInFunc')
|
||||
self.assertEqual(self.TypeAliasInClass.__name__, 'TypeAliasInClass')
|
||||
self.assertEqual(TypeAliasLocal.__name__, 'TypeAliasLocal')
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
AttributeError,
|
||||
"readonly attribute",
|
||||
):
|
||||
setattr(TypeAliasLocal, '__name__', 'TA')
|
||||
|
||||
def test___qualname__(self):
|
||||
type TypeAliasLocal = GlobalTypeAlias
|
||||
|
||||
self.assertEqual(GlobalTypeAlias.__qualname__,
|
||||
'GlobalTypeAlias')
|
||||
self.assertEqual(get_type_alias().__qualname__,
|
||||
'get_type_alias.<locals>.TypeAliasInFunc')
|
||||
self.assertEqual(self.TypeAliasInClass.__qualname__,
|
||||
'TypeParamsAliasValueTest.TypeAliasInClass')
|
||||
self.assertEqual(TypeAliasLocal.__qualname__,
|
||||
'TypeParamsAliasValueTest.test___qualname__.<locals>.TypeAliasLocal')
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
AttributeError,
|
||||
"readonly attribute",
|
||||
):
|
||||
setattr(TypeAliasLocal, '__qualname__', 'TA')
|
||||
|
||||
def test_repr(self):
|
||||
type Simple = int
|
||||
type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
|
||||
self.assertEqual(repr(Simple), Simple.__qualname__)
|
||||
|
||||
self.assertEqual(repr(Simple), "Simple")
|
||||
self.assertEqual(repr(VeryGeneric), "VeryGeneric")
|
||||
type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
|
||||
self.assertEqual(repr(VeryGeneric), VeryGeneric.__qualname__)
|
||||
fullname = f"{VeryGeneric.__module__}.{VeryGeneric.__qualname__}"
|
||||
self.assertEqual(repr(VeryGeneric[int, bytes, str, [float, object]]),
|
||||
"VeryGeneric[int, bytes, str, [float, object]]")
|
||||
f"{fullname}[int, bytes, str, [float, object]]")
|
||||
self.assertEqual(repr(VeryGeneric[int, []]),
|
||||
"VeryGeneric[int, []]")
|
||||
f"{fullname}[int, []]")
|
||||
self.assertEqual(repr(VeryGeneric[int, [VeryGeneric[int], list[str]]]),
|
||||
"VeryGeneric[int, [VeryGeneric[int], list[str]]]")
|
||||
f"{fullname}[int, [{fullname}[int], list[str]]]")
|
||||
|
||||
def test_recursive_repr(self):
|
||||
type Recursive = Recursive
|
||||
self.assertEqual(repr(Recursive), "Recursive")
|
||||
self.assertEqual(repr(Recursive), Recursive.__qualname__)
|
||||
|
||||
type X = list[Y]
|
||||
type Y = list[X]
|
||||
self.assertEqual(repr(X), "X")
|
||||
self.assertEqual(repr(Y), "Y")
|
||||
self.assertEqual(repr(X), X.__qualname__)
|
||||
self.assertEqual(repr(Y), Y.__qualname__)
|
||||
|
||||
type GenericRecursive[X] = list[X | GenericRecursive[X]]
|
||||
self.assertEqual(repr(GenericRecursive), "GenericRecursive")
|
||||
self.assertEqual(repr(GenericRecursive[int]), "GenericRecursive[int]")
|
||||
self.assertEqual(repr(GenericRecursive), GenericRecursive.__qualname__)
|
||||
fullname = f"{GenericRecursive.__module__}.{GenericRecursive.__qualname__}"
|
||||
self.assertEqual(repr(GenericRecursive[int]), f"{fullname}[int]")
|
||||
self.assertEqual(repr(GenericRecursive[GenericRecursive[int]]),
|
||||
"GenericRecursive[GenericRecursive[int]]")
|
||||
f"{fullname}[{fullname}[int]]")
|
||||
|
||||
def test_raising(self):
|
||||
type MissingName = list[_My_X]
|
||||
|
@ -193,15 +234,25 @@ class TypeAliasConstructorTest(unittest.TestCase):
|
|||
def test_basic(self):
|
||||
TA = TypeAliasType("TA", int)
|
||||
self.assertEqual(TA.__name__, "TA")
|
||||
self.assertEqual(TA.__qualname__, "TA")
|
||||
self.assertIs(TA.__value__, int)
|
||||
self.assertEqual(TA.__type_params__, ())
|
||||
self.assertEqual(TA.__module__, __name__)
|
||||
|
||||
def test_with_qualname(self):
|
||||
TA = TypeAliasType("TA", str, qualname="Class.TA")
|
||||
self.assertEqual(TA.__name__, "TA")
|
||||
self.assertEqual(TA.__qualname__, "Class.TA")
|
||||
self.assertIs(TA.__value__, str)
|
||||
self.assertEqual(TA.__type_params__, ())
|
||||
self.assertEqual(TA.__module__, __name__)
|
||||
|
||||
def test_attributes_with_exec(self):
|
||||
ns = {}
|
||||
exec("type TA = int", ns, ns)
|
||||
TA = ns["TA"]
|
||||
self.assertEqual(TA.__name__, "TA")
|
||||
self.assertEqual(TA.__qualname__, "TA")
|
||||
self.assertIs(TA.__value__, int)
|
||||
self.assertEqual(TA.__type_params__, ())
|
||||
self.assertIs(TA.__module__, None)
|
||||
|
@ -210,6 +261,7 @@ def test_generic(self):
|
|||
T = TypeVar("T")
|
||||
TA = TypeAliasType("TA", list[T], type_params=(T,))
|
||||
self.assertEqual(TA.__name__, "TA")
|
||||
self.assertEqual(TA.__qualname__, "TA")
|
||||
self.assertEqual(TA.__value__, list[T])
|
||||
self.assertEqual(TA.__type_params__, (T,))
|
||||
self.assertEqual(TA.__module__, __name__)
|
||||
|
@ -218,6 +270,7 @@ def test_generic(self):
|
|||
def test_not_generic(self):
|
||||
TA = TypeAliasType("TA", list[int], type_params=())
|
||||
self.assertEqual(TA.__name__, "TA")
|
||||
self.assertEqual(TA.__qualname__, "TA")
|
||||
self.assertEqual(TA.__value__, list[int])
|
||||
self.assertEqual(TA.__type_params__, ())
|
||||
self.assertEqual(TA.__module__, __name__)
|
||||
|
@ -268,8 +321,9 @@ def test_expects_type_like(self):
|
|||
TypeAliasType("A", int, type_params=(T, 2))
|
||||
|
||||
def test_keywords(self):
|
||||
TA = TypeAliasType(name="TA", value=int)
|
||||
TA = TypeAliasType(name="TA", value=int, type_params=(), qualname=None)
|
||||
self.assertEqual(TA.__name__, "TA")
|
||||
self.assertEqual(TA.__qualname__, "TA")
|
||||
self.assertIs(TA.__value__, int)
|
||||
self.assertEqual(TA.__type_params__, ())
|
||||
self.assertEqual(TA.__module__, __name__)
|
||||
|
@ -283,6 +337,8 @@ def test_errors(self):
|
|||
TypeAliasType("TA", list, ())
|
||||
with self.assertRaises(TypeError):
|
||||
TypeAliasType("TA", list, type_params=42)
|
||||
with self.assertRaises(TypeError):
|
||||
TypeAliasType("TA", list, qualname=range(5))
|
||||
|
||||
|
||||
class TypeAliasTypeTest(unittest.TestCase):
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix :c:func:`Py_REFCNT` definition on limited C API 3.11-3.13. Patch by
|
||||
Victor Stinner.
|
|
@ -0,0 +1,2 @@
|
|||
Attribute ``__qualname__`` is added to :class:`typing.TypeAliasType`.
|
||||
Patch by Mikhail Efimov.
|
|
@ -0,0 +1,2 @@
|
|||
Speed up :meth:`io.RawIOBase.readall` by using PyBytesWriter API (about 4x
|
||||
faster)
|
|
@ -0,0 +1,5 @@
|
|||
The :py:class:`importlib.metadata.PackageNotFoundError` traceback raised when
|
||||
``importlib.metadata.Distribution.from_name`` cannot discover a
|
||||
distribution no longer includes a transient :exc:`StopIteration` exception trace.
|
||||
|
||||
Contributed by Bartosz Sławecki in :gh:`140142`.
|
|
@ -0,0 +1 @@
|
|||
Fix import of :mod:`ctypes` on Android and Cygwin when ABI flags are present.
|
|
@ -962,12 +962,10 @@ static PyObject *
|
|||
_io__RawIOBase_readall_impl(PyObject *self)
|
||||
/*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/
|
||||
{
|
||||
int r;
|
||||
PyObject *chunks = PyList_New(0);
|
||||
PyObject *result;
|
||||
|
||||
if (chunks == NULL)
|
||||
PyBytesWriter *writer = PyBytesWriter_Create(0);
|
||||
if (writer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
PyObject *data = _PyObject_CallMethod(self, &_Py_ID(read),
|
||||
|
@ -978,21 +976,21 @@ _io__RawIOBase_readall_impl(PyObject *self)
|
|||
if (_PyIO_trap_eintr()) {
|
||||
continue;
|
||||
}
|
||||
Py_DECREF(chunks);
|
||||
PyBytesWriter_Discard(writer);
|
||||
return NULL;
|
||||
}
|
||||
if (data == Py_None) {
|
||||
if (PyList_GET_SIZE(chunks) == 0) {
|
||||
Py_DECREF(chunks);
|
||||
if (PyBytesWriter_GetSize(writer) == 0) {
|
||||
PyBytesWriter_Discard(writer);
|
||||
return data;
|
||||
}
|
||||
Py_DECREF(data);
|
||||
break;
|
||||
}
|
||||
if (!PyBytes_Check(data)) {
|
||||
Py_DECREF(chunks);
|
||||
Py_DECREF(data);
|
||||
PyErr_SetString(PyExc_TypeError, "read() should return bytes");
|
||||
PyBytesWriter_Discard(writer);
|
||||
return NULL;
|
||||
}
|
||||
if (PyBytes_GET_SIZE(data) == 0) {
|
||||
|
@ -1000,16 +998,16 @@ _io__RawIOBase_readall_impl(PyObject *self)
|
|||
Py_DECREF(data);
|
||||
break;
|
||||
}
|
||||
r = PyList_Append(chunks, data);
|
||||
Py_DECREF(data);
|
||||
if (r < 0) {
|
||||
Py_DECREF(chunks);
|
||||
if (PyBytesWriter_WriteBytes(writer,
|
||||
PyBytes_AS_STRING(data),
|
||||
PyBytes_GET_SIZE(data)) < 0) {
|
||||
Py_DECREF(data);
|
||||
PyBytesWriter_Discard(writer);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(data);
|
||||
}
|
||||
result = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
|
||||
Py_DECREF(chunks);
|
||||
return result;
|
||||
return PyBytesWriter_Finish(writer);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
|
@ -3366,11 +3366,13 @@ static PyMemberDef pystatx_result_members[] = {
|
|||
"minimum size for direct I/O with torn-write protection"),
|
||||
MM(stx_atomic_write_unit_max, Py_T_UINT, atomic_write_unit_max,
|
||||
"maximum size for direct I/O with torn-write protection"),
|
||||
MM(stx_atomic_write_unit_max_opt, Py_T_UINT, atomic_write_unit_max_opt,
|
||||
"maximum optimized size for direct I/O with torn-write protection"),
|
||||
MM(stx_atomic_write_segments_max, Py_T_UINT, atomic_write_segments_max,
|
||||
"maximum iovecs for direct I/O with torn-write protection"),
|
||||
#endif
|
||||
#if 0
|
||||
MM(stx_atomic_write_unit_max_opt, Py_T_UINT, atomic_write_unit_max_opt,
|
||||
"maximum optimized size for direct I/O with torn-write protection"),
|
||||
#endif
|
||||
#ifdef STATX_DIO_READ_ALIGN
|
||||
MM(stx_dio_read_offset_align, Py_T_UINT, dio_read_offset_align,
|
||||
"direct I/O file offset alignment for reads"),
|
||||
|
|
25
Objects/clinic/typevarobject.c.h
generated
25
Objects/clinic/typevarobject.c.h
generated
|
@ -688,14 +688,14 @@ typealias_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(typealias_new__doc__,
|
||||
"typealias(name, value, *, type_params=<unrepresentable>)\n"
|
||||
"typealias(name, value, *, type_params=<unrepresentable>, qualname=None)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Create a TypeAliasType.");
|
||||
|
||||
static PyObject *
|
||||
typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
|
||||
PyObject *type_params);
|
||||
PyObject *type_params, PyObject *qualname);
|
||||
|
||||
static PyObject *
|
||||
typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
|
@ -703,7 +703,7 @@ 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
|
||||
#define NUM_KEYWORDS 4
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
|
@ -712,7 +712,7 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), },
|
||||
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), &_Py_ID(qualname), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
@ -721,20 +721,21 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"name", "value", "type_params", NULL};
|
||||
static const char * const _keywords[] = {"name", "value", "type_params", "qualname", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "typealias",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[3];
|
||||
PyObject *argsbuf[4];
|
||||
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;
|
||||
PyObject *qualname = NULL;
|
||||
|
||||
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
|
||||
/*minpos*/ 2, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||
|
@ -750,11 +751,17 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
type_params = fastargs[2];
|
||||
if (fastargs[2]) {
|
||||
type_params = fastargs[2];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
qualname = fastargs[3];
|
||||
skip_optional_kwonly:
|
||||
return_value = typealias_new_impl(type, name, value, type_params);
|
||||
return_value = typealias_new_impl(type, name, value, type_params, qualname);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=9dad71445e079303 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=67ab9a5d1869f2c9 input=a9049054013a1b77]*/
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *name;
|
||||
PyObject *qualname;
|
||||
PyObject *type_params;
|
||||
PyObject *compute_value;
|
||||
PyObject *value;
|
||||
|
@ -1858,6 +1859,7 @@ typealias_dealloc(PyObject *self)
|
|||
_PyObject_GC_UNTRACK(self);
|
||||
typealiasobject *ta = typealiasobject_CAST(self);
|
||||
Py_XDECREF(ta->name);
|
||||
Py_XDECREF(ta->qualname);
|
||||
Py_XDECREF(ta->type_params);
|
||||
Py_XDECREF(ta->compute_value);
|
||||
Py_XDECREF(ta->value);
|
||||
|
@ -1884,11 +1886,12 @@ static PyObject *
|
|||
typealias_repr(PyObject *self)
|
||||
{
|
||||
typealiasobject *ta = (typealiasobject *)self;
|
||||
return Py_NewRef(ta->name);
|
||||
return Py_NewRef(ta->qualname);
|
||||
}
|
||||
|
||||
static PyMemberDef typealias_members[] = {
|
||||
{"__name__", _Py_T_OBJECT, offsetof(typealiasobject, name), Py_READONLY},
|
||||
{"__qualname__", _Py_T_OBJECT, offsetof(typealiasobject, qualname), Py_READONLY},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -2003,7 +2006,7 @@ typealias_check_type_params(PyObject *type_params, int *err) {
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
typelias_convert_type_params(PyObject *type_params)
|
||||
typealias_convert_type_params(PyObject *type_params)
|
||||
{
|
||||
if (
|
||||
type_params == NULL
|
||||
|
@ -2018,14 +2021,15 @@ typelias_convert_type_params(PyObject *type_params)
|
|||
}
|
||||
|
||||
static typealiasobject *
|
||||
typealias_alloc(PyObject *name, PyObject *type_params, PyObject *compute_value,
|
||||
PyObject *value, PyObject *module)
|
||||
typealias_alloc(PyObject *name, PyObject *qualname, PyObject *type_params,
|
||||
PyObject *compute_value, PyObject *value, PyObject *module)
|
||||
{
|
||||
typealiasobject *ta = PyObject_GC_New(typealiasobject, &_PyTypeAlias_Type);
|
||||
if (ta == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ta->name = Py_NewRef(name);
|
||||
ta->qualname = Py_NewRef(qualname);
|
||||
ta->type_params = Py_XNewRef(type_params);
|
||||
ta->compute_value = Py_XNewRef(compute_value);
|
||||
ta->value = Py_XNewRef(value);
|
||||
|
@ -2039,6 +2043,7 @@ typealias_traverse(PyObject *op, visitproc visit, void *arg)
|
|||
{
|
||||
typealiasobject *self = typealiasobject_CAST(op);
|
||||
Py_VISIT(self->name);
|
||||
Py_VISIT(self->qualname);
|
||||
Py_VISIT(self->type_params);
|
||||
Py_VISIT(self->compute_value);
|
||||
Py_VISIT(self->value);
|
||||
|
@ -2051,6 +2056,7 @@ typealias_clear(PyObject *op)
|
|||
{
|
||||
typealiasobject *self = typealiasobject_CAST(op);
|
||||
Py_CLEAR(self->name);
|
||||
Py_CLEAR(self->qualname);
|
||||
Py_CLEAR(self->type_params);
|
||||
Py_CLEAR(self->compute_value);
|
||||
Py_CLEAR(self->value);
|
||||
|
@ -2096,14 +2102,15 @@ typealias.__new__ as typealias_new
|
|||
value: object
|
||||
*
|
||||
type_params: object = NULL
|
||||
qualname: object(c_default="NULL") = None
|
||||
|
||||
Create a TypeAliasType.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
|
||||
PyObject *type_params)
|
||||
/*[clinic end generated code: output=8920ce6bdff86f00 input=df163c34e17e1a35]*/
|
||||
PyObject *type_params, PyObject *qualname)
|
||||
/*[clinic end generated code: output=b7f6d9f1c577cd9c input=cbec290f8c4886ef]*/
|
||||
{
|
||||
if (type_params != NULL && !PyTuple_Check(type_params)) {
|
||||
PyErr_SetString(PyExc_TypeError, "type_params must be a tuple");
|
||||
|
@ -2120,8 +2127,19 @@ typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
|
|||
if (module == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *ta = (PyObject *)typealias_alloc(name, checked_params, NULL, value,
|
||||
module);
|
||||
|
||||
if (qualname == NULL || qualname == Py_None) {
|
||||
// If qualname was not set directly, we use name instead.
|
||||
qualname = name;
|
||||
} else {
|
||||
if (!PyUnicode_Check(qualname)) {
|
||||
PyErr_SetString(PyExc_TypeError, "qualname must be a string");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *ta = (PyObject *)typealias_alloc(
|
||||
name, qualname, checked_params, NULL, value, module);
|
||||
Py_DECREF(module);
|
||||
return ta;
|
||||
}
|
||||
|
@ -2187,10 +2205,17 @@ _Py_make_typealias(PyThreadState* unused, PyObject *args)
|
|||
assert(PyTuple_GET_SIZE(args) == 3);
|
||||
PyObject *name = PyTuple_GET_ITEM(args, 0);
|
||||
assert(PyUnicode_Check(name));
|
||||
PyObject *type_params = typelias_convert_type_params(PyTuple_GET_ITEM(args, 1));
|
||||
PyObject *type_params = typealias_convert_type_params(PyTuple_GET_ITEM(args, 1));
|
||||
PyObject *compute_value = PyTuple_GET_ITEM(args, 2);
|
||||
assert(PyFunction_Check(compute_value));
|
||||
return (PyObject *)typealias_alloc(name, type_params, compute_value, NULL, NULL);
|
||||
|
||||
PyFunctionObject *compute_func = (PyFunctionObject *)compute_value;
|
||||
PyCodeObject *code_obj = (PyCodeObject *)compute_func->func_code;
|
||||
PyObject *qualname = code_obj->co_qualname;
|
||||
assert(qualname != NULL);
|
||||
|
||||
return (PyObject *)typealias_alloc(
|
||||
name, qualname, type_params, compute_value, NULL, NULL);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(generic_doc,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue