diff --git a/planning/changes/2026-05-31.01-bmad-to-superpowers-migration-and-httpx2-wrapper.md b/planning/changes/2026-05-31.01-bmad-to-superpowers-migration-and-httpx2-wrapper.md index 8b51e72..804da59 100644 --- a/planning/changes/2026-05-31.01-bmad-to-superpowers-migration-and-httpx2-wrapper.md +++ b/planning/changes/2026-05-31.01-bmad-to-superpowers-migration-and-httpx2-wrapper.md @@ -133,6 +133,7 @@ The provider stays a flat dataclass with no base class. Reasons: ```python T = TypeVar("T", bound=pydantic.BaseModel) + class HttpClient: client: httpx2.Client auth_headers: Callable[[], dict[str, str]] diff --git a/planning/changes/2026-05-31.05-ioc-idiomatic-modern-di-typer.md b/planning/changes/2026-05-31.05-ioc-idiomatic-modern-di-typer.md index 61d7f46..5d32681 100644 --- a/planning/changes/2026-05-31.05-ioc-idiomatic-modern-di-typer.md +++ b/planning/changes/2026-05-31.05-ioc-idiomatic-modern-di-typer.md @@ -83,8 +83,13 @@ modern_di_typer.setup_di(MAIN_APP, ioc.container) @MAIN_APP.callback() def _root( ctx: typer.Context, - project_id: ..., strategy: ..., provider: ..., token: ..., - default_branch: ..., gitlab_endpoint: ..., request_timeout: ..., + project_id: ..., + strategy: ..., + provider: ..., + token: ..., + default_branch: ..., + gitlab_endpoint: ..., + request_timeout: ..., _version: ..., ) -> None: try: @@ -112,7 +117,9 @@ aren't known here). def _tag( use_case: typing.Annotated[SemvertagUseCase, modern_di_typer.FromDI(SemvertagUseCase)], quiet: typing.Annotated[bool, typer.Option("--quiet", help="Suppress progress narrative.")] = False, - json_flag: typing.Annotated[bool, typer.Option("--json", help="Emit JSON envelope instead of human-readable output.")] = False, + json_flag: typing.Annotated[ + bool, typer.Option("--json", help="Emit JSON envelope instead of human-readable output.") + ] = False, ) -> None: output: Output = build_json_output(quiet=quiet) if json_flag else build_rich_output(quiet=quiet) try: diff --git a/planning/changes/2026-05-31.07-strategy-no-bump-cleanup.md b/planning/changes/2026-05-31.07-strategy-no-bump-cleanup.md index ed6b72b..a313399 100644 --- a/planning/changes/2026-05-31.07-strategy-no-bump-cleanup.md +++ b/planning/changes/2026-05-31.07-strategy-no-bump-cleanup.md @@ -106,17 +106,17 @@ class ConventionalCommitsStrategy: Replace: ```python -status=_status_for_no_bump(self.strategy.name), +status = (_status_for_no_bump(self.strategy.name),) # ... -reason=_reason_for_no_bump(self.strategy.name), +reason = (_reason_for_no_bump(self.strategy.name),) ``` With: ```python -status=self.strategy.no_bump_status, +status = (self.strategy.no_bump_status,) # ... -reason=self.strategy.no_bump_reason, +reason = (self.strategy.no_bump_reason,) ``` Delete: diff --git a/planning/changes/2026-05-31.08-v0-1-0-release-prep.md b/planning/changes/2026-05-31.08-v0-1-0-release-prep.md index 68acc13..23c1260 100644 --- a/planning/changes/2026-05-31.08-v0-1-0-release-prep.md +++ b/planning/changes/2026-05-31.08-v0-1-0-release-prep.md @@ -157,13 +157,13 @@ Drop the `--provider` typer Option (currently around lines 93-96 in provider: typing.Annotated[ str | None, typer.Option("--provider", help="Provider: gitlab | github | bitbucket."), -] = None, +] = (None,) ``` Drop the corresponding line in `_collect_overrides` call (~line 124): ```python -provider=provider, +provider = (provider,) ``` Drop the `provider` keyword from `_collect_overrides`'s signature diff --git a/planning/changes/2026-06-07.01-httpware-migration.md b/planning/changes/2026-06-07.01-httpware-migration.md index d0dca36..d2aff5e 100644 --- a/planning/changes/2026-06-07.01-httpware-migration.md +++ b/planning/changes/2026-06-07.01-httpware-migration.md @@ -95,9 +95,7 @@ def translate_gitlab(exc: httpware.StatusError, *, project_id: int) -> Exception "Add 'api' or 'write_repository' to the SEMVERTAG_TOKEN scopes on GitLab." ) if isinstance(exc, httpware.NotFoundError): - return ConfigError( - f"GitLab project not found: project_id={project_id}. Verify CI_PROJECT_ID or --project-id." - ) + return ConfigError(f"GitLab project not found: project_id={project_id}. Verify CI_PROJECT_ID or --project-id.") if isinstance(exc, httpware.UnprocessableEntityError): return ConfigError( "Request rejected by GitLab: 422. Check tag name format and that the referenced commit exists." @@ -106,8 +104,7 @@ def translate_gitlab(exc: httpware.StatusError, *, project_id: int) -> Exception return ProviderAPIError("GitLab rate limit: 429. Retries exhausted after 3 attempts; try again later.") if isinstance(exc, httpware.ServerStatusError): return ProviderAPIError( - f"GitLab API failure: {status}. Retries exhausted after 3 attempts. " - "Try again or check GitLab status." + f"GitLab API failure: {status}. Retries exhausted after 3 attempts. Try again or check GitLab status." ) return ProviderAPIError(f"Unexpected GitLab response: {status}. Please file an issue.") @@ -117,8 +114,7 @@ def translate_create_tag_bad_request(exc: httpware.BadRequestError, *, tag_name: body = exc.response.text if _TAG_EXISTS_FRAGMENT in body.lower(): return ConfigError( - f"Tag already exists: '{tag_name}'. " - "The tag was created by a concurrent run or previous invocation." + f"Tag already exists: '{tag_name}'. The tag was created by a concurrent run or previous invocation." ) return ConfigError("Request rejected by GitLab: 400. Check tag name format and that the referenced commit exists.") ``` @@ -162,8 +158,7 @@ class GitLabProvider: raise _errors.translate_gitlab(exc, project_id=self.project_id) from exc if not project.default_branch: raise ConfigError( - "Default branch missing from GitLab response. " - "Verify the project has a default branch configured." + "Default branch missing from GitLab response. Verify the project has a default branch configured." ) return project.default_branch @@ -175,11 +170,13 @@ class GitLabProvider: def create_tag(self, name: str, commit_sha: str) -> None: try: - self.http.send(self.http.build_request( - "POST", - f"{_API_PREFIX}/{self.project_id}/repository/tags", - json={"tag_name": name, "ref": commit_sha}, - )) + self.http.send( + self.http.build_request( + "POST", + f"{_API_PREFIX}/{self.project_id}/repository/tags", + json={"tag_name": name, "ref": commit_sha}, + ) + ) except httpware.BadRequestError as exc: raise _errors.translate_create_tag_bad_request(exc, tag_name=name) from exc except httpware.StatusError as exc: @@ -195,6 +192,7 @@ The `_url(self, path)` helper (`f"{self.config.endpoint.rstrip('/')}{path}"`) de import httpware + def _build_gitlab_provider(settings: Settings) -> GitLabProvider: if settings.project_id is None: raise ConfigError("Project id missing. Set CI_PROJECT_ID or pass --project-id.") diff --git a/planning/changes/2026-06-08.01-httpware-decoder-adoption.md b/planning/changes/2026-06-08.01-httpware-decoder-adoption.md index b219d64..eea5737 100644 --- a/planning/changes/2026-06-08.01-httpware-decoder-adoption.md +++ b/planning/changes/2026-06-08.01-httpware-decoder-adoption.md @@ -168,9 +168,7 @@ The pagination helpers (`_next_page_url`, `_parse_rel_values`, `_same_origin`, ` ```python if isinstance(exc, httpware.DecodeError): - return ProviderAPIError( - f"GitLab {exc.model.__name__} response could not be decoded: {exc.original}" - ) + return ProviderAPIError(f"GitLab {exc.model.__name__} response could not be decoded: {exc.original}") ``` Branch ordering: `DecodeError` should be checked **before** the generic `ClientError` fallback at the end of `_translate_gitlab_transport`, since `DecodeError` is a `ClientError` subclass and the fallback would otherwise swallow it with the less informative `f"GitLab request failed: {type(exc).__name__}"` message. diff --git a/planning/changes/2026-06-08.02-github-provider.md b/planning/changes/2026-06-08.02-github-provider.md index aebe391..7cae195 100644 --- a/planning/changes/2026-06-08.02-github-provider.md +++ b/planning/changes/2026-06-08.02-github-provider.md @@ -161,7 +161,7 @@ class _CommitAuthor(pydantic.BaseModel): class _CommitItem(pydantic.BaseModel): sha: str - commit: _CommitAuthor # GitHub nests message under .commit: {sha, commit: {message, author, ...}} + commit: _CommitAuthor # GitHub nests message under .commit: {sha, commit: {message, author, ...}} class _TagCommit(pydantic.BaseModel): @@ -170,7 +170,7 @@ class _TagCommit(pydantic.BaseModel): class _TagItem(pydantic.BaseModel): name: str - commit: _TagCommit # {name, commit: {sha, url}} + commit: _TagCommit # {name, commit: {sha, url}} class _CommitList(pydantic.RootModel[list[_CommitItem]]): @@ -185,7 +185,7 @@ class _TagList(pydantic.RootModel[list[_TagItem]]): class GitHubProvider: name: typing.ClassVar[str] = "github" config: GitHubConfig - repo: str # "OWNER/REPO" + repo: str # "OWNER/REPO" http: httpware.Client def get_default_branch(self) -> str: @@ -241,11 +241,13 @@ class GitHubProvider: def create_tag(self, name: str, commit_sha: str) -> None: try: - self.http.send(self.http.build_request( - "POST", - f"{_API_PREFIX}/{self.repo}/git/refs", - json={"ref": f"refs/tags/{name}", "sha": commit_sha}, - )) + self.http.send( + self.http.build_request( + "POST", + f"{_API_PREFIX}/{self.repo}/git/refs", + json={"ref": f"refs/tags/{name}", "sha": commit_sha}, + ) + ) except httpware.UnprocessableEntityError as exc: raise _errors.translate_create_tag_github_unprocessable(exc, tag_name=name) from exc except httpware.ClientError as exc: @@ -275,17 +277,11 @@ Three changes in `semvertag/providers/_errors.py`: ```python def _translate_transport(exc: httpware.ClientError, *, provider_label: str) -> Exception: if isinstance(exc, httpware.DecodeError): - return ProviderAPIError( - f"{provider_label} {exc.model.__name__} response could not be decoded: {exc.original}" - ) + return ProviderAPIError(f"{provider_label} {exc.model.__name__} response could not be decoded: {exc.original}") if isinstance(exc, httpware.TimeoutError): - return ProviderAPIError( - f"{provider_label} request timed out. Try again or increase SEMVERTAG_REQUEST_TIMEOUT." - ) + return ProviderAPIError(f"{provider_label} request timed out. Try again or increase SEMVERTAG_REQUEST_TIMEOUT.") if isinstance(exc, httpware.RetryBudgetExhaustedError): - return ProviderAPIError( - f"{provider_label} retries exhausted after {exc.attempts} attempts. Try again later." - ) + return ProviderAPIError(f"{provider_label} retries exhausted after {exc.attempts} attempts. Try again later.") if isinstance(exc, httpware.NetworkError): return ProviderAPIError(f"{provider_label} unreachable. Check network connectivity.") return ProviderAPIError(f"{provider_label} request failed: {type(exc).__name__}") @@ -304,15 +300,11 @@ Three changes in `semvertag/providers/_errors.py`: "(or 'public_repo' / 'repo' for classic PATs)." ) if isinstance(exc, httpware.NotFoundError): - return ConfigError( - f"GitHub repo not found: repo='{repo}'. Verify GITHUB_REPOSITORY or --repo OWNER/REPO." - ) + return ConfigError(f"GitHub repo not found: repo='{repo}'. Verify GITHUB_REPOSITORY or --repo OWNER/REPO.") if isinstance(exc, httpware.UnprocessableEntityError): # Generic 422. The create_tag-specific 422 ("already_exists") is handled separately # by translate_create_tag_github_unprocessable below. - return ConfigError( - "Request rejected by GitHub: 422. Check ref format and that the referenced sha exists." - ) + return ConfigError("Request rejected by GitHub: 422. Check ref format and that the referenced sha exists.") if isinstance(exc, httpware.RateLimitedError): return ProviderAPIError( "GitHub rate limit: 429. Retries exhausted after 3 attempts; " @@ -324,27 +316,20 @@ Three changes in `semvertag/providers/_errors.py`: "Retries exhausted after 3 attempts. Try again or check https://www.githubstatus.com." ) if isinstance(exc, httpware.StatusError): - return ProviderAPIError( - f"Unexpected GitHub response: {exc.response.status_code}. Please file an issue." - ) + return ProviderAPIError(f"Unexpected GitHub response: {exc.response.status_code}. Please file an issue.") return _translate_transport(exc, provider_label="GitHub") ``` 3. **Add `translate_create_tag_github_unprocessable(exc, *, tag_name: str)`** for the 422-already-exists special case. Inspects body for the structured `"already_exists"` code (durable contract) OR the human-readable `"already exists"` substring (safety net): ```python - def translate_create_tag_github_unprocessable( - exc: httpware.UnprocessableEntityError, *, tag_name: str - ) -> Exception: + def translate_create_tag_github_unprocessable(exc: httpware.UnprocessableEntityError, *, tag_name: str) -> Exception: body = exc.response.text if "already_exists" in body or "already exists" in body.lower(): return ConfigError( - f"Tag already exists: '{tag_name}'. " - "The tag was created by a concurrent run or previous invocation." + f"Tag already exists: '{tag_name}'. The tag was created by a concurrent run or previous invocation." ) - return ConfigError( - "Request rejected by GitHub: 422. Check ref format and that the referenced sha exists." - ) + return ConfigError("Request rejected by GitHub: 422. Check ref format and that the referenced sha exists.") ``` `_translate_gitlab_transport` deletes; `translate_gitlab` is updated to call `_translate_transport(exc, provider_label="GitLab")` for its transport branches. No behavior change for the GitLab side — messages remain bit-identical because the parameterization only varies the label string. @@ -469,18 +454,21 @@ def _close_github_provider(provider: GitHubProvider) -> None: class ProvidersGroup(modern_di.Group): gitlab_client = providers.Factory(scope=Scope.APP, creator=_build_gitlab_client) gitlab_provider = providers.Factory( - scope=Scope.APP, creator=_build_gitlab_provider, + scope=Scope.APP, + creator=_build_gitlab_provider, kwargs={"client": gitlab_client}, cache_settings=providers.CacheSettings(finalizer=_close_gitlab_provider), ) github_client = providers.Factory(scope=Scope.APP, creator=_build_github_client) github_provider = providers.Factory( - scope=Scope.APP, creator=_build_github_provider, + scope=Scope.APP, + creator=_build_github_provider, kwargs={"client": github_client}, cache_settings=providers.CacheSettings(finalizer=_close_github_provider), ) current_provider = providers.Factory( - scope=Scope.APP, creator=_build_current_provider, + scope=Scope.APP, + creator=_build_current_provider, kwargs={"gitlab_provider": gitlab_provider, "github_provider": github_provider}, ) ``` @@ -499,15 +487,15 @@ Three new flags + provider-aware `--token` routing: provider: typing.Annotated[ str | None, typer.Option("--provider", help="Provider: 'github' or 'gitlab' (default: auto-detect from CI env)."), -] = None, +] = (None,) repo: typing.Annotated[ str | None, typer.Option("--repo", help="GitHub repo as OWNER/REPO (or set GITHUB_REPOSITORY)."), -] = None, +] = (None,) github_endpoint: typing.Annotated[ str | None, typer.Option("--github-endpoint", help="GitHub API endpoint URL (for GitHub Enterprise)."), -] = None, +] = (None,) ``` `--project-id`, `--gitlab-endpoint`, `--strategy`, `--default-branch`, `--request-timeout`, `--token` stay as-is in signature. The `--project-id` and `--gitlab-endpoint` help text doesn't need adjusting — they're GitLab-specific and that's now explicit in the broader CLI surface. @@ -517,9 +505,7 @@ github_endpoint: typing.Annotated[ ```python # In _main_callback, after the first apply_cli_overlay call: if token is not None: - settings = apply_cli_overlay( - settings, {f"{settings.provider}.token": pydantic.SecretStr(token)} - ) + settings = apply_cli_overlay(settings, {f"{settings.provider}.token": pydantic.SecretStr(token)}) ``` Two-pass overlay is mildly awkward but it's the cleanest way to handle "the token belongs to whichever provider we end up using." Alternative (force users to pass `--gitlab-token` / `--github-token` explicitly) is uglier from a UX standpoint — `--token` as the catch-all is what the existing CLI promised. diff --git a/planning/changes/2026-06-09.02-dry-run-flag.md b/planning/changes/2026-06-09.02-dry-run-flag.md index 2ac06a4..12dc7a2 100644 --- a/planning/changes/2026-06-09.02-dry-run-flag.md +++ b/planning/changes/2026-06-09.02-dry-run-flag.md @@ -86,36 +86,56 @@ def __call__(self, *, output: Output, dry_run: bool = False) -> RunResult: if latest_semver_tag is None: return self._emit( - output=output, bump=Bump.NONE, status="no_tags", - tag=None, commit=commit.sha, reason=_NO_TAGS_REASON, + output=output, + bump=Bump.NONE, + status="no_tags", + tag=None, + commit=commit.sha, + reason=_NO_TAGS_REASON, ) if latest_semver_tag.commit_sha == commit.sha: return self._emit( - output=output, bump=Bump.NONE, status="already_tagged", - tag=latest_semver_tag.name, commit=commit.sha, reason=_ALREADY_TAGGED_REASON, + output=output, + bump=Bump.NONE, + status="already_tagged", + tag=latest_semver_tag.name, + commit=commit.sha, + reason=_ALREADY_TAGGED_REASON, ) output.progress("Computing bump...") bump: typing.Final = self.strategy.decide(commit) if bump is Bump.NONE: return self._emit( - output=output, bump=Bump.NONE, status=self.strategy.no_bump_status, - tag=None, commit=commit.sha, reason=self.strategy.no_bump_reason, + output=output, + bump=Bump.NONE, + status=self.strategy.no_bump_status, + tag=None, + commit=commit.sha, + reason=self.strategy.no_bump_reason, ) new_version: typing.Final = _compute_new_version(latest_semver_tag, bump) if dry_run: return self._emit( - output=output, bump=bump, status="dry_run", - tag=new_version, commit=commit.sha, reason=None, + output=output, + bump=bump, + status="dry_run", + tag=new_version, + commit=commit.sha, + reason=None, ) output.progress(f"Creating tag {new_version}...") self.provider.create_tag(name=new_version, commit_sha=commit.sha) return self._emit( - output=output, bump=bump, status="created", - tag=new_version, commit=commit.sha, reason=None, + output=output, + bump=bump, + status="created", + tag=new_version, + commit=commit.sha, + reason=None, ) ``` diff --git a/planning/changes/2026-06-24.02-closed-outcome-type.md b/planning/changes/2026-06-24.02-closed-outcome-type.md index 3f50526..f3ea6ed 100644 --- a/planning/changes/2026-06-24.02-closed-outcome-type.md +++ b/planning/changes/2026-06-24.02-closed-outcome-type.md @@ -48,11 +48,32 @@ fields meaningful to it: ```python @dataclasses.dataclass(frozen=True, slots=True, kw_only=True) -class Created: tag: str; bump: Bump; commit: str -class DryRun: tag: str; bump: Bump; commit: str -class NoTags: commit: str -class AlreadyTagged: tag: str; commit: str -class NoBump: status: str; reason: str; commit: str # strategy-supplied +class Created: + tag: str + bump: Bump + commit: str + + +class DryRun: + tag: str + bump: Bump + commit: str + + +class NoTags: + commit: str + + +class AlreadyTagged: + tag: str + commit: str + + +class NoBump: + status: str + reason: str + commit: str # strategy-supplied + Outcome: typing.TypeAlias = Created | DryRun | NoTags | AlreadyTagged | NoBump ``` diff --git a/planning/changes/2026-06-26.02-provider-target.md b/planning/changes/2026-06-26.02-provider-target.md index 6852db4..b59c150 100644 --- a/planning/changes/2026-06-26.02-provider-target.md +++ b/planning/changes/2026-06-26.02-provider-target.md @@ -68,10 +68,12 @@ not decided-against. class GitHubTarget: repo: str + @dataclasses.dataclass(frozen=True, slots=True, kw_only=True) class GitLabTarget: project_id: int + ProviderTarget: typing.TypeAlias = GitHubTarget | GitLabTarget ``` @@ -88,11 +90,13 @@ the target using locals that narrow across its existing guard — no `assert`, n ```python _provider_target: ProviderTarget | None = pydantic.PrivateAttr(default=None) + @property def provider_target(self) -> ProviderTarget: assert self._provider_target is not None, "provider_target is set by _resolve_provider" # noqa: S101 return self._provider_target + @pydantic.model_validator(mode="after") def _resolve_provider(self) -> "Settings": if self.provider is None: @@ -123,9 +127,13 @@ asserts are (see Risk). ```python match settings.provider_target: case GitHubTarget(repo=repo): - return GitHubProvider(config=settings.github, repo=repo, http=github_client, default_branch=settings.default_branch) + return GitHubProvider( + config=settings.github, repo=repo, http=github_client, default_branch=settings.default_branch + ) case GitLabTarget(project_id=project_id): - return GitLabProvider(config=settings.gitlab, project_id=project_id, http=gitlab_client, default_branch=settings.default_branch) + return GitLabProvider( + config=settings.gitlab, project_id=project_id, http=gitlab_client, default_branch=settings.default_branch + ) case _: # pragma: no cover typing.assert_never(settings.provider_target) ``` diff --git a/planning/changes/2026-06-26.03-semver-tag-selection.md b/planning/changes/2026-06-26.03-semver-tag-selection.md index 827f479..9bbf003 100644 --- a/planning/changes/2026-06-26.03-semver-tag-selection.md +++ b/planning/changes/2026-06-26.03-semver-tag-selection.md @@ -87,6 +87,7 @@ precedence-neutral. ```python _BUMP_PARTS: typing.Final[dict[Bump, str]] = {Bump.MAJOR: "major", Bump.MINOR: "minor", Bump.PATCH: "patch"} + def _compute_new_version(version: semver.Version, bump: Bump) -> str: return str(version.next_version(_BUMP_PARTS[bump])) ``` diff --git a/planning/releases/0.3.1.md b/planning/releases/0.3.1.md index 65b9540..33f6548 100644 --- a/planning/releases/0.3.1.md +++ b/planning/releases/0.3.1.md @@ -9,7 +9,7 @@ If you're not on `branch-prefix`, or your CI is GitLab, you can skip this releas `BranchPrefixStrategy.decide` gated the bump computation on a single substring check: ```python -if self.config.merge_mark_text not in subject: # default: "Merge branch" +if self.config.merge_mark_text not in subject: # default: "Merge branch" return Bump.NONE ``` diff --git a/planning/releases/0.8.3.md b/planning/releases/0.8.3.md new file mode 100644 index 0000000..949ceeb --- /dev/null +++ b/planning/releases/0.8.3.md @@ -0,0 +1,34 @@ +# semvertag 0.8.3 — restore compatibility with modern-di 3.x + +**0.8.2 is broken and should not be used.** Installing it fresh resolves +modern-di 3.0.0, which renamed a Factory keyword semvertag still passed, so the +CLI raised `TypeError` on import — `semvertag --help` included. This release +fixes that and bounds the dependency so it cannot recur. + +## Fixes + +- **Migrate to the modern-di 3.x Factory API.** `Factory(cache_settings=...)` + was renamed to `Factory(cache=...)` in modern-di 3.0.0. `semvertag/ioc.py` + still used the old name, so importing `semvertag.ioc` raised + `TypeError: Factory.__init__() got an unexpected keyword argument 'cache_settings'`. + Every entry point died on import, and the `modern-python/semvertag` GitHub + Action failed for all users. + +## Dependencies + +- **Bound `modern-di-typer` to `>=3,<4`.** The dependency was previously + unbounded, which is how a modern-di major landed in a published semvertag + without a release. A future modern-di 4.0 now fails resolution at install + time instead of breaking the CLI at runtime. + +## CI + +- Adopt **ruff 0.16.0**: ignore `CPY001` (`missing-copyright-notice`) and + silence `PLR0917` on the typer callback, both newly stabilized out of + preview; reformat Python code blocks in Markdown, which 0.16.0 now formats. + No runtime effect. + +## Downstream + +Upgrade from 0.8.2. Users of the `modern-python/semvertag` action get the fix +automatically once the floating `v0` tag moves; no workflow change is needed. diff --git a/pyproject.toml b/pyproject.toml index 14b722f..d139fd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ dependencies = [ "rich", "semver", "pydantic-settings", - "modern-di-typer", + "modern-di-typer>=3,<4", "httpx2", "httpware[pydantic]>=0.15.0", ] @@ -77,6 +77,7 @@ ignore = [ "COM812", "ISC001", "S105", + "CPY001", # no per-file copyright header ] isort.lines-after-imports = 2 isort.no-lines-before = ["standard-library", "local-folder"] diff --git a/semvertag/__main__.py b/semvertag/__main__.py index e2e1706..202c163 100644 --- a/semvertag/__main__.py +++ b/semvertag/__main__.py @@ -67,7 +67,7 @@ def _collect_overrides( # noqa: PLR0913 @MAIN_APP.callback() -def _main_callback( # noqa: PLR0913 +def _main_callback( # noqa: PLR0913, PLR0917 ctx: typer.Context, project_id: typing.Annotated[ int | None, diff --git a/semvertag/ioc.py b/semvertag/ioc.py index 28563e4..2a1cfa8 100644 --- a/semvertag/ioc.py +++ b/semvertag/ioc.py @@ -101,13 +101,13 @@ class ProvidersGroup(modern_di.Group): scope=Scope.APP, creator=_build_gitlab_client, bound_type=None, - cache_settings=providers.CacheSettings(finalizer=_close_client), + cache=providers.CacheSettings(finalizer=_close_client), ) github_client = providers.Factory( scope=Scope.APP, creator=_build_github_client, bound_type=None, - cache_settings=providers.CacheSettings(finalizer=_close_client), + cache=providers.CacheSettings(finalizer=_close_client), ) current_provider = providers.Factory( scope=Scope.APP,