]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-43931: Export Python version as API data (GH-25577)
authorGabriele N. Tornetta <P403n1x87@users.noreply.github.com>
Fri, 10 Dec 2021 01:52:05 +0000 (01:52 +0000)
committerGitHub <noreply@github.com>
Fri, 10 Dec 2021 01:52:05 +0000 (17:52 -0800)
When Python is embedded in other applications, it is not easy to determine which version of Python is being used. This change exposes the Python version as part of the API data. Tools like Austin (https://github.com/P403n1x87/austin) can benefit from this data when targeting applications like uWSGI, as the Python version can then be inferred systematically by looking at the exported symbols rather than relying on unreliable pattern matching or other hacks (like remote code execution etc...).

Automerge-Triggered-By: GH:pablogsal
12 files changed:
Doc/c-api/apiabiversion.rst
Doc/c-api/init.rst
Doc/data/stable_abi.dat
Doc/whatsnew/3.11.rst
Include/pylifecycle.h
Lib/test/test_capi.py
Lib/test/test_stable_abi_ctypes.py
Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst [new file with mode: 0644]
Misc/stable_abi.txt
Modules/_testcapimodule.c
PC/python3dll.c
Python/getversion.c

index 04050f7dabe172864eb68f9b412fcf730548bf86..53a42e7f28ef103ec188fadba1c2098dd672fd63 100644 (file)
@@ -58,5 +58,14 @@ See :ref:`stable` for a discussion of API and ABI stability across versions.
    Thus ``3.4.1a2`` is hexversion ``0x030401a2`` and ``3.10.0`` is
    hexversion ``0x030a00f0``.
 
+   This version is also available via the symbol :data:`Py_Version`.
+
+.. c:var:: const unsigned long Py_Version
+
+   The Python runtime version number encoded in a single constant integer, with
+   the same format as the c:macro:`PY_VERSION_HEX` macro.
+   This contains the Python version used at run time.
+
+   .. versionadded:: 3.11
 
 All the given macros are defined in :source:`Include/patchlevel.h`.
index 09dfc68fee57dc73a87cfadf1c954cfbaea7d17a..322b9e4d251e76c57931f93f405fea43d01bc45b 100644 (file)
@@ -553,6 +553,8 @@ Process-wide parameters
    period.  The returned string points into static storage; the caller should not
    modify its value.  The value is available to Python code as :data:`sys.version`.
 
+   See also the :data:`Py_Version` constant.
+
 
 .. c:function:: const char* Py_GetPlatform()
 
index 64a0a2a247cd20c2fdd8aa8be892f0cd77c746ff..02e54e5d7f14abffc3bba10b75b535c264f6a0ea 100644 (file)
@@ -830,6 +830,7 @@ type,Py_UCS4,3.2,
 macro,Py_UNBLOCK_THREADS,3.2,
 var,Py_UTF8Mode,3.8,
 function,Py_VaBuildValue,3.2,
+var,Py_Version,3.11,
 function,Py_XNewRef,3.10,
 type,Py_intptr_t,3.2,
 type,Py_ssize_t,3.2,
index 7a828663e7f34ed0fef431416581709331742b07..8d1f4eba36eb24c507c23c6635035fa1dce62834 100644 (file)
@@ -626,6 +626,10 @@ New Features
   fields of the result from the exception instance (the ``value`` field).
   (Contributed by Irit Katriel in :issue:`45711`.)
 
+* Added the :c:data:`Py_Version` constant which bears the same value as
+  :c:macro:`PY_VERSION_HEX`.
+  (Contributed by  Gabriele N. Tornetta in :issue:`43931`.)
+
 
 Porting to Python 3.11
 ----------------------
index 4aecda235abf763cecdc0f8a6e77a675e71ac2c2..e4c3b09c963fe8ae115247ad64d770ef81d072ee 100644 (file)
@@ -62,6 +62,10 @@ typedef void (*PyOS_sighandler_t)(int);
 PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
 PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
 
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000
+PyAPI_DATA(const unsigned long) Py_Version;
+#endif
+
 #ifndef Py_LIMITED_API
 #  define Py_CPYTHON_PYLIFECYCLE_H
 #  include "cpython/pylifecycle.h"
index d51247003ded1c8d462bc91ef5b845dc24bbde0b..ecf3aa34ede7c17f7f219e36f1bdc5dcaa3cc35f 100644 (file)
@@ -840,6 +840,9 @@ class Test_testcapi(unittest.TestCase):
     def test_widechar(self):
         _testcapi.test_widechar()
 
+    def test_version_api_data(self):
+        self.assertEqual(_testcapi.Py_Version, sys.hexversion)
+
 
 class Test_testinternalcapi(unittest.TestCase):
     locals().update((name, getattr(_testinternalcapi, name))
index d0cd5c20dd5f42fc9aa32a4cb1e8baa949cb6f70..9fd6b14b0232a4a8a71fd5de431d4b8b332d5936 100644 (file)
@@ -808,6 +808,7 @@ SYMBOL_NAMES = (
     "Py_SetRecursionLimit",
     "Py_UTF8Mode",
     "Py_VaBuildValue",
+    "Py_Version",
     "Py_XNewRef",
     "_PyArg_ParseTupleAndKeywords_SizeT",
     "_PyArg_ParseTuple_SizeT",
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-24-15-39-23.bpo-43931.zpChDi.rst
new file mode 100644 (file)
index 0000000..0375129
--- /dev/null
@@ -0,0 +1,2 @@
+Added the :c:data:`Py_Version` constant which bears the same value as
+:c:macro:`PY_VERSION_HEX`. Patch by Gabriele N. Tornetta.
\ No newline at end of file
index de6caa8c807467be14775be42df1d77f69c6a763..9cb210c60cf246a6788657278f674b340cb5a4e9 100644 (file)
@@ -2153,3 +2153,6 @@ data PyStructSequence_UnnamedField
 
 # (Detailed comments aren't really needed for further entries: from here on
 #  we can use version control logs.)
+
+data Py_Version
+    added 3.11
index 56d394985eb7c5b8262efe71bf0b23cb66f85ebd..6116365b2c0f7191e9bbf2a12ff5c4e6069f5050 100644 (file)
@@ -7525,6 +7525,7 @@ PyInit__testcapi(void)
     PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyLong_FromSsize_t(PY_SSIZE_T_MAX));
     PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyLong_FromSsize_t(PY_SSIZE_T_MIN));
     PyModule_AddObject(m, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t)));
+    PyModule_AddObject(m, "Py_Version", PyLong_FromUnsignedLong(Py_Version));
     Py_INCREF(&PyInstanceMethod_Type);
     PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type);
 
index 6e469357ede506352955cd7037577985ca94d0b0..b2bb1706c4a2ebd7f45dd829b37e66e3e18b42f2 100755 (executable)
@@ -725,6 +725,7 @@ EXPORT_DATA(Py_FileSystemDefaultEncoding)
 EXPORT_DATA(Py_GenericAliasType)
 EXPORT_DATA(Py_HasFileSystemDefaultEncoding)
 EXPORT_DATA(Py_UTF8Mode)
+EXPORT_DATA(Py_Version)
 EXPORT_DATA(PyBaseObject_Type)
 EXPORT_DATA(PyBool_Type)
 EXPORT_DATA(PyByteArray_Type)
index c32b6f9d60d4b751d30d0539f103ee7c52e6a633..46910451fdf859f1836e4a1148adc3588dbb3712 100644 (file)
@@ -13,3 +13,6 @@ Py_GetVersion(void)
                   PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());
     return version;
 }
+
+// Export the Python hex version as a constant.
+const unsigned long Py_Version = PY_VERSION_HEX;