Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Doc/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ interpreter and to functions that interact strongly with the interpreter. It is
always available. Unless explicitly noted otherwise, all variables are read-only.


.. data:: abi_features

A frozen set of strings that represent ABI features.
Currently supported features are:

``free-threading`` or ``gil-enabled``
The Python interpreter is free-threaded. On POSIX systems, this corresponds
to ``"t" in sys.abiflags``.

``debug``
The Python interpreter has debugging capabilities. On POSIX systems, this
corresponds to ``"d" in sys.abiflags``.

``32-bit`` or ``64-bit``
The bitness of the interpreter, that is, whether it is a 32-bit or 64-bit
build.
Comment on lines +27 to +29
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the right place. This information is part of the target architecture, where this API is meant to expose features of the Python ABI — see PEP 3149.


.. versionadded:: 3.14


.. data:: abiflags

On POSIX systems where Python was built with the standard ``configure``
Expand Down
66 changes: 66 additions & 0 deletions Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3479,6 +3479,71 @@ make_impl_info(PyObject *version_info)
return NULL;
}

static PyObject*
make_abi_features(void)
{
int res;
PyObject *features = PyFrozenSet_New(NULL);
if (features == NULL) {
goto error;
}

#ifdef Py_GIL_DISABLED
PyObject *threading_feature = PyUnicode_FromString("free-threading");
#else
PyObject *threading_feature = PyUnicode_FromString("gil-enabled");
#endif
if (threading_feature == NULL) {
goto error;
}
res = PySet_Add(features, threading_feature);
Py_DECREF(threading_feature);
if (res < 0) {
goto error;
}

#ifdef Py_DEBUG
PyObject *debug = PyUnicode_FromString("debug");
if (debug == NULL) {
goto error;
}
res = PySet_Add(features, debug);
Py_DECREF(debug);
if (res < 0) {
goto error;
}
#endif

PyObject *bitness;
switch (PY_SSIZE_T_MAX) {
case 0x7FFFFFFFL:
bitness = PyUnicode_FromString("32-bit");
break;
case 0x7FFFFFFFFFFFFFFFL:
bitness = PyUnicode_FromString("64-bit");
break;
default:
bitness = Py_NewRef(Py_None);
break;
}
Comment on lines +3518 to +3528
Copy link
Copy Markdown

@XuehaiPan XuehaiPan Mar 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would 0x7FFFFFFFFFFFFFFFL overflow on some platforms?

Suggested change
switch (PY_SSIZE_T_MAX) {
case 0x7FFFFFFFL:
bitness = PyUnicode_FromString("32-bit");
break;
case 0x7FFFFFFFFFFFFFFFL:
bitness = PyUnicode_FromString("64-bit");
break;
default:
bitness = Py_NewRef(Py_None);
break;
}
switch (SIZEOF_VOID_P) {
case 4:
bitness = PyUnicode_FromString("32-bit");
break;
case 8:
bitness = PyUnicode_FromString("64-bit");
break;
default:
bitness = Py_NewRef(Py_None);
break;
}

if (bitness == NULL) {
goto error;
}
if (bitness != Py_None) {
res = PySet_Add(features, bitness);
}
Py_DECREF(bitness);
if (res < 0) {
goto error;
}

return features;

error:
Py_XDECREF(features);
return NULL;
}

#ifdef __EMSCRIPTEN__

PyDoc_STRVAR(emscripten_info__doc__,
Expand Down Expand Up @@ -3665,6 +3730,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
#ifdef ABIFLAGS
SET_SYS_FROM_STRING("abiflags", ABIFLAGS);
#endif
SET_SYS("abi_features", make_abi_features());

#define ENSURE_INFO_TYPE(TYPE, DESC) \
do { \
Expand Down