From 9507901be9ddf519ba8b2595519116939c653e4a Mon Sep 17 00:00:00 2001 From: the Mulhern Date: Fri, 13 Nov 2026 11:54:29 -0500 Subject: [PATCH 1/2] Add type annotations to _utils.py Signed-off-by: the Mulhern --- release_management/_utils.py | 58 +++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/release_management/_utils.py b/release_management/_utils.py index 5991e90..e511cd4 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -24,12 +24,13 @@ from datetime import datetime from functools import partial from getpass import getpass -from typing import Any, List, Optional -from urllib.parse import urlparse +from typing import Any +from urllib.parse import ParseResult, urlparse import requests from build.util import project_wheel_metadata from github import Github +from github.GitRelease import GitRelease from giturlparse import GitUrlParsed, parse from semantic_version import Version from specfile import specfile @@ -56,7 +57,7 @@ class ReleaseVersion: Release version for the package. """ - def __init__(self, base: Version, *, pre: bool = False, post: bool = False): + def __init__(self, base: Version, *, pre: bool = False, post: bool = False) -> None: """ Initializer. :param Version base: Base version @@ -67,10 +68,10 @@ def __init__(self, base: Version, *, pre: bool = False, post: bool = False): self.pre = pre self.post = post - def __str__(self): + def __str__(self) -> str: return f"{self.base}{'~pre' if self.pre else ''}{'^post' if self.post else ''}" - def release(self) -> Optional[str]: + def release(self) -> str | None: """ Optional release string for spec file. """ @@ -78,12 +79,12 @@ def release(self) -> Optional[str]: def edit_specfile( - specfile_path, + specfile_path: str | None, *, - release_version: Optional[ReleaseVersion] = None, - sources: Optional[List[str]] = None, - arbitrary: Optional[Callable[[specfile.Specfile], None]] = None, -): + release_version: ReleaseVersion | None = None, + sources: list[str] | None = None, + arbitrary: Callable[[specfile.Specfile], None] | None = None, +) -> None: """ Edit the specfile in place :param specfile_path: abspath of specfile @@ -132,7 +133,9 @@ def get_python_package_info(name: str) -> tuple[Version, GitUrlParsed]: return (release_version, github_repo) -def get_package_info(manifest_abs_path, package_name) -> tuple[Version, Any]: +def get_package_info( + manifest_abs_path: str, package_name: str +) -> tuple[Version, ParseResult]: """ Extract the version string and repo URL from Cargo.toml and return it. @@ -159,7 +162,7 @@ def get_package_info(manifest_abs_path, package_name) -> tuple[Version, Any]: return (Version(version), github_repo) -def verify_tag(tag): +def verify_tag(tag: str) -> bool: """ Verify that the designated tag exists and point at current HEAD. @@ -175,7 +178,7 @@ def verify_tag(tag): return tag_str.decode("utf-8").rstrip() == tag -def set_tag(tag, message): +def set_tag(tag: str, message: str) -> None: """ Set specified tag on HEAD if it does not already exist. @@ -189,7 +192,7 @@ def set_tag(tag, message): ) -def get_branch(): +def get_branch() -> str: """ Get the current git branch as a string. @@ -204,8 +207,13 @@ def get_branch(): def create_release( - repository, tag, release_version, changelog_url, *, additional_assets=None -): + repository: ParseResult | GitUrlParsed, + tag: str, + release_version: Version | str, + changelog_url: str, + *, + additional_assets: list[str] | None = None, +) -> GitRelease: """ Create draft release from a pre-established GitHub tag for this repository. @@ -223,7 +231,13 @@ def create_release( git = Github(api_key) - repo = git.get_repo(repository.path.strip("/")) + # GitUrlParsed uses pathname, ParseResult uses path + # giturlparse lacks type stubs, so we use getattr to access its attributes + if isinstance(repository, GitUrlParsed): + repo_path = getattr(repository, "pathname", "") + else: + repo_path = repository.path + repo = git.get_repo(repo_path.strip("/")) release = repo.create_git_release( tag, f"Version {release_version}", f"See {changelog_url}", draft=True @@ -235,7 +249,9 @@ def create_release( return release -def vendor(manifest_abs_path, release_version, *, filterer=False): +def vendor( + manifest_abs_path: str, release_version: ReleaseVersion, *, filterer: bool = False +) -> str: """ Makes a vendor tarfile, suitable for uploading. @@ -291,7 +307,9 @@ def vendor(manifest_abs_path, release_version, *, filterer=False): return vendor_tarfile_name -def make_source_tarball(package_name, release_version, output_dir): +def make_source_tarball( + package_name: str, release_version: ReleaseVersion | str, output_dir: str +) -> str: """ Make the source tarball and place it in the output dir. @@ -323,7 +341,7 @@ def make_source_tarball(package_name, release_version, output_dir): return output_file -def get_changelog_url(repository_url, branch): +def get_changelog_url(repository_url: str, branch: str) -> str: """ Get the URL for the changelog in the release message. From 0cc0e29c5d1bc49ae9ced9c3f2bfda0254b3825c Mon Sep 17 00:00:00 2001 From: the Mulhern Date: Fri, 13 Nov 2026 13:54:48 -0500 Subject: [PATCH 2/2] Get Python changelog URL from pyproject.toml Signed-off-by: the Mulhern Assisted-by: Claude:claude-sonnet-4-5 --- release_management/_utils.py | 26 +++++++++----------------- release_management/create_release.py | 4 ++-- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/release_management/_utils.py b/release_management/_utils.py index e511cd4..551ddd5 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -31,7 +31,6 @@ from build.util import project_wheel_metadata from github import Github from github.GitRelease import GitRelease -from giturlparse import GitUrlParsed, parse from semantic_version import Version from specfile import specfile @@ -110,7 +109,7 @@ def edit_specfile( arbitrary(spec) -def get_python_package_info(name: str) -> tuple[Version, GitUrlParsed]: +def get_python_package_info(name: str) -> tuple[Version, ParseResult]: """ Get info about the python package. @@ -122,14 +121,13 @@ def get_python_package_info(name: str) -> tuple[Version, GitUrlParsed]: release_version = Version(config.get("version")) - command = ["git", "remote", "get-url", "origin", "--push"] - with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: - stdout = proc.stdout - assert stdout is not None, "stdout set in subprocess call" - github_url = stdout.readline().strip().decode("utf-8") + github_url = dict(u.split(", ", 1) for u in config.get_all("Project-URL", [])).get( + "Homepage" + ) + assert github_url is not None, "Homepage URL not found in project metadata" - github_repo = parse(github_url) - assert github_repo.host == "github.com", "specified repo is not on GitHub" + github_repo = urlparse(github_url) + assert github_repo.netloc == "github.com", "specified repo is not on GitHub" return (release_version, github_repo) @@ -207,7 +205,7 @@ def get_branch() -> str: def create_release( - repository: ParseResult | GitUrlParsed, + repository: ParseResult, tag: str, release_version: Version | str, changelog_url: str, @@ -231,13 +229,7 @@ def create_release( git = Github(api_key) - # GitUrlParsed uses pathname, ParseResult uses path - # giturlparse lacks type stubs, so we use getattr to access its attributes - if isinstance(repository, GitUrlParsed): - repo_path = getattr(repository, "pathname", "") - else: - repo_path = repository.path - repo = git.get_repo(repo_path.strip("/")) + repo = git.get_repo(repository.path.strip("/")) release = repo.create_git_release( tag, f"Version {release_version}", f"See {changelog_url}", draft=True diff --git a/release_management/create_release.py b/release_management/create_release.py index 997a498..f80f77a 100755 --- a/release_management/create_release.py +++ b/release_management/create_release.py @@ -304,7 +304,7 @@ def tag_python_library(namespace, name): return push_git_url = ( - repository.url if namespace.git_repo is None else namespace.git_repo + repository.geturl() if namespace.git_repo is None else namespace.git_repo ) dry_run_caller("__main__._push_tag", lambda: _push_tag(push_git_url, tag)) @@ -315,7 +315,7 @@ def tag_python_library(namespace, name): repository, tag, release_version, - get_changelog_url(repository.url, get_branch()), + get_changelog_url(repository.geturl(), get_branch()), ), skip=namespace.no_github_release, )