summaryrefslogtreecommitdiff
path: root/packaging/release.py
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/release.py')
-rwxr-xr-xpackaging/release.py74
1 files changed, 54 insertions, 20 deletions
diff --git a/packaging/release.py b/packaging/release.py
index 05c29faa..97c58a74 100755
--- a/packaging/release.py
+++ b/packaging/release.py
@@ -42,7 +42,7 @@ from packaging.version import Version, InvalidVersion
# region CLI Framework
-C = t.TypeVar("C", bound=t.Callable[[...], None])
+C = t.TypeVar("C", bound=t.Callable[..., None])
def path_to_str(value: t.Any) -> str:
@@ -50,12 +50,27 @@ def path_to_str(value: t.Any) -> str:
return f"{value}/" if isinstance(value, pathlib.Path) and value.is_dir() else str(value)
+@t.overload
+def run(*args: t.Any, env: dict[str, t.Any] | None, cwd: pathlib.Path | str, capture_output: t.Literal[True]) -> CompletedProcess:
+ ...
+
+
+@t.overload
+def run(*args: t.Any, env: dict[str, t.Any] | None, cwd: pathlib.Path | str, capture_output: t.Literal[False]) -> None:
+ ...
+
+
+@t.overload
+def run(*args: t.Any, env: dict[str, t.Any] | None, cwd: pathlib.Path | str) -> None:
+ ...
+
+
def run(
*args: t.Any,
env: dict[str, t.Any] | None,
cwd: pathlib.Path | str,
capture_output: bool = False,
-) -> CompletedProcess:
+) -> CompletedProcess | None:
"""Run the specified command."""
args = [arg.relative_to(cwd) if isinstance(arg, pathlib.Path) else arg for arg in args]
@@ -76,16 +91,18 @@ def run(
stderr=ex.stderr,
) from None
+ if not capture_output:
+ return None
+
# improve type hinting
return CompletedProcess(
- args=str_args,
stdout=p.stdout,
stderr=p.stderr,
)
@contextlib.contextmanager
-def suppress_when(error_as_warning: bool) -> None:
+def suppress_when(error_as_warning: bool) -> t.Generator[None, None, None]:
"""Conditionally convert an ApplicationError in the provided context to a warning."""
if error_as_warning:
try:
@@ -122,9 +139,8 @@ class CalledProcessError(Exception):
class CompletedProcess:
"""Results from a completed process."""
- args: tuple[str, ...]
- stdout: str | None
- stderr: str | None
+ stdout: str
+ stderr: str
class Display:
@@ -167,7 +183,7 @@ class CommandFramework:
"""
def __init__(self, **kwargs: dict[str, t.Any] | None) -> None:
- self.commands: list[C] = []
+ self.commands: list[t.Callable[..., None]] = []
self.arguments = kwargs
self.parsed_arguments: argparse.Namespace | None = None
@@ -176,7 +192,7 @@ class CommandFramework:
self.commands.append(func)
return func
- def run(self, *args: C, **kwargs) -> None:
+ def run(self, *args: t.Callable[..., None], **kwargs) -> None:
"""Run the specified command(s), using any provided internal args."""
for arg in args:
self._run(arg, **kwargs)
@@ -203,6 +219,9 @@ class CommandFramework:
arguments = arguments.copy()
exclusive = arguments.pop("exclusive", None)
+ # noinspection PyProtectedMember, PyUnresolvedReferences
+ command_parser: argparse._ActionsContainer
+
if exclusive:
if exclusive not in exclusive_groups:
exclusive_groups[exclusive] = func_parser.add_mutually_exclusive_group()
@@ -234,7 +253,7 @@ class CommandFramework:
display.fatal(ex)
sys.exit(1)
- def _run(self, func: C, **kwargs) -> None:
+ def _run(self, func: t.Callable[..., None], **kwargs) -> None:
"""Run the specified command, using any provided internal args."""
signature = inspect.signature(func)
func_args = {name: getattr(self.parsed_arguments, name) for name in signature.parameters if hasattr(self.parsed_arguments, name)}
@@ -253,7 +272,7 @@ class CommandFramework:
display.show(f"<== {label}", color=Display.BLUE)
@staticmethod
- def _format_command_name(func: C) -> str:
+ def _format_command_name(func: t.Callable[..., None]) -> str:
"""Return the friendly name of the given command."""
return func.__name__.replace("_", "-")
@@ -441,7 +460,22 @@ class VersionMode(enum.Enum):
raise NotImplementedError(self)
-def git(*args: t.Any, capture_output: bool = False) -> CompletedProcess:
+@t.overload
+def git(*args: t.Any, capture_output: t.Literal[True]) -> CompletedProcess:
+ ...
+
+
+@t.overload
+def git(*args: t.Any, capture_output: t.Literal[False]) -> None:
+ ...
+
+
+@t.overload
+def git(*args: t.Any) -> None:
+ ...
+
+
+def git(*args: t.Any, capture_output: t.Literal[True] | t.Literal[False] = False) -> CompletedProcess | None:
"""Run the specified git command."""
return run("git", *args, env=None, cwd=CHECKOUT_DIR, capture_output=capture_output)
@@ -534,10 +568,6 @@ def create_pull_request_body(title: str) -> str:
##### ISSUE TYPE
Feature Pull Request
-
-##### COMPONENT NAME
-
-ansible
"""
return body.lstrip()
@@ -629,7 +659,7 @@ def get_git_state(version: Version, allow_stale: bool) -> GitState:
@functools.cache
-def ensure_venv() -> dict[str, str]:
+def ensure_venv() -> dict[str, t.Any]:
"""Ensure the release venv is ready and return the env vars needed to use it."""
# TODO: consider freezing the ansible and release requirements along with their dependencies
@@ -943,7 +973,7 @@ def create_github_release_notes(upstream: Remote, repository: str, version: Vers
variables = dict(
version=version,
releases=get_release_artifact_details(repository, version, validate),
- changelog=f"https://github.com/{upstream.user}/{upstream.repo}/blob/v{ version }/changelogs/CHANGELOG-v{ version.major }.{ version.minor }.rst",
+ changelog=f"https://github.com/{upstream.user}/{upstream.repo}/blob/v{version}/changelogs/CHANGELOG-v{version.major}.{version.minor}.rst",
)
release_notes = template.render(**variables).strip()
@@ -1274,7 +1304,7 @@ def build(allow_dirty: bool = False) -> None:
commit_time = int(git("show", "-s", "--format=%ct", capture_output=True).stdout)
env.update(
- SOURCE_DATE_EPOCH=str(commit_time),
+ SOURCE_DATE_EPOCH=commit_time,
)
git("worktree", "add", "-d", temp_dir)
@@ -1312,7 +1342,11 @@ def test_sdist() -> None:
except FileNotFoundError:
raise ApplicationError(f"Missing sdist: {sdist_file.relative_to(CHECKOUT_DIR)}") from None
- sdist.extractall(temp_dir)
+ # deprecated: description='extractall fallback without filter' python_version='3.11'
+ if hasattr(tarfile, 'data_filter'):
+ sdist.extractall(temp_dir, filter='data') # type: ignore[call-arg]
+ else:
+ sdist.extractall(temp_dir)
pyc_glob = "*.pyc*"
pyc_files = sorted(path.relative_to(temp_dir) for path in temp_dir.rglob(pyc_glob))