Skip to content

Commit 0ec2b74

Browse files
committed
Convert input version<->hex and print with --hex
1 parent e7ad59b commit 0ec2b74

File tree

1 file changed

+83
-3
lines changed

1 file changed

+83
-3
lines changed

Doc/tools/extensions/patchlevel.py

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,89 @@ def get_version_info():
7373
return version, release
7474

7575

76-
if __name__ == "__main__":
77-
short_ver, full_ver = format_version_info(get_header_version_info())
78-
if sys.argv[1:2] == ["--short"]:
76+
def get_version_hex(info: version_info) -> int:
77+
"""Convert a version_info object to a hex version number."""
78+
levels = {"alpha": 0xA, "beta": 0xB, "candidate": 0xC, "final": 0xF}
79+
return (
80+
(info.major << 24)
81+
| (info.minor << 16)
82+
| (info.micro << 8)
83+
| (levels[info.releaselevel] << 4)
84+
| (info.serial << 0)
85+
)
86+
87+
88+
def parse_str_version(version: str) -> version_info:
89+
"""Convert a version string to a version_info object."""
90+
tag_cre = re.compile(r"(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:([ab]|rc)(\d+))?$")
91+
result = tag_cre.match(version)
92+
if not result:
93+
raise ValueError(f"Invalid version string: {version}")
94+
95+
parts = list(result.groups())
96+
levels = {"a": "alpha", "b": "beta", "rc": "candidate"}
97+
return version_info(
98+
major=int(parts[0]),
99+
minor=int(parts[1]),
100+
micro=int(parts[2] or 0),
101+
releaselevel=levels.get(parts[3], "final"),
102+
serial=int(parts[4]) if parts[4] else 0,
103+
)
104+
105+
106+
def parse_hex_version(version: int) -> version_info:
107+
"""Convert a hex version number to a version_info object."""
108+
if not isinstance(version, int):
109+
raise ValueError(f"Invalid hex version: {version}")
110+
111+
levels = {0xA: "alpha", 0xB: "beta", 0xC: "candidate", 0xF: "final"}
112+
return version_info(
113+
major=(version >> 24) & 0xFF,
114+
minor=(version >> 16) & 0xFF,
115+
micro=(version >> 8) & 0xFF,
116+
releaselevel=levels.get((version >> 4) & 0xF, "final"),
117+
serial=version & 0xF,
118+
)
119+
120+
121+
def main() -> None:
122+
import argparse
123+
124+
parser = argparse.ArgumentParser(color=True)
125+
parser.add_argument(
126+
"version",
127+
nargs="?",
128+
help="version to convert (default: repo version)",
129+
)
130+
group = parser.add_mutually_exclusive_group()
131+
group.add_argument(
132+
"--short",
133+
action="store_true",
134+
help="print version as x.y",
135+
)
136+
group.add_argument(
137+
"--hex",
138+
action="store_true",
139+
help="print version as a 4-byte hex number",
140+
)
141+
args = parser.parse_args()
142+
143+
if args.version:
144+
try:
145+
info = parse_str_version(args.version)
146+
except ValueError:
147+
info = parse_hex_version(int(args.version, 16))
148+
else:
149+
info = get_header_version_info()
150+
151+
short_ver, full_ver = format_version_info(info)
152+
if args.short:
79153
print(short_ver)
154+
elif args.hex:
155+
print(hex(get_version_hex(info)))
80156
else:
81157
print(full_ver)
158+
159+
160+
if __name__ == "__main__":
161+
main()

0 commit comments

Comments
 (0)