mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
GH-121970: Modernise the patchlevel extension (#121995)
This commit is contained in:
parent
3de092b82f
commit
b7ad711fcb
3 changed files with 66 additions and 58 deletions
|
@ -6,7 +6,6 @@ extend-exclude = [
|
||||||
"includes/*",
|
"includes/*",
|
||||||
# Temporary exclusions:
|
# Temporary exclusions:
|
||||||
"tools/extensions/escape4chm.py",
|
"tools/extensions/escape4chm.py",
|
||||||
"tools/extensions/patchlevel.py",
|
|
||||||
"tools/extensions/pyspecific.py",
|
"tools/extensions/pyspecific.py",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
# The contents of this file are pickled, so don't put values in the namespace
|
# The contents of this file are pickled, so don't put values in the namespace
|
||||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||||
|
|
||||||
|
import importlib
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
@ -64,9 +65,8 @@ copyright = f"2001-{time.strftime('%Y')}, Python Software Foundation"
|
||||||
|
|
||||||
# We look for the Include/patchlevel.h file in the current Python source tree
|
# We look for the Include/patchlevel.h file in the current Python source tree
|
||||||
# and replace the values accordingly.
|
# and replace the values accordingly.
|
||||||
import patchlevel # noqa: E402
|
# See Doc/tools/extensions/patchlevel.py
|
||||||
|
version, release = importlib.import_module('patchlevel').get_version_info()
|
||||||
version, release = patchlevel.get_version_info()
|
|
||||||
|
|
||||||
rst_epilog = f"""
|
rst_epilog = f"""
|
||||||
.. |python_version_literal| replace:: ``Python {version}``
|
.. |python_version_literal| replace:: ``Python {version}``
|
||||||
|
|
|
@ -1,68 +1,77 @@
|
||||||
# -*- coding: utf-8 -*-
|
"""Extract version information from Include/patchlevel.h."""
|
||||||
"""
|
|
||||||
patchlevel.py
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Extract version info from Include/patchlevel.h.
|
|
||||||
Adapted from Doc/tools/getversioninfo.
|
|
||||||
|
|
||||||
:copyright: 2007-2008 by Georg Brandl.
|
|
||||||
:license: Python license.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Literal, NamedTuple
|
||||||
|
|
||||||
def get_header_version_info(srcdir):
|
CPYTHON_ROOT = Path(
|
||||||
patchlevel_h = os.path.join(srcdir, '..', 'Include', 'patchlevel.h')
|
__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"
|
||||||
|
|
||||||
# This won't pick out all #defines, but it will pick up the ones we
|
RELEASE_LEVELS = {
|
||||||
# care about.
|
"PY_RELEASE_LEVEL_ALPHA": "alpha",
|
||||||
rx = re.compile(r'\s*#define\s+([a-zA-Z][a-zA-Z_0-9]*)\s+([a-zA-Z_0-9]+)')
|
"PY_RELEASE_LEVEL_BETA": "beta",
|
||||||
|
"PY_RELEASE_LEVEL_GAMMA": "candidate",
|
||||||
d = {}
|
"PY_RELEASE_LEVEL_FINAL": "final",
|
||||||
with open(patchlevel_h) as f:
|
|
||||||
for line in f:
|
|
||||||
m = rx.match(line)
|
|
||||||
if m is not None:
|
|
||||||
name, value = m.group(1, 2)
|
|
||||||
d[name] = value
|
|
||||||
|
|
||||||
release = version = '%s.%s' % (d['PY_MAJOR_VERSION'], d['PY_MINOR_VERSION'])
|
|
||||||
micro = int(d['PY_MICRO_VERSION'])
|
|
||||||
release += '.' + str(micro)
|
|
||||||
|
|
||||||
level = d['PY_RELEASE_LEVEL']
|
|
||||||
suffixes = {
|
|
||||||
'PY_RELEASE_LEVEL_ALPHA': 'a',
|
|
||||||
'PY_RELEASE_LEVEL_BETA': 'b',
|
|
||||||
'PY_RELEASE_LEVEL_GAMMA': 'rc',
|
|
||||||
}
|
}
|
||||||
if level != 'PY_RELEASE_LEVEL_FINAL':
|
|
||||||
release += suffixes[level] + str(int(d['PY_RELEASE_SERIAL']))
|
|
||||||
return version, release
|
|
||||||
|
|
||||||
|
|
||||||
def get_sys_version_info():
|
class version_info(NamedTuple): # noqa: N801
|
||||||
major, minor, micro, level, serial = sys.version_info
|
major: int #: Major release number
|
||||||
release = version = '%s.%s' % (major, minor)
|
minor: int #: Minor release number
|
||||||
release += '.%s' % micro
|
micro: int #: Patch release number
|
||||||
if level != 'final':
|
releaselevel: Literal["alpha", "beta", "candidate", "final"]
|
||||||
release += '%s%s' % (level[0], serial)
|
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
|
return version, release
|
||||||
|
|
||||||
|
|
||||||
def get_version_info():
|
def get_version_info():
|
||||||
try:
|
try:
|
||||||
return get_header_version_info('.')
|
info = get_header_version_info()
|
||||||
except (IOError, OSError):
|
return format_version_info(info)
|
||||||
version, release = get_sys_version_info()
|
except OSError:
|
||||||
print('Can\'t get version info from Include/patchlevel.h, ' \
|
version, release = format_version_info(sys.version_info)
|
||||||
'using version of this interpreter (%s).' % release, file=sys.stderr)
|
print(
|
||||||
|
f"Failed to get version info from Include/patchlevel.h, "
|
||||||
|
f"using version of this interpreter ({release}).",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
return version, release
|
return version, release
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print(get_header_version_info('.')[1])
|
if __name__ == "__main__":
|
||||||
|
print(format_version_info(get_header_version_info())[1])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue