Skip to content

Commit 1acb718

Browse files
zklausencukouvstinnerAA-Turner
authored
gh-133143: Add sys.abi_info (GH-137476)
This makes information about the interpreter ABI more accessible. Co-authored-by: Petr Viktorin <[email protected]> Co-authored-by: Victor Stinner <[email protected]> Co-authored-by: Adam Turner <[email protected]>
1 parent c006a62 commit 1acb718

File tree

5 files changed

+137
-0
lines changed

5 files changed

+137
-0
lines changed

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)
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.

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)