mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-128629: Add Py_PACK_VERSION and Py_PACK_FULL_VERSION (GH-128630)
This commit is contained in:
parent
4685401845
commit
1439b81928
18 changed files with 358 additions and 33 deletions
|
@ -6,9 +6,13 @@
|
|||
API and ABI Versioning
|
||||
***********************
|
||||
|
||||
|
||||
Build-time version constants
|
||||
----------------------------
|
||||
|
||||
CPython exposes its version number in the following macros.
|
||||
Note that these correspond to the version code is **built** with,
|
||||
not necessarily the version used at **run time**.
|
||||
Note that these correspond to the version code is **built** with.
|
||||
See :c:var:`Py_Version` for the version used at **run time**.
|
||||
|
||||
See :ref:`stable` for a discussion of API and ABI stability across versions.
|
||||
|
||||
|
@ -37,37 +41,83 @@ See :ref:`stable` for a discussion of API and ABI stability across versions.
|
|||
.. c:macro:: PY_VERSION_HEX
|
||||
|
||||
The Python version number encoded in a single integer.
|
||||
See :c:func:`Py_PACK_FULL_VERSION` for the encoding details.
|
||||
|
||||
The underlying version information can be found by treating it as a 32 bit
|
||||
number in the following manner:
|
||||
Use this for numeric comparisons, for example,
|
||||
``#if PY_VERSION_HEX >= ...``.
|
||||
|
||||
+-------+-------------------------+-------------------------+--------------------------+
|
||||
| Bytes | Bits (big endian order) | Meaning | Value for ``3.4.1a2`` |
|
||||
+=======+=========================+=========================+==========================+
|
||||
| 1 | 1-8 | ``PY_MAJOR_VERSION`` | ``0x03`` |
|
||||
+-------+-------------------------+-------------------------+--------------------------+
|
||||
| 2 | 9-16 | ``PY_MINOR_VERSION`` | ``0x04`` |
|
||||
+-------+-------------------------+-------------------------+--------------------------+
|
||||
| 3 | 17-24 | ``PY_MICRO_VERSION`` | ``0x01`` |
|
||||
+-------+-------------------------+-------------------------+--------------------------+
|
||||
| 4 | 25-28 | ``PY_RELEASE_LEVEL`` | ``0xA`` |
|
||||
+ +-------------------------+-------------------------+--------------------------+
|
||||
| | 29-32 | ``PY_RELEASE_SERIAL`` | ``0x2`` |
|
||||
+-------+-------------------------+-------------------------+--------------------------+
|
||||
|
||||
Thus ``3.4.1a2`` is hexversion ``0x030401a2`` and ``3.10.0`` is
|
||||
hexversion ``0x030a00f0``.
|
||||
|
||||
Use this for numeric comparisons, e.g. ``#if PY_VERSION_HEX >= ...``.
|
||||
|
||||
This version is also available via the symbol :c:var:`Py_Version`.
|
||||
Run-time 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.
|
||||
The Python runtime version number encoded in a single constant integer.
|
||||
See :c:func:`Py_PACK_FULL_VERSION` for the encoding details.
|
||||
This contains the Python version used at run time.
|
||||
|
||||
Use this for numeric comparisons, for example, ``if (Py_Version >= ...)``.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
All the given macros are defined in :source:`Include/patchlevel.h`.
|
||||
|
||||
Bit-packing macros
|
||||
------------------
|
||||
|
||||
.. c:function:: uint32_t Py_PACK_FULL_VERSION(int major, int minor, int micro, int release_level, int release_serial)
|
||||
|
||||
Return the given version, encoded as a single 32-bit integer with
|
||||
the following structure:
|
||||
|
||||
+------------------+-------+----------------+-----------+--------------------------+
|
||||
| | No. | | | Example values |
|
||||
| | of | | +-------------+------------+
|
||||
| Argument | bits | Bit mask | Bit shift | ``3.4.1a2`` | ``3.10.0`` |
|
||||
+==================+=======+================+===========+=============+============+
|
||||
| *major* | 8 | ``0xFF000000`` | 24 | ``0x03`` | ``0x03`` |
|
||||
+------------------+-------+----------------+-----------+-------------+------------+
|
||||
| *minor* | 8 | ``0x00FF0000`` | 16 | ``0x04`` | ``0x0A`` |
|
||||
+------------------+-------+----------------+-----------+-------------+------------+
|
||||
| *micro* | 8 | ``0x0000FF00`` | 8 | ``0x01`` | ``0x00`` |
|
||||
+------------------+-------+----------------+-----------+-------------+------------+
|
||||
| *release_level* | 4 | ``0x000000F0`` | 4 | ``0xA`` | ``0xF`` |
|
||||
+------------------+-------+----------------+-----------+-------------+------------+
|
||||
| *release_serial* | 4 | ``0x0000000F`` | 0 | ``0x2`` | ``0x0`` |
|
||||
+------------------+-------+----------------+-----------+-------------+------------+
|
||||
|
||||
For example:
|
||||
|
||||
+-------------+------------------------------------+-----------------+
|
||||
| Version | ``Py_PACK_FULL_VERSION`` arguments | Encoded version |
|
||||
+=============+====================================+=================+
|
||||
| ``3.4.1a2`` | ``(3, 4, 1, 0xA, 2)`` | ``0x030401a2`` |
|
||||
+-------------+------------------------------------+-----------------+
|
||||
| ``3.10.0`` | ``(3, 10, 0, 0xF, 0)`` | ``0x030a00f0`` |
|
||||
+-------------+------------------------------------+-----------------+
|
||||
|
||||
Out-of range bits in the arguments are ignored.
|
||||
That is, the macro can be defined as:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifndef Py_PACK_FULL_VERSION
|
||||
#define Py_PACK_FULL_VERSION(X, Y, Z, LEVEL, SERIAL) ( \
|
||||
(((X) & 0xff) << 24) | \
|
||||
(((Y) & 0xff) << 16) | \
|
||||
(((Z) & 0xff) << 8) | \
|
||||
(((LEVEL) & 0xf) << 4) | \
|
||||
(((SERIAL) & 0xf) << 0))
|
||||
#endif
|
||||
|
||||
``Py_PACK_FULL_VERSION`` is primarily a macro, intended for use in
|
||||
``#if`` directives, but it is also available as an exported function.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. c:function:: uint32_t Py_PACK_VERSION(int major, int minor)
|
||||
|
||||
Equivalent to ``Py_PACK_FULL_VERSION(major, minor, 0, 0, 0)``.
|
||||
The result does not correspond to any Python release, but is useful
|
||||
in numeric comparisons.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
|
2
Doc/data/stable_abi.dat
generated
2
Doc/data/stable_abi.dat
generated
|
@ -883,6 +883,8 @@ func,Py_Main,3.2,,
|
|||
func,Py_MakePendingCalls,3.2,,
|
||||
func,Py_NewInterpreter,3.2,,
|
||||
func,Py_NewRef,3.10,,
|
||||
func,Py_PACK_FULL_VERSION,3.14,,
|
||||
func,Py_PACK_VERSION,3.14,,
|
||||
func,Py_REFCNT,3.14,,
|
||||
func,Py_ReprEnter,3.2,,
|
||||
func,Py_ReprLeave,3.2,,
|
||||
|
|
|
@ -1243,6 +1243,10 @@ New features
|
|||
file.
|
||||
(Contributed by Victor Stinner in :gh:`127350`.)
|
||||
|
||||
* Add macros :c:func:`Py_PACK_VERSION` and :c:func:`Py_PACK_FULL_VERSION` for
|
||||
bit-packing Python version numbers.
|
||||
(Contributed by Petr Viktorin in :gh:`128629`.)
|
||||
|
||||
|
||||
Porting to Python 3.14
|
||||
----------------------
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#ifndef _Py_PATCHLEVEL_H
|
||||
#define _Py_PATCHLEVEL_H
|
||||
/* Python version identification scheme.
|
||||
|
||||
When the major or minor version changes, the VERSION variable in
|
||||
|
@ -26,10 +27,23 @@
|
|||
#define PY_VERSION "3.14.0a3+"
|
||||
/*--end constants--*/
|
||||
|
||||
|
||||
#define _Py_PACK_FULL_VERSION(X, Y, Z, LEVEL, SERIAL) ( \
|
||||
(((X) & 0xff) << 24) | \
|
||||
(((Y) & 0xff) << 16) | \
|
||||
(((Z) & 0xff) << 8) | \
|
||||
(((LEVEL) & 0xf) << 4) | \
|
||||
(((SERIAL) & 0xf) << 0))
|
||||
|
||||
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
|
||||
Use this for numeric comparisons, e.g. #if PY_VERSION_HEX >= ... */
|
||||
#define PY_VERSION_HEX ((PY_MAJOR_VERSION << 24) | \
|
||||
(PY_MINOR_VERSION << 16) | \
|
||||
(PY_MICRO_VERSION << 8) | \
|
||||
(PY_RELEASE_LEVEL << 4) | \
|
||||
(PY_RELEASE_SERIAL << 0))
|
||||
#define PY_VERSION_HEX _Py_PACK_FULL_VERSION( \
|
||||
PY_MAJOR_VERSION, \
|
||||
PY_MINOR_VERSION, \
|
||||
PY_MICRO_VERSION, \
|
||||
PY_RELEASE_LEVEL, \
|
||||
PY_RELEASE_SERIAL)
|
||||
|
||||
// Public Py_PACK_VERSION is declared in pymacro.h; it needs <inttypes.h>.
|
||||
|
||||
#endif //_Py_PATCHLEVEL_H
|
||||
|
|
|
@ -190,4 +190,13 @@
|
|||
// "comparison of unsigned expression in '< 0' is always false".
|
||||
#define _Py_IS_TYPE_SIGNED(type) ((type)(-1) <= 0)
|
||||
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030E0000 // 3.14
|
||||
// Version helpers. These are primarily macros, but have exported equivalents.
|
||||
PyAPI_FUNC(uint32_t) Py_PACK_FULL_VERSION(int x, int y, int z, int level, int serial);
|
||||
PyAPI_FUNC(uint32_t) Py_PACK_VERSION(int x, int y);
|
||||
#define Py_PACK_FULL_VERSION _Py_PACK_FULL_VERSION
|
||||
#define Py_PACK_VERSION(X, Y) Py_PACK_FULL_VERSION(X, Y, 0, 0, 0)
|
||||
#endif // Py_LIMITED_API < 3.14
|
||||
|
||||
|
||||
#endif /* Py_PYMACRO_H */
|
||||
|
|
|
@ -3335,6 +3335,49 @@ class TestPyThreadId(unittest.TestCase):
|
|||
self.assertEqual(len(set(py_thread_ids)), len(py_thread_ids),
|
||||
py_thread_ids)
|
||||
|
||||
class TestVersions(unittest.TestCase):
|
||||
full_cases = (
|
||||
(3, 4, 1, 0xA, 2, 0x030401a2),
|
||||
(3, 10, 0, 0xF, 0, 0x030a00f0),
|
||||
(0x103, 0x10B, 0xFF00, -1, 0xF0, 0x030b00f0), # test masking
|
||||
)
|
||||
xy_cases = (
|
||||
(3, 4, 0x03040000),
|
||||
(3, 10, 0x030a0000),
|
||||
(0x103, 0x10B, 0x030b0000), # test masking
|
||||
)
|
||||
|
||||
def test_pack_full_version(self):
|
||||
for *args, expected in self.full_cases:
|
||||
with self.subTest(hexversion=hex(expected)):
|
||||
result = _testlimitedcapi.pack_full_version(*args)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_pack_version(self):
|
||||
for *args, expected in self.xy_cases:
|
||||
with self.subTest(hexversion=hex(expected)):
|
||||
result = _testlimitedcapi.pack_version(*args)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_pack_full_version_ctypes(self):
|
||||
ctypes = import_helper.import_module('ctypes')
|
||||
ctypes_func = ctypes.pythonapi.Py_PACK_FULL_VERSION
|
||||
ctypes_func.restype = ctypes.c_uint32
|
||||
ctypes_func.argtypes = [ctypes.c_int] * 5
|
||||
for *args, expected in self.full_cases:
|
||||
with self.subTest(hexversion=hex(expected)):
|
||||
result = ctypes_func(*args)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_pack_version_ctypes(self):
|
||||
ctypes = import_helper.import_module('ctypes')
|
||||
ctypes_func = ctypes.pythonapi.Py_PACK_VERSION
|
||||
ctypes_func.restype = ctypes.c_uint32
|
||||
ctypes_func.argtypes = [ctypes.c_int] * 2
|
||||
for *args, expected in self.xy_cases:
|
||||
with self.subTest(hexversion=hex(expected)):
|
||||
result = ctypes_func(*args)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
2
Lib/test/test_stable_abi_ctypes.py
generated
2
Lib/test/test_stable_abi_ctypes.py
generated
|
@ -901,6 +901,8 @@ SYMBOL_NAMES = (
|
|||
"Py_MakePendingCalls",
|
||||
"Py_NewInterpreter",
|
||||
"Py_NewRef",
|
||||
"Py_PACK_FULL_VERSION",
|
||||
"Py_PACK_VERSION",
|
||||
"Py_REFCNT",
|
||||
"Py_ReprEnter",
|
||||
"Py_ReprLeave",
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Add macros :c:func:`Py_PACK_VERSION` and :c:func:`Py_PACK_FULL_VERSION` for
|
||||
bit-packing Python version numbers.
|
|
@ -2540,3 +2540,7 @@
|
|||
added = '3.14'
|
||||
[function.PyType_Freeze]
|
||||
added = '3.14'
|
||||
[function.Py_PACK_FULL_VERSION]
|
||||
added = '3.14'
|
||||
[function.Py_PACK_VERSION]
|
||||
added = '3.14'
|
||||
|
|
|
@ -163,7 +163,7 @@
|
|||
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
|
||||
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
|
||||
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/monitoring.c _testcapi/config.c
|
||||
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c
|
||||
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c
|
||||
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
|
||||
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
|
||||
|
||||
|
|
|
@ -83,5 +83,8 @@ PyInit__testlimitedcapi(void)
|
|||
if (_PyTestLimitedCAPI_Init_VectorcallLimited(mod) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (_PyTestLimitedCAPI_Init_Version(mod) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
|
93
Modules/_testlimitedcapi/clinic/version.c.h
generated
Normal file
93
Modules/_testlimitedcapi/clinic/version.c.h
generated
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*[clinic input]
|
||||
preserve
|
||||
[clinic start generated code]*/
|
||||
|
||||
PyDoc_STRVAR(_testlimitedcapi_pack_full_version__doc__,
|
||||
"pack_full_version($module, major, minor, micro, level, serial, /)\n"
|
||||
"--\n"
|
||||
"\n");
|
||||
|
||||
#define _TESTLIMITEDCAPI_PACK_FULL_VERSION_METHODDEF \
|
||||
{"pack_full_version", (PyCFunction)(void(*)(void))_testlimitedcapi_pack_full_version, METH_FASTCALL, _testlimitedcapi_pack_full_version__doc__},
|
||||
|
||||
static PyObject *
|
||||
_testlimitedcapi_pack_full_version_impl(PyObject *module, int major,
|
||||
int minor, int micro, int level,
|
||||
int serial);
|
||||
|
||||
static PyObject *
|
||||
_testlimitedcapi_pack_full_version(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int major;
|
||||
int minor;
|
||||
int micro;
|
||||
int level;
|
||||
int serial;
|
||||
|
||||
if (nargs != 5) {
|
||||
PyErr_Format(PyExc_TypeError, "pack_full_version expected 5 arguments, got %zd", nargs);
|
||||
goto exit;
|
||||
}
|
||||
major = PyLong_AsInt(args[0]);
|
||||
if (major == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
minor = PyLong_AsInt(args[1]);
|
||||
if (minor == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
micro = PyLong_AsInt(args[2]);
|
||||
if (micro == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
level = PyLong_AsInt(args[3]);
|
||||
if (level == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
serial = PyLong_AsInt(args[4]);
|
||||
if (serial == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = _testlimitedcapi_pack_full_version_impl(module, major, minor, micro, level, serial);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(_testlimitedcapi_pack_version__doc__,
|
||||
"pack_version($module, major, minor, /)\n"
|
||||
"--\n"
|
||||
"\n");
|
||||
|
||||
#define _TESTLIMITEDCAPI_PACK_VERSION_METHODDEF \
|
||||
{"pack_version", (PyCFunction)(void(*)(void))_testlimitedcapi_pack_version, METH_FASTCALL, _testlimitedcapi_pack_version__doc__},
|
||||
|
||||
static PyObject *
|
||||
_testlimitedcapi_pack_version_impl(PyObject *module, int major, int minor);
|
||||
|
||||
static PyObject *
|
||||
_testlimitedcapi_pack_version(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int major;
|
||||
int minor;
|
||||
|
||||
if (nargs != 2) {
|
||||
PyErr_Format(PyExc_TypeError, "pack_version expected 2 arguments, got %zd", nargs);
|
||||
goto exit;
|
||||
}
|
||||
major = PyLong_AsInt(args[0]);
|
||||
if (major == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
minor = PyLong_AsInt(args[1]);
|
||||
if (minor == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = _testlimitedcapi_pack_version_impl(module, major, minor);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=aed3e226da77f2d2 input=a9049054013a1b77]*/
|
|
@ -40,5 +40,6 @@ int _PyTestLimitedCAPI_Init_Sys(PyObject *module);
|
|||
int _PyTestLimitedCAPI_Init_Tuple(PyObject *module);
|
||||
int _PyTestLimitedCAPI_Init_Unicode(PyObject *module);
|
||||
int _PyTestLimitedCAPI_Init_VectorcallLimited(PyObject *module);
|
||||
int _PyTestLimitedCAPI_Init_Version(PyObject *module);
|
||||
|
||||
#endif // Py_TESTLIMITEDCAPI_PARTS_H
|
||||
|
|
77
Modules/_testlimitedcapi/version.c
Normal file
77
Modules/_testlimitedcapi/version.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* Test version macros in the limited API */
|
||||
|
||||
#include "pyconfig.h" // Py_GIL_DISABLED
|
||||
#ifndef Py_GIL_DISABLED
|
||||
# define Py_LIMITED_API 0x030e0000 // Added in 3.14
|
||||
#endif
|
||||
|
||||
#include "parts.h"
|
||||
#include "clinic/version.c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*[clinic input]
|
||||
module _testlimitedcapi
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2700057f9c1135ba]*/
|
||||
|
||||
/*[clinic input]
|
||||
_testlimitedcapi.pack_full_version
|
||||
|
||||
major: int
|
||||
minor: int
|
||||
micro: int
|
||||
level: int
|
||||
serial: int
|
||||
/
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_testlimitedcapi_pack_full_version_impl(PyObject *module, int major,
|
||||
int minor, int micro, int level,
|
||||
int serial)
|
||||
/*[clinic end generated code: output=b87a1e9805648861 input=2a304423be61d2ac]*/
|
||||
{
|
||||
uint32_t macro_result = Py_PACK_FULL_VERSION(
|
||||
major, minor, micro, level, serial);
|
||||
#undef Py_PACK_FULL_VERSION
|
||||
uint32_t func_result = Py_PACK_FULL_VERSION(
|
||||
major, minor, micro, level, serial);
|
||||
|
||||
assert(macro_result == func_result);
|
||||
return PyLong_FromUnsignedLong((unsigned long)func_result);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_testlimitedcapi.pack_version
|
||||
|
||||
major: int
|
||||
minor: int
|
||||
/
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_testlimitedcapi_pack_version_impl(PyObject *module, int major, int minor)
|
||||
/*[clinic end generated code: output=771247bbd06e7883 input=3e39e9dcbc09e86a]*/
|
||||
{
|
||||
uint32_t macro_result = Py_PACK_VERSION(major, minor);
|
||||
#undef Py_PACK_VERSION
|
||||
uint32_t func_result = Py_PACK_VERSION(major, minor);
|
||||
|
||||
assert(macro_result == func_result);
|
||||
return PyLong_FromUnsignedLong((unsigned long)func_result);
|
||||
}
|
||||
|
||||
static PyMethodDef TestMethods[] = {
|
||||
_TESTLIMITEDCAPI_PACK_FULL_VERSION_METHODDEF
|
||||
_TESTLIMITEDCAPI_PACK_VERSION_METHODDEF
|
||||
{NULL},
|
||||
};
|
||||
|
||||
int
|
||||
_PyTestLimitedCAPI_Init_Version(PyObject *m)
|
||||
{
|
||||
if (PyModule_AddFunctions(m, TestMethods) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
2
PC/python3dll.c
generated
2
PC/python3dll.c
generated
|
@ -81,6 +81,8 @@ EXPORT_FUNC(Py_Main)
|
|||
EXPORT_FUNC(Py_MakePendingCalls)
|
||||
EXPORT_FUNC(Py_NewInterpreter)
|
||||
EXPORT_FUNC(Py_NewRef)
|
||||
EXPORT_FUNC(Py_PACK_FULL_VERSION)
|
||||
EXPORT_FUNC(Py_PACK_VERSION)
|
||||
EXPORT_FUNC(Py_REFCNT)
|
||||
EXPORT_FUNC(Py_ReprEnter)
|
||||
EXPORT_FUNC(Py_ReprLeave)
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
<ClCompile Include="..\Modules\_testlimitedcapi\tuple.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\unicode.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\vectorcall_limited.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\version.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\PC\python_nt.rc" />
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
<ClCompile Include="..\Modules\_testlimitedcapi\tuple.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\unicode.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\vectorcall_limited.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\version.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -648,3 +648,20 @@ PyModule_AddType(PyObject *module, PyTypeObject *type)
|
|||
|
||||
return PyModule_AddObjectRef(module, name, (PyObject *)type);
|
||||
}
|
||||
|
||||
|
||||
/* Exported functions for version helper macros */
|
||||
|
||||
#undef Py_PACK_FULL_VERSION
|
||||
uint32_t
|
||||
Py_PACK_FULL_VERSION(int x, int y, int z, int level, int serial)
|
||||
{
|
||||
return _Py_PACK_FULL_VERSION(x, y, z, level, serial);
|
||||
}
|
||||
|
||||
#undef Py_PACK_VERSION
|
||||
uint32_t
|
||||
Py_PACK_VERSION(int x, int y)
|
||||
{
|
||||
return Py_PACK_FULL_VERSION(x, y, 0, 0, 0);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue