Skip to content

Commit e3883dd

Browse files
XuehaiPanhenryiiipre-commit-ci[bot]
authored
refactor: use CPython macros to construct PYBIND11_VERSION_HEX (#5683)
* refactor: use CPython macros to construct `PYBIND11_VERSION_HEX` * docs: update release guide * tests: add test to keep version values in sync Signed-off-by: Henry Schreiner <[email protected]> * style: pre-commit fixes * test: update version test * test: update version test * test: update version test * chore: update code comments * Update docs/release.rst --------- Signed-off-by: Henry Schreiner <[email protected]> Co-authored-by: Henry Schreiner <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent e4622cb commit e3883dd

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

docs/release.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ For example:
1010

1111
#define PYBIND11_VERSION_MAJOR X
1212
#define PYBIND11_VERSION_MINOR Y
13+
#define PYBIND11_VERSION_MICRO Z
14+
#define PYBIND11_VERSION_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA
15+
#define PYBIND11_VERSION_RELEASE_SERIAL 0
1316
#define PYBIND11_VERSION_PATCH Za0
1417

1518
For beta, ``PYBIND11_VERSION_PATCH`` should be ``Zb1``. RC's can be ``Zrc1``.
16-
For a final release, this must be a simple integer. There is also
17-
``PYBIND11_VERSION_HEX`` just below that needs to be updated.
19+
For a final release, this must be a simple integer.
1820

1921

2022
To release a new version of pybind11:
@@ -26,9 +28,7 @@ If you don't have nox, you should either use ``pipx run nox`` instead, or use
2628
- Update the version number
2729

2830
- Update ``PYBIND11_VERSION_MAJOR`` etc. in
29-
``include/pybind11/detail/common.h``. PATCH should be a simple integer.
30-
31-
- Update ``PYBIND11_VERSION_HEX`` just below as well.
31+
``include/pybind11/detail/common.h``. MICRO should be a simple integer.
3232

3333
- Run ``nox -s tests_packaging`` to ensure this was done correctly.
3434

include/pybind11/detail/common.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,35 @@
1414
# error "PYTHON < 3.8 IS UNSUPPORTED. pybind11 v2.13 was the last to support Python 3.7."
1515
#endif
1616

17+
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
18+
// See also: https://github.com/python/cpython/blob/HEAD/Include/patchlevel.h
19+
/* -- start version constants -- */
1720
#define PYBIND11_VERSION_MAJOR 3
1821
#define PYBIND11_VERSION_MINOR 0
22+
#define PYBIND11_VERSION_MICRO 0
23+
// ALPHA = 0xA, BETA = 0xB, GAMMA = 0xC (release candidate), FINAL = 0xF (stable release)
24+
// - The release level is set to "alpha" for development versions.
25+
// Use 0xA0 (LEVEL=0xA, SERIAL=0) for development versions.
26+
// - For stable releases, set the serial to 0.
27+
#define PYBIND11_VERSION_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA
28+
#define PYBIND11_VERSION_RELEASE_SERIAL 1
29+
// String version of (micro, release level, release serial), e.g.: 0a0, 0b1, 0rc1, 0
1930
#define PYBIND11_VERSION_PATCH 0rc1
31+
/* -- end version constants -- */
2032

21-
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
22-
// Use 0xA0 for dev
23-
#define PYBIND11_VERSION_HEX 0x030000C1
33+
#if !defined(Py_PACK_FULL_VERSION)
34+
// Stable API since Python 3.14.0a4
35+
# define Py_PACK_FULL_VERSION(X, Y, Z, LEVEL, SERIAL) \
36+
((((X) & 0xff) << 24) | (((Y) & 0xff) << 16) | (((Z) & 0xff) << 8) \
37+
| (((LEVEL) & 0xf) << 4) | (((SERIAL) & 0xf) << 0))
38+
#endif
39+
// Version as a single 4-byte hex number, e.g. 0x030C04B5 == 3.12.4b5.
40+
#define PYBIND11_VERSION_HEX \
41+
Py_PACK_FULL_VERSION(PYBIND11_VERSION_MAJOR, \
42+
PYBIND11_VERSION_MINOR, \
43+
PYBIND11_VERSION_MICRO, \
44+
PYBIND11_VERSION_RELEASE_LEVEL, \
45+
PYBIND11_VERSION_RELEASE_SERIAL)
2446

2547
#include "pybind11_namespace_macros.h"
2648

tests/extra_python_package/test_files.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,36 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
347347

348348
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version)
349349
assert pkgconfig_expected == pkgconfig
350+
351+
352+
def test_version_matches():
353+
header = MAIN_DIR / "include/pybind11/detail/common.h"
354+
text = header.read_text()
355+
356+
# Extract the relevant macro values
357+
regex_prefix = r"#\s*define\s+PYBIND11_VERSION_"
358+
micro = re.search(rf"{regex_prefix}MICRO\s+(\d+)\b", text).group(1)
359+
release_level = re.search(rf"{regex_prefix}RELEASE_LEVEL\s+(\w+)\b", text).group(1)
360+
release_serial = re.search(
361+
rf"{regex_prefix}RELEASE_SERIAL\s+(\d+)\b",
362+
text,
363+
).group(1)
364+
patch = re.search(rf"{regex_prefix}PATCH\s+([\w.-]+)\b", text).group(1)
365+
366+
# Map release level macro to string
367+
level_map = {
368+
"PY_RELEASE_LEVEL_ALPHA": "a",
369+
"PY_RELEASE_LEVEL_BETA": "b",
370+
"PY_RELEASE_LEVEL_GAMMA": "rc",
371+
"PY_RELEASE_LEVEL_FINAL": "",
372+
}
373+
level_str = level_map[release_level]
374+
375+
if release_level == "PY_RELEASE_LEVEL_FINAL":
376+
assert level_str == ""
377+
assert release_serial == "0"
378+
expected_patch = micro
379+
else:
380+
expected_patch = f"{micro}{level_str}{release_serial}"
381+
382+
assert patch == expected_patch

0 commit comments

Comments
 (0)