Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Doc/c-api/interp-lifecycle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ Process-wide parameters
Return the version of this Python interpreter. This is a string that looks
something like ::
"3.15.0rc2 (3.15.0~rc2-1.fc44.x86_64, Sep 3 2026, 00:00:00) [GCC 16.2.1 20260819 (Red Hat 16.2.1-2)]"
"3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]"
.. index:: single: version (in module sys)
Expand Down
3 changes: 1 addition & 2 deletions Include/internal/pycore_pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extern int _Py_IsLocaleCoercionTarget(const char *ctype_loc);

/* Various one-time initializers */

extern PyStatus _Py_GetVersion_Init(void);
extern void _Py_InitVersion(void);
extern PyStatus _PyFaulthandler_Init(int enable);
extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp);
extern int _PyBuiltin_InitPythonFunctions(PyObject *dict);
Expand All @@ -43,7 +43,6 @@ extern PyStatus _PyDateTime_InitTypes(PyInterpreterState *interp);

/* Various internal finalizers */

extern void _Py_GetVersion_Fini(void);
extern int _PySignal_Init(int install_signal_handlers);
extern void _PySignal_Fini(void);

Expand Down
8 changes: 6 additions & 2 deletions Lib/test/test_capi/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ def test_getcopyright(self):

# Test Py_GetCompiler()
def test_getcompiler(self):
self.assertIn(_testlimitedcapi.py_getcompiler(), sys.version)
compiler = _testlimitedcapi.py_getcompiler()
self.assertIsInstance(compiler, str)
self.assertNotEqual(compiler, '')

# Test Py_GetBuildInfo()
def test_getbuildinfo(self):
self.assertIn(_testlimitedcapi.py_getbuildinfo(), sys.version)
buildinfo = _testlimitedcapi.py_getbuildinfo()
self.assertIsInstance(buildinfo, str)
self.assertNotEqual(buildinfo, '')

# Test internal _Py_GetBuiltWithAssert()
def test__getbuiltwithassert(self):
Expand Down
1 change: 0 additions & 1 deletion Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,6 @@ pymain_free(void)
_PyPathConfig_ClearGlobal();
_Py_ClearArgcArgv();
_PyRuntime_Finalize();
_Py_GetVersion_Fini();
}


Expand Down
9 changes: 4 additions & 5 deletions Python/getcompiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "Python.h"

// PC/pyconfig.h defines _Py_COMPILER
#ifdef _Py_COMPILER
# define COMPILER _Py_COMPILER
#endif
Expand All @@ -13,14 +12,14 @@
// Note the __clang__ conditional has to come before the __GNUC__ one because
// clang pretends to be GCC.
#if defined(__clang__)
# define COMPILER "[Clang " __clang_version__ "]"
#define COMPILER "[Clang " __clang_version__ "]"
#elif defined(__GNUC__)
# define COMPILER "[GCC " __VERSION__ "]"
#define COMPILER "[GCC " __VERSION__ "]"
// Generic fallbacks.
#elif defined(__cplusplus)
# define COMPILER "[C++]"
#define COMPILER "[C++]"
#else
# define COMPILER "[C]"
#define COMPILER "[C]"
#endif

#endif /* !COMPILER */
Expand Down
67 changes: 11 additions & 56 deletions Python/getversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,32 @@
/* Return the full version string. */

#include "Python.h"
#include "pycore_initconfig.h" // _PyStatus_NO_MEMORY()

#include "patchlevel.h"

static int initialized = 0;
// Use the smallest possible buffer: it's only needed if malloc() fails *and*
// Py_GetVersion() is called before Py_Initialize(). The buffer should be big
// enough to store "3.16.0a0 " string.
static char static_version[20];
static char *heap_version = NULL;
static char version[300];


PyStatus
_Py_GetVersion_Init(void)
void _Py_InitVersion(void)
{
if (initialized) {
return _PyStatus_OK();
return;
}

initialized = 1;
#ifdef Py_GIL_DISABLED
const char *format = "%s free-threading build (%s) %s";
size_t format_len = strlen(" free-threading build () ");
const char *buildinfo_format = "%.80s free-threading build (%.80s) %.80s";
#else
const char *format = "%s (%s) %s";
size_t format_len = strlen(" () ");
const char *buildinfo_format = "%.80s (%.80s) %.80s";
#endif
const char *version_str = PY_VERSION;
const char *buildinfo = Py_GetBuildInfo();
const char *compiler = Py_GetCompiler();
// +1 for the trailing NUL byte
size_t len = (format_len + strlen(version_str) + strlen(buildinfo)
+ strlen(compiler) + 1);

// Always format the static version
PyOS_snprintf(static_version, sizeof(static_version), format,
version_str, buildinfo, compiler);

heap_version = malloc(len);
if (heap_version == NULL) {
// If malloc() failed, don't set initialized to 1, so next
// Py_GetVersion() will try again to allocate memory.
return _PyStatus_NO_MEMORY();
}

PyOS_snprintf(heap_version, len, format,
version_str, buildinfo, compiler);
initialized = 1;
return _PyStatus_OK();
}

void
_Py_GetVersion_Fini(void)
{
if (heap_version) {
free(heap_version);
heap_version = NULL;
}
PyOS_snprintf(version, sizeof(version), buildinfo_format,
PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());
}

const char *
Py_GetVersion(void)
{
PyStatus status = _Py_GetVersion_Init();
// Ignore error: Py_GetVersion() API cannot report error
(void)status;

if (heap_version) {
return heap_version;
}
else {
return static_version;
}
_Py_InitVersion();
return version;
}

// Export the Python hex version as a constant.
Expand Down
6 changes: 1 addition & 5 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,11 +559,7 @@ pycore_init_runtime(_PyRuntimeState *runtime,
*/
_PyRuntimeState_SetFinalizing(runtime, NULL);

status = _Py_GetVersion_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
}

_Py_InitVersion();
_Py_DumpTraceback_Init();

status = _Py_HashRandomization_Init(config);
Expand Down
3 changes: 1 addition & 2 deletions Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ Objects/unicodeobject.c _init_global_state initialized -
Modules/getbuildinfo.c - buildinfo -
Modules/getbuildinfo.c - initialized -
Python/getversion.c - initialized -
Python/getversion.c - static_version -
Python/getversion.c - heap_version -
Python/getversion.c - version -

## public C-API - set during first init
Python/bootstrap_hash.c - _Py_HashSecret_Initialized -
Expand Down
Loading