|
| 1 | +#!/usr/bin/env python |
| 2 | +"""A simple script to update the version embedded in the source.""" |
| 3 | + |
| 4 | +import argparse |
| 5 | +import pathlib |
| 6 | +import re |
| 7 | + |
| 8 | +from packaging.version import Version |
| 9 | + |
| 10 | + |
| 11 | +def main() -> None: |
| 12 | + parser = argparse.ArgumentParser(description=__doc__) |
| 13 | + parser.add_argument('version', type=Version, help='version number to embed in source files') |
| 14 | + args = parser.parse_args() |
| 15 | + version: Version = args.version |
| 16 | + |
| 17 | + major_minor_version = f'{version.major}.{version.minor}' |
| 18 | + version_info = ', '.join(map(repr, get_version_info(version))) |
| 19 | + |
| 20 | + updates: list[tuple[str, re.Pattern, str | Version]] = [ |
| 21 | + ('doc/source/conf.py', re.compile(r"^(version = ')[^']*(')$", flags=re.MULTILINE), major_minor_version), |
| 22 | + ('doc/source/conf.py', re.compile(r"^(release = ')[^']*(')$", flags=re.MULTILINE), version), |
| 23 | + ('setup.py', re.compile(r"^( +version=')[^']*(',)$", flags=re.MULTILINE), version), |
| 24 | + ('src/c/_cffi_backend.c', re.compile(r'^(#define CFFI_VERSION +")[^"]*(")$', flags=re.MULTILINE), version), |
| 25 | + ('src/c/test_c.py', re.compile(r'^(assert __version__ == ")[^"]*(", .*)$', flags=re.MULTILINE), version), |
| 26 | + ('src/cffi/__init__.py', re.compile(r'^(__version__ = ")[^"]*(")$', flags=re.MULTILINE), version), |
| 27 | + ('src/cffi/__init__.py', re.compile(r'^(__version_info__ = \()[^)]*(\))$', flags=re.MULTILINE), version_info), |
| 28 | + ('src/cffi/_embedding.h', re.compile(r'^( +"\\ncompiled with cffi version: )[^"]*(")$', flags=re.MULTILINE), version), |
| 29 | + ] |
| 30 | + |
| 31 | + repo_root = pathlib.Path(__file__).parent.parent |
| 32 | + |
| 33 | + for relative_path, pattern, replacement in updates: |
| 34 | + path = repo_root / relative_path |
| 35 | + original_content = path.read_text() |
| 36 | + |
| 37 | + if not pattern.search(original_content): |
| 38 | + raise RuntimeError(f'{relative_path}: no match found for pattern: {pattern.pattern}') |
| 39 | + |
| 40 | + updated_content = pattern.sub(rf'\g<1>{replacement}\g<2>', original_content) |
| 41 | + |
| 42 | + if updated_content == original_content: |
| 43 | + print(f'{relative_path}: unchanged') |
| 44 | + else: |
| 45 | + path.write_text(updated_content) |
| 46 | + print(f'{relative_path}: updated') |
| 47 | + |
| 48 | + |
| 49 | +def get_version_info(version: Version) -> tuple: |
| 50 | + """Return a tuple representing the given version.""" |
| 51 | + version_info = list(version.release) |
| 52 | + |
| 53 | + if version.pre is not None: |
| 54 | + version_info.append(''.join(map(str, version.pre))) |
| 55 | + |
| 56 | + if version.post is not None: |
| 57 | + version_info.append(f'post{version.post}') |
| 58 | + |
| 59 | + if version.dev is not None: |
| 60 | + version_info.append(f'dev{version.dev}') |
| 61 | + |
| 62 | + if version.local is not None: |
| 63 | + version_info.append(f'+{version.local}') |
| 64 | + |
| 65 | + return tuple(version_info) |
| 66 | + |
| 67 | + |
| 68 | +if __name__ == '__main__': |
| 69 | + main() |
0 commit comments