Skip to content

Commit 90f0d46

Browse files
Merge branch 'main' into code
2 parents 19b6f6d + 1acb718 commit 90f0d46

8 files changed

Lines changed: 149 additions & 4 deletions

File tree

Doc/c-api/init.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,12 @@ code, or when embedding the Python interpreter:
10201020
interpreter lock is also shared by all threads, regardless of to which
10211021
interpreter they belong.
10221022
1023+
.. versionchanged:: 3.12
1024+
1025+
:pep:`684` introduced the possibility
1026+
of a :ref:`per-interpreter GIL <per-interpreter-gil>`.
1027+
See :c:func:`Py_NewInterpreterFromConfig`.
1028+
10231029
10241030
.. c:type:: PyThreadState
10251031
@@ -1711,6 +1717,8 @@ function. You can create and destroy them using the following functions:
17111717
haven't been explicitly destroyed at that point.
17121718
17131719
1720+
.. _per-interpreter-gil:
1721+
17141722
A Per-Interpreter GIL
17151723
---------------------
17161724
@@ -1722,7 +1730,7 @@ being blocked by other interpreters or blocking any others. Thus a
17221730
single Python process can truly take advantage of multiple CPU cores
17231731
when running Python code. The isolation also encourages a different
17241732
approach to concurrency than that of just using threads.
1725-
(See :pep:`554`.)
1733+
(See :pep:`554` and :pep:`684`.)
17261734
17271735
Using an isolated interpreter requires vigilance in preserving that
17281736
isolation. That especially means not sharing any objects or mutable

Doc/library/sys.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,51 @@ interpreter and to functions that interact strongly with the interpreter. It is
1111
always available. Unless explicitly noted otherwise, all variables are read-only.
1212

1313

14+
.. data:: abi_info
15+
16+
.. versionadded:: next
17+
18+
An object containing information about the ABI of the currently running
19+
Python interpreter.
20+
It should include information that affect the CPython ABI in ways that
21+
require a specific build of the interpreter chosen from variants that can
22+
co-exist on a single machine.
23+
For example, it does not encode the base OS (Linux or Windows), but does
24+
include pointer size since some systems support both 32- and 64-bit builds.
25+
The available entries are the same on all platforms;
26+
e.g. *pointer_size* is available even on 64-bit-only architectures.
27+
28+
The following attributes are available:
29+
30+
.. attribute:: abi_info.pointer_bits
31+
32+
The width of pointers in bits, as an integer,
33+
equivalent to ``8 * sizeof(void *)``.
34+
Usually, this is ``32`` or ``64``.
35+
36+
.. attribute:: abi_info.free_threaded
37+
38+
A Boolean indicating whether the interpreter was built with
39+
:term:`free threading` support.
40+
This reflects either the presence of the :option:`--disable-gil`
41+
:file:`configure` option (on Unix)
42+
or setting the ``DisableGil`` property (on Windows).
43+
44+
.. attribute:: abi_info.debug
45+
46+
A Boolean indicating whether the interpreter was built in
47+
:ref:`debug mode <debug-build>`.
48+
This reflects either the presence of the :option:`--with-pydebug`
49+
:file:`configure` option (on Unix)
50+
or the ``Debug`` configuration (on Windows).
51+
52+
.. attribute:: abi_info.byteorder
53+
54+
A string indicating the native byte order,
55+
either ``'big'`` or ``'little'``.
56+
This is the same as the :data:`byteorder` attribute.
57+
58+
1459
.. data:: abiflags
1560

1661
On POSIX systems where Python was built with the standard ``configure``

Doc/whatsnew/3.15.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,13 @@ ssl
460460
(Contributed by Ron Frederick in :gh:`138252`.)
461461

462462

463+
sys
464+
---
465+
466+
* Add :data:`sys.abi_info` namespace to improve access to ABI information.
467+
(Contributed by Klaus Zimmermann in :gh:`137476`.)
468+
469+
463470
tarfile
464471
-------
465472

Lib/test/test_sys.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,20 @@ def test_thread_info(self):
739739
elif sys.platform == "wasi":
740740
self.assertEqual(info.name, "pthread-stubs")
741741

742+
def test_abi_info(self):
743+
info = sys.abi_info
744+
self.assertEqual(len(info.__dict__), 4)
745+
pointer_bits = 64 if sys.maxsize > 2**32 else 32
746+
self.assertEqual(info.pointer_bits, pointer_bits)
747+
self.assertEqual(info.byteorder, sys.byteorder)
748+
for attr, flag in [
749+
("free_threaded", "Py_GIL_DISABLED"),
750+
("debug", "Py_DEBUG"),
751+
]:
752+
self.assertEqual(getattr(info, attr, None),
753+
bool(sysconfig.get_config_var(flag)),
754+
f"for {attr}")
755+
742756
@unittest.skipUnless(support.is_emscripten, "only available on Emscripten")
743757
def test_emscripten_info(self):
744758
self.assertEqual(len(sys._emscripten_info), 4)

Lib/test/test_tarfile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3694,7 +3694,7 @@ def setUpClass(cls):
36943694
else:
36953695
raise AssertionError('Could not determine link resolution')
36963696
else:
3697-
cls.dotdot_resolves_early = True
3697+
cls.dotdot_resolves_early = False
36983698

36993699
@contextmanager
37003700
def check_context(self, tar, filter, *, check_flag=True):
@@ -3842,7 +3842,7 @@ def test_parent_symlink(self):
38423842
arc.add('current', symlink_to='.')
38433843

38443844
# effectively points to ./../
3845-
if self.dotdot_resolves_early:
3845+
if self.dotdot_resolves_early and os_helper.can_symlink():
38463846
arc.add('parent', symlink_to='current/../..')
38473847
else:
38483848
arc.add('parent', symlink_to='current/..')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ``sys.abi_info`` object to make ABI information more easily accessible.

Modules/gcmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ PyDoc_STRVAR(gc__doc__,
478478
"set_debug() -- Set debugging flags.\n"
479479
"get_debug() -- Get debugging flags.\n"
480480
"set_threshold() -- Set the collection thresholds.\n"
481-
"get_threshold() -- Return the current the collection thresholds.\n"
481+
"get_threshold() -- Return the current collection thresholds.\n"
482482
"get_objects() -- Return a list of all objects tracked by the collector.\n"
483483
"is_tracked() -- Returns true if a given object is tracked.\n"
484484
"is_finalized() -- Returns true if a given object has been already finalized.\n"

Python/sysmodule.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,6 +3268,7 @@ PyDoc_STR(
32683268
"\n\
32693269
Static objects:\n\
32703270
\n\
3271+
abi_info -- Python ABI information.\n\
32713272
builtin_module_names -- tuple of module names built into this interpreter\n\
32723273
copyright -- copyright notice pertaining to this interpreter\n\
32733274
exec_prefix -- prefix used to find the machine-specific Python library\n\
@@ -3638,6 +3639,73 @@ make_impl_info(PyObject *version_info)
36383639
return NULL;
36393640
}
36403641

3642+
3643+
static PyObject *
3644+
make_abi_info(void)
3645+
{
3646+
// New entries should be added when needed for a supported platform, or (for
3647+
// enabling an unsupported one) by core dev consensus. Entries should be removed
3648+
// following PEP 387.
3649+
int res;
3650+
PyObject *abi_info, *value, *ns;
3651+
abi_info = PyDict_New();
3652+
if (abi_info == NULL) {
3653+
goto error;
3654+
}
3655+
3656+
value = PyLong_FromLong(sizeof(void *) * 8);
3657+
if (value == NULL) {
3658+
goto error;
3659+
}
3660+
res = PyDict_SetItemString(abi_info, "pointer_bits", value);
3661+
Py_DECREF(value);
3662+
if (res < 0) {
3663+
goto error;
3664+
}
3665+
3666+
#ifdef Py_GIL_DISABLED
3667+
value = Py_True;
3668+
#else
3669+
value = Py_False;
3670+
#endif
3671+
res = PyDict_SetItemString(abi_info, "free_threaded", value);
3672+
if (res < 0) {
3673+
goto error;
3674+
}
3675+
3676+
#ifdef Py_DEBUG
3677+
value = Py_True;
3678+
#else
3679+
value = Py_False;
3680+
#endif
3681+
res = PyDict_SetItemString(abi_info, "debug", value);
3682+
if (res < 0) {
3683+
goto error;
3684+
}
3685+
3686+
#if PY_BIG_ENDIAN
3687+
value = PyUnicode_FromString("big");
3688+
#else
3689+
value = PyUnicode_FromString("little");
3690+
#endif
3691+
if (value == NULL) {
3692+
goto error;
3693+
}
3694+
res = PyDict_SetItemString(abi_info, "byteorder", value);
3695+
Py_DECREF(value);
3696+
if (res < 0) {
3697+
goto error;
3698+
}
3699+
3700+
ns = _PyNamespace_New(abi_info);
3701+
Py_DECREF(abi_info);
3702+
return ns;
3703+
3704+
error:
3705+
Py_DECREF(abi_info);
3706+
return NULL;
3707+
}
3708+
36413709
#ifdef __EMSCRIPTEN__
36423710

36433711
PyDoc_STRVAR(emscripten_info__doc__,
@@ -3863,6 +3931,8 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
38633931

38643932
SET_SYS("thread_info", PyThread_GetInfo());
38653933

3934+
SET_SYS("abi_info", make_abi_info());
3935+
38663936
/* initialize asyncgen_hooks */
38673937
if (_PyStructSequence_InitBuiltin(interp, &AsyncGenHooksType,
38683938
&asyncgen_hooks_desc) < 0)

0 commit comments

Comments
 (0)