| # This file is dual licensed under the terms of the Apache License, Version | |
| # 2.0, and the BSD License. See the LICENSE file in the root of this repository | |
| # for complete details. | |
| # /// script | |
| # dependencies = [ | |
| # "click", | |
| # "packaging", | |
| # ] | |
| # /// | |
| import pathlib | |
| import re | |
| import subprocess | |
| import sys | |
| import click | |
| from packaging.version import Version | |
| if sys.version_info >= (3, 11): | |
| import tomllib | |
| else: | |
| import tomli as tomllib | |
| def run(*args: str) -> None: | |
| print(f"[running] {list(args)}") | |
| subprocess.check_call(list(args)) | |
| @click.group() | |
| def cli(): | |
| pass | |
| @cli.command() | |
| def release() -> None: | |
| base_dir = pathlib.Path(__file__).parent | |
| with (base_dir / "pyproject.toml").open("rb") as f: | |
| pyproject = tomllib.load(f) | |
| version = pyproject["project"]["version"] | |
| if Version(version).is_prerelease: | |
| raise RuntimeError( | |
| f"Can't release, pyproject.toml version is pre-release: {version}" | |
| ) | |
| # Tag and push the tag (this will trigger the wheel builder in Actions) | |
| run("git", "tag", "-s", version, "-m", f"{version} release") | |
| run("git", "push", "--tags", "git@github.com:pyca/cryptography.git") | |
| def replace_pattern(p: pathlib.Path, pattern: str, replacement: str) -> None: | |
| content = p.read_text() | |
| match = re.search(pattern, content, re.MULTILINE) | |
| assert match is not None | |
| start, end = match.span() | |
| new_content = content[:start] + replacement + content[end:] | |
| p.write_text(new_content) | |
| def replace_version( | |
| p: pathlib.Path, variable_name: str, new_version: str | |
| ) -> None: | |
| replace_pattern( | |
| p, rf"^{variable_name}\s*=\s*.*$", f'{variable_name} = "{new_version}"' | |
| ) | |
| def rust_version(version: Version) -> str: | |
| # The Rust crates use a version that maps to the cryptography version, | |
| # but pre-1.0: cryptography X.0.Z is version 0.X.Z of the crates, and | |
| # pre-releases map to semver pre-releases (49.0.0.dev1 is 0.49.0-dev1). | |
| if version.minor != 0: | |
| raise ValueError( | |
| f"Can't map {version} to a crate version, minor must be 0" | |
| ) | |
| crate_version = f"0.{version.major}.{version.micro}" | |
| pre_parts = [] | |
| if version.pre is not None: | |
| pre_parts.append(f"{version.pre[0]}{version.pre[1]}") | |
| if version.dev is not None: | |
| pre_parts.append(f"dev{version.dev}") | |
| if pre_parts: | |
| crate_version += "-" + ".".join(pre_parts) | |
| return crate_version | |
| def bump_rust_versions(base_dir: pathlib.Path, new_version: str) -> None: | |
| # All crates in the workspace inherit the workspace version, so we only | |
| # need to update it in one place, then sync Cargo.lock. | |
| replace_version( | |
| base_dir / "Cargo.toml", "version", rust_version(Version(new_version)) | |
| ) | |
| run("cargo", "update", "--workspace") | |
| @cli.command() | |
| @click.argument("new_version") | |
| def bump_version(new_version: str) -> None: | |
| base_dir = pathlib.Path(__file__).parent | |
| replace_version(base_dir / "pyproject.toml", "version", new_version) | |
| replace_version( | |
| base_dir / "src/cryptography/__about__.py", "__version__", new_version | |
| ) | |
| replace_version( | |
| base_dir / "vectors/pyproject.toml", | |
| "version", | |
| new_version, | |
| ) | |
| replace_version( | |
| base_dir / "vectors/cryptography_vectors/__about__.py", | |
| "__version__", | |
| new_version, | |
| ) | |
| if Version(new_version).is_prerelease: | |
| replace_pattern( | |
| base_dir / "pyproject.toml", | |
| r'"cryptography_vectors(==.*?)?"', | |
| '"cryptography_vectors"', | |
| ) | |
| else: | |
| replace_pattern( | |
| base_dir / "pyproject.toml", | |
| r'"cryptography_vectors(==.*?)?"', | |
| f'"cryptography_vectors=={new_version}"', | |
| ) | |
| bump_rust_versions(base_dir, new_version) | |
| if __name__ == "__main__": | |
| cli() |