mirror of https://github.com/python/cpython
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
"""Extract version information from Include/patchlevel.h."""
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Literal, NamedTuple
|
|
|
|
CPYTHON_ROOT = Path(
|
|
__file__, # cpython/Doc/tools/extensions/patchlevel.py
|
|
"..", # cpython/Doc/tools/extensions
|
|
"..", # cpython/Doc/tools
|
|
"..", # cpython/Doc
|
|
"..", # cpython
|
|
).resolve()
|
|
PATCHLEVEL_H = CPYTHON_ROOT / "Include" / "patchlevel.h"
|
|
|
|
RELEASE_LEVELS = {
|
|
"PY_RELEASE_LEVEL_ALPHA": "alpha",
|
|
"PY_RELEASE_LEVEL_BETA": "beta",
|
|
"PY_RELEASE_LEVEL_GAMMA": "candidate",
|
|
"PY_RELEASE_LEVEL_FINAL": "final",
|
|
}
|
|
|
|
|
|
class version_info(NamedTuple): # noqa: N801
|
|
major: int #: Major release number
|
|
minor: int #: Minor release number
|
|
micro: int #: Patch release number
|
|
releaselevel: Literal["alpha", "beta", "candidate", "final"]
|
|
serial: int #: Serial release number
|
|
|
|
|
|
def get_header_version_info() -> version_info:
|
|
# Capture PY_ prefixed #defines.
|
|
pat = re.compile(r"\s*#define\s+(PY_\w*)\s+(\w+)", re.ASCII)
|
|
|
|
defines = {}
|
|
patchlevel_h = PATCHLEVEL_H.read_text(encoding="utf-8")
|
|
for line in patchlevel_h.splitlines():
|
|
if (m := pat.match(line)) is not None:
|
|
name, value = m.groups()
|
|
defines[name] = value
|
|
|
|
return version_info(
|
|
major=int(defines["PY_MAJOR_VERSION"]),
|
|
minor=int(defines["PY_MINOR_VERSION"]),
|
|
micro=int(defines["PY_MICRO_VERSION"]),
|
|
releaselevel=RELEASE_LEVELS[defines["PY_RELEASE_LEVEL"]],
|
|
serial=int(defines["PY_RELEASE_SERIAL"]),
|
|
)
|
|
|
|
|
|
def format_version_info(info: version_info) -> tuple[str, str]:
|
|
version = f"{info.major}.{info.minor}"
|
|
release = f"{info.major}.{info.minor}.{info.micro}"
|
|
if info.releaselevel != "final":
|
|
suffix = {"alpha": "a", "beta": "b", "candidate": "rc"}
|
|
release += f"{suffix[info.releaselevel]}{info.serial}"
|
|
return version, release
|
|
|
|
|
|
def get_version_info():
|
|
try:
|
|
info = get_header_version_info()
|
|
return format_version_info(info)
|
|
except OSError:
|
|
version, release = format_version_info(sys.version_info)
|
|
print(
|
|
f"Failed to get version info from Include/patchlevel.h, "
|
|
f"using version of this interpreter ({release}).",
|
|
file=sys.stderr,
|
|
)
|
|
return version, release
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(format_version_info(get_header_version_info())[0])
|