From d7fcd97726c85b582c2b42e810531bc23e6f695b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 01:05:30 +0000 Subject: [PATCH 001/221] ci(deps): bump actions/labeler from 5 to 6 Bumps [actions/labeler](https://github.com/actions/labeler) from 5 to 6. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](https://github.com/actions/labeler/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/label_pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/label_pr.yml b/.github/workflows/label_pr.yml index a74a507bba..fda20e4173 100644 --- a/.github/workflows/label_pr.yml +++ b/.github/workflows/label_pr.yml @@ -14,7 +14,7 @@ jobs: sparse-checkout: | .github/labeler.yml sparse-checkout-cone-mode: false - - uses: actions/labeler@v5 + - uses: actions/labeler@v6 with: configuration-path: .github/labeler.yml - name: Label based on PR title From adbe3cac1133a36272c302c88fe06ca9a6afc58d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 01:05:35 +0000 Subject: [PATCH 002/221] ci(deps): bump actions/setup-python from 5 to 6 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docspublish.yml | 4 ++-- .github/workflows/homebrewpublish.yml | 2 +- .github/workflows/pythonpackage.yml | 2 +- .github/workflows/pythonpublish.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index 7a2109266f..eb52dc46a8 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -15,7 +15,7 @@ jobs: token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" - name: Install dependencies @@ -51,7 +51,7 @@ jobs: run: | git pull origin master - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" - name: Install dependencies diff --git a/.github/workflows/homebrewpublish.yml b/.github/workflows/homebrewpublish.yml index c9a1b35081..8c315b6322 100644 --- a/.github/workflows/homebrewpublish.yml +++ b/.github/workflows/homebrewpublish.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" - name: Install dependencies diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 00794babbf..7a574c9e0a 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 3976d309dd..e70690a1a3 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -14,7 +14,7 @@ jobs: token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.x" - name: Install dependencies From 0fbc28718b96850257d9587ac8276383700c043f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 01:05:38 +0000 Subject: [PATCH 003/221] ci(deps): bump actions/github-script from 7 to 8 Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/label_issues.yml | 2 +- .github/workflows/label_pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/label_issues.yml b/.github/workflows/label_issues.yml index e74a36c4bd..359c50d65a 100644 --- a/.github/workflows/label_issues.yml +++ b/.github/workflows/label_issues.yml @@ -12,7 +12,7 @@ jobs: issues: write runs-on: ubuntu-latest steps: - - uses: actions/github-script@v7 + - uses: actions/github-script@v8 with: script: | const issue = await github.rest.issues.get({ diff --git a/.github/workflows/label_pr.yml b/.github/workflows/label_pr.yml index fda20e4173..c1a3df2c70 100644 --- a/.github/workflows/label_pr.yml +++ b/.github/workflows/label_pr.yml @@ -18,7 +18,7 @@ jobs: with: configuration-path: .github/labeler.yml - name: Label based on PR title - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const title = context.payload.pull_request.title.toLowerCase(); From 1f2d26a45a5d4bd9cb5ae44b523334b69a183a81 Mon Sep 17 00:00:00 2001 From: vemilano <230173219+vemilano@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:24:21 +0200 Subject: [PATCH 004/221] fix: cargo workspaces --- commitizen/providers/cargo_provider.py | 41 +++++++++++++++++++++----- tests/providers/test_cargo_provider.py | 16 ++++++++-- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/commitizen/providers/cargo_provider.py b/commitizen/providers/cargo_provider.py index d453a4aa5b..53bf77caac 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -1,5 +1,6 @@ from __future__ import annotations +import glob from pathlib import Path import tomlkit @@ -22,8 +23,10 @@ def lock_file(self) -> Path: return Path() / self.lock_filename def get(self, document: tomlkit.TOMLDocument) -> str: + # If there is a root package, change its version (but not the workspace version) try: return document["package"]["version"] # type: ignore[index,return-value] + # Else, bump the workspace version except tomlkit.exceptions.NonExistentKey: ... return document["workspace"]["package"]["version"] # type: ignore[index,return-value] @@ -43,15 +46,39 @@ def set_version(self, version: str) -> None: def set_lock_version(self, version: str) -> None: cargo_toml_content = tomlkit.parse(self.file.read_text()) + cargo_lock_content = tomlkit.parse(self.lock_file.read_text()) + packages: tomlkit.items.AoT = cargo_lock_content["package"] # type: ignore[assignment] try: package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + for i, package in enumerate(packages): + if package["name"] == package_name: + cargo_lock_content["package"][i]["version"] = version # type: ignore[index] + break except tomlkit.exceptions.NonExistentKey: - package_name = cargo_toml_content["workspace"]["package"]["name"] # type: ignore[index] + workspace_members = ( + cargo_toml_content.get("workspace", {}) + .get("package", {}) + .get("members", []) + ) + members_inheriting = [] + + for member in workspace_members: + matched_paths = glob.glob(member, recursive=True) + for path in matched_paths: + cargo_file = Path(path) / "Cargo.toml" + cargo_toml_content = tomlkit.parse(cargo_file.read_text()) + try: + version_workspace = cargo_toml_content["package"]["version"][ # type: ignore[index] + "workspace" + ] + if version_workspace is True: + package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + members_inheriting.append(package_name) + except tomlkit.exceptions.NonExistentKey: + continue + + for i, package in enumerate(packages): + if package["name"] in members_inheriting: + cargo_lock_content["package"][i]["version"] = version # type: ignore[index] - cargo_lock_content = tomlkit.parse(self.lock_file.read_text()) - packages: tomlkit.items.AoT = cargo_lock_content["package"] # type: ignore[assignment] - for i, package in enumerate(packages): - if package["name"] == package_name: - cargo_lock_content["package"][i]["version"] = version # type: ignore[index] - break self.lock_file.write_text(tomlkit.dumps(cargo_lock_content)) diff --git a/tests/providers/test_cargo_provider.py b/tests/providers/test_cargo_provider.py index 4b20c6ea53..8a3b1b8da9 100644 --- a/tests/providers/test_cargo_provider.py +++ b/tests/providers/test_cargo_provider.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os from pathlib import Path from textwrap import dedent @@ -23,13 +24,19 @@ CARGO_WORKSPACE_TOML = """\ [workspace.package] -name = "whatever" +members = ["whatever"] version = "0.1.0" """ +CARGO_WORKSPACE_MEMBER_TOML = """\ +[package] +name = "whatever" +version.workspace = true +""" + CARGO_WORKSPACE_TOML_EXPECTED = """\ [workspace.package] -name = "whatever" +members = ["whatever"] version = "42.1" """ @@ -115,6 +122,11 @@ def test_cargo_provider_with_lock( file = chdir / filename file.write_text(dedent(toml_content)) + member_folder = chdir / "whatever" + os.mkdir(member_folder) + member_file = member_folder / "Cargo.toml" + member_file.write_text(dedent(CARGO_WORKSPACE_MEMBER_TOML)) + lock_filename = CargoProvider.lock_filename lock_file = chdir / lock_filename lock_file.write_text(dedent(lock_content)) From 44bce6029e93f214e6014a1560be769d15632a92 Mon Sep 17 00:00:00 2001 From: vemilano <230173219+vemilano@users.noreply.github.com> Date: Thu, 4 Sep 2025 17:30:45 +0200 Subject: [PATCH 005/221] fix: members in workspace, use exclude --- commitizen/providers/cargo_provider.py | 45 +++--- tests/providers/test_cargo_provider.py | 184 +++++++++++++++++++++++-- 2 files changed, 201 insertions(+), 28 deletions(-) diff --git a/commitizen/providers/cargo_provider.py b/commitizen/providers/cargo_provider.py index 53bf77caac..afeb47f58b 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -1,5 +1,6 @@ from __future__ import annotations +import fnmatch import glob from pathlib import Path @@ -8,6 +9,13 @@ from commitizen.providers.base_provider import TomlProvider +def matches_exclude(path: str, exclude_patterns: list[str]) -> bool: + for pattern in exclude_patterns: + if fnmatch.fnmatch(path, pattern): + return True + return False + + class CargoProvider(TomlProvider): """ Cargo version management @@ -55,27 +63,30 @@ def set_lock_version(self, version: str) -> None: cargo_lock_content["package"][i]["version"] = version # type: ignore[index] break except tomlkit.exceptions.NonExistentKey: - workspace_members = ( - cargo_toml_content.get("workspace", {}) - .get("package", {}) - .get("members", []) + workspace_members = cargo_toml_content.get("workspace", {}).get( + "members", [] + ) + excluded_workspace_members = cargo_toml_content.get("workspace", {}).get( + "exclude", [] ) members_inheriting = [] for member in workspace_members: - matched_paths = glob.glob(member, recursive=True) - for path in matched_paths: - cargo_file = Path(path) / "Cargo.toml" - cargo_toml_content = tomlkit.parse(cargo_file.read_text()) - try: - version_workspace = cargo_toml_content["package"]["version"][ # type: ignore[index] - "workspace" - ] - if version_workspace is True: - package_name = cargo_toml_content["package"]["name"] # type: ignore[index] - members_inheriting.append(package_name) - except tomlkit.exceptions.NonExistentKey: - continue + for path in glob.glob(member, recursive=True): + if not matches_exclude(path, excluded_workspace_members): + cargo_file = Path(path) / "Cargo.toml" + cargo_toml_content = tomlkit.parse(cargo_file.read_text()) + try: + version_workspace = cargo_toml_content["package"][ + "version" + ][ # type: ignore[index] + "workspace" + ] + if version_workspace is True: + package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + members_inheriting.append(package_name) + except tomlkit.exceptions.NonExistentKey: + continue for i, package in enumerate(packages): if package["name"] in members_inheriting: diff --git a/tests/providers/test_cargo_provider.py b/tests/providers/test_cargo_provider.py index 8a3b1b8da9..5e7b2d8cb7 100644 --- a/tests/providers/test_cargo_provider.py +++ b/tests/providers/test_cargo_provider.py @@ -23,20 +23,64 @@ """ CARGO_WORKSPACE_TOML = """\ +[workspace] +members = ["member1", "folder/member2", "crates/*"] +exclude = ["crates/member4", "folder/member5"] + [workspace.package] -members = ["whatever"] version = "0.1.0" """ -CARGO_WORKSPACE_MEMBER_TOML = """\ +CARGO_WORKSPACE_MEMBERS = [ + { + "path": "member1", + "content": """\ [package] -name = "whatever" +name = "member1" version.workspace = true -""" +""", + }, + { + "path": "folder/member2", + "content": """\ +[package] +name = "member2" +version.workspace = "1.1.1" +""", + }, + { + "path": "crates/member3", + "content": """\ +[package] +name = "member3" +version.workspace = true +""", + }, + { + "path": "crates/member4", + "content": """\ +[package] +name = "member4" +version.workspace = "2.2.2" +""", + }, + { + "path": "folder/member5", + "content": """\ +[package] +name = "member5" +version.workspace = "3.3.3" +""", + }, +] + CARGO_WORKSPACE_TOML_EXPECTED = """\ +[workspace] +members = ["member1", "folder/member2", "crates/*"] +exclude = ["crates/member4", "folder/member5"] + [workspace.package] -members = ["whatever"] version = "42.1" """ @@ -66,6 +110,120 @@ ] """ +CARGO_WORKSPACE_LOCK = """\ +[[package]] +name = "member1" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member2" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member3" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member4" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member5" +version = "3.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] +""" + +CARGO_WORKSPACE_LOCK_EXPECTED = """\ +[[package]] +name = "member1" +version = "42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member2" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member3" +version = "42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member4" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] + +[[package]] +name = "member5" +version = "3.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] +""" + @pytest.mark.parametrize( "content, expected", @@ -104,9 +262,9 @@ def test_cargo_provider( ), ( CARGO_WORKSPACE_TOML, - CARGO_LOCK, + CARGO_WORKSPACE_LOCK, CARGO_WORKSPACE_TOML_EXPECTED, - CARGO_LOCK_EXPECTED, + CARGO_WORKSPACE_LOCK_EXPECTED, ), ), ) @@ -122,10 +280,14 @@ def test_cargo_provider_with_lock( file = chdir / filename file.write_text(dedent(toml_content)) - member_folder = chdir / "whatever" - os.mkdir(member_folder) - member_file = member_folder / "Cargo.toml" - member_file.write_text(dedent(CARGO_WORKSPACE_MEMBER_TOML)) + # Create workspace members + os.mkdir(chdir / "crates") + os.mkdir(chdir / "folder") + for i in range(0, 5): + member_folder = Path(CARGO_WORKSPACE_MEMBERS[i]["path"]) + os.mkdir(member_folder) + member_file = member_folder / "Cargo.toml" + member_file.write_text(dedent(CARGO_WORKSPACE_MEMBERS[i]["content"])) lock_filename = CargoProvider.lock_filename lock_file = chdir / lock_filename From 1cde9ee705928c75873a33ad738d61a83447482f Mon Sep 17 00:00:00 2001 From: vemilano <230173219+vemilano@users.noreply.github.com> Date: Fri, 5 Sep 2025 10:15:37 +0200 Subject: [PATCH 006/221] refactor: reduce code indentation --- commitizen/providers/cargo_provider.py | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/commitizen/providers/cargo_provider.py b/commitizen/providers/cargo_provider.py index afeb47f58b..3e8c95e22a 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -73,20 +73,19 @@ def set_lock_version(self, version: str) -> None: for member in workspace_members: for path in glob.glob(member, recursive=True): - if not matches_exclude(path, excluded_workspace_members): - cargo_file = Path(path) / "Cargo.toml" - cargo_toml_content = tomlkit.parse(cargo_file.read_text()) - try: - version_workspace = cargo_toml_content["package"][ - "version" - ][ # type: ignore[index] - "workspace" - ] - if version_workspace is True: - package_name = cargo_toml_content["package"]["name"] # type: ignore[index] - members_inheriting.append(package_name) - except tomlkit.exceptions.NonExistentKey: - continue + if matches_exclude(path, excluded_workspace_members): + continue + cargo_file = Path(path) / "Cargo.toml" + cargo_toml_content = tomlkit.parse(cargo_file.read_text()) + try: + version_workspace = cargo_toml_content["package"]["version"][ # type: ignore[index] + "workspace" + ] + if version_workspace is True: + package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + members_inheriting.append(package_name) + except tomlkit.exceptions.NonExistentKey: + continue for i, package in enumerate(packages): if package["name"] in members_inheriting: From 186dd18042ad30269e157e17db271a34b71e3bcd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Sep 2025 16:49:37 +0000 Subject: [PATCH 007/221] =?UTF-8?q?bump:=20version=204.8.3=20=E2=86=92=204?= =?UTF-8?q?.8.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 11 +++++++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e09fb63e8..3dfd50ee68 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.8.3 # automatically updated by Commitizen + rev: v4.8.4 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d7a31cc40..5723e11274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## v4.8.4 (2025-09-05) + +### Fix + +- members in workspace, use exclude +- cargo workspaces + +### Refactor + +- reduce code indentation + ## v4.8.3 (2025-06-09) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index af82c57223..adba53e1e0 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.8.3" +__version__ = "4.8.4" diff --git a/pyproject.toml b/pyproject.toml index 82fe8b6e33..ebb2244770 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.8.3" +version = "4.8.4" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -88,7 +88,7 @@ build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "4.8.3" +version = "4.8.4" tag_format = "v$version" version_files = [ "pyproject.toml:version", From 5a21f833e8cf2a56d4218972471afbe98cca1bee Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 21:54:37 +0800 Subject: [PATCH 008/221] refactor(ParseArgs): simplify __call__ function body --- commitizen/cli.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 6f7556df49..a73377fe45 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -52,16 +52,13 @@ def __call__( ) -> None: if not isinstance(values, str): return - if "=" not in values: + + key, sep, value = values.partition("=") + if not key or not sep: raise InvalidCommandArgumentError( f"Option {option_string} expect a key=value format" ) kwargs = getattr(namespace, self.dest, None) or {} - key, value = values.split("=", 1) - if not key: - raise InvalidCommandArgumentError( - f"Option {option_string} expect a key=value format" - ) kwargs[key] = value.strip("'\"") setattr(namespace, self.dest, kwargs) From 647f0f50cd142dbd9ddcf462fedc7a575ba514c5 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 22:28:57 +0800 Subject: [PATCH 009/221] refactor(ExpectedExit): make the constructor more compact --- commitizen/exceptions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/commitizen/exceptions.py b/commitizen/exceptions.py index 8c0956be53..8be792258a 100644 --- a/commitizen/exceptions.py +++ b/commitizen/exceptions.py @@ -59,8 +59,7 @@ class ExpectedExit(CommitizenException): exit_code = ExitCode.EXPECTED_EXIT def __init__(self, *args: str, **kwargs: Any) -> None: - output_method = kwargs.get("output_method") or out.write - kwargs["output_method"] = output_method + kwargs["output_method"] = kwargs.get("output_method") or out.write super().__init__(*args, **kwargs) From d1bfd5535301efc15d2f3ddec236c245e3b9da90 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 21:42:30 +0800 Subject: [PATCH 010/221] refactor(ScmProvider): replace sorted with max --- commitizen/providers/scm_provider.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/commitizen/providers/scm_provider.py b/commitizen/providers/scm_provider.py index 3085b16efa..687775da30 100644 --- a/commitizen/providers/scm_provider.py +++ b/commitizen/providers/scm_provider.py @@ -18,10 +18,8 @@ def get_version(self) -> str: rules = TagRules.from_settings(self.config.settings) tags = get_tags(reachable_only=True) version_tags = rules.get_version_tags(tags) - versions = sorted(rules.extract_version(t) for t in version_tags) - if not versions: - return "0.0.0" - return str(versions[-1]) + version = max((rules.extract_version(t) for t in version_tags), default=None) + return str(version) if version is not None else "0.0.0" def set_version(self, version: str) -> None: # Not necessary From 0fa3db0f0c96c1c65633410dd403ab4377a4588d Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 22:43:30 +0800 Subject: [PATCH 011/221] refactor(git): remove redundant if branch --- commitizen/git.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/commitizen/git.py b/commitizen/git.py index 8025041abb..4883b34e7d 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -328,6 +328,4 @@ def _get_log_as_str_list(start: str | None, end: str, args: str) -> list[str]: c = cmd.run(command) if c.return_code != 0: raise GitCommandError(c.err) - if not c.out: - return [] return c.out.split(f"{delimiter}\n") From 280856adec28eb6d9d87731acdb853366bce6aad Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 13 Jun 2025 21:00:01 +0800 Subject: [PATCH 012/221] fix(Bump): rewrite --get-next NotAllowed error message for consistency --- commitizen/commands/bump.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 2a84483c94..e07a359cf5 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -215,11 +215,13 @@ def __call__(self) -> None: raise NotAllowed("--local-version cannot be combined with --build-metadata") if get_next: - # if trying to use --get-next, we should not allow --changelog or --changelog-to-stdout - if self.changelog_flag or self.changelog_to_stdout: - raise NotAllowed( - "--changelog or --changelog-to-stdout is not allowed with --get-next" - ) + for value, option in ( + (self.changelog_flag, "--changelog"), + (self.changelog_to_stdout, "--changelog-to-stdout"), + ): + if value: + raise NotAllowed(f"{option} cannot be combined with --get-next") + # --get-next is a special case, taking precedence over config for 'update_changelog_on_bump' self.changelog_config = False # Setting dry_run to prevent any unwanted changes to the repo or files From a352e4b7dc8d562122ab2c636de9a56c0cb17a71 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 13 Jun 2025 19:40:48 +0800 Subject: [PATCH 013/221] fix(Changelog): fix _export_template variable type Closes #1503 --- commitizen/commands/changelog.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index dc50eb3ad2..8668dd44c6 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -174,11 +174,15 @@ def _write_changelog( changelog_file.write(changelog_out) - def _export_template(self) -> None: - tpl = changelog.get_changelog_template(self.cz.template_loader, self.template) - # TODO: fix the following type ignores - src = Path(tpl.filename) # type: ignore[arg-type] - Path(self.export_template_to).write_text(src.read_text()) # type: ignore[arg-type] + def _export_template(self, dist: str) -> None: + filename = changelog.get_changelog_template( + self.cz.template_loader, self.template + ).filename + if filename is None: + raise NotAllowed("Template filename is not set") + + text = Path(filename).read_text() + Path(dist).write_text(text) def __call__(self) -> None: commit_parser = self.cz.commit_parser @@ -195,7 +199,7 @@ def __call__(self) -> None: ) if self.export_template_to: - return self._export_template() + return self._export_template(self.export_template_to) if not changelog_pattern or not commit_parser: raise NoPatternMapError( From b35d3431978e357fcce68613869c17b99e5cffe9 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 13 Jun 2025 13:57:59 +0800 Subject: [PATCH 014/221] refactor(TagRules): extract tag_formats property and simplify list comprehension --- commitizen/tags.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/commitizen/tags.py b/commitizen/tags.py index b19bb89e09..e3f54370f1 100644 --- a/commitizen/tags.py +++ b/commitizen/tags.py @@ -5,6 +5,7 @@ from collections.abc import Iterable, Sequence from dataclasses import dataclass, field from functools import cached_property +from itertools import chain from string import Template from typing import TYPE_CHECKING, NamedTuple @@ -88,18 +89,22 @@ class TagRules: ignored_tag_formats: Sequence[str] = field(default_factory=list) merge_prereleases: bool = False + @property + def tag_formats(self) -> Iterable[str]: + return chain([self.tag_format], self.legacy_tag_formats) + @cached_property def version_regexes(self) -> list[re.Pattern]: """Regexes for all legit tag formats, current and legacy""" - tag_formats = [self.tag_format, *self.legacy_tag_formats] - regexes = (self._format_regex(p) for p in tag_formats) - return [re.compile(r) for r in regexes] + return [re.compile(self._format_regex(f)) for f in self.tag_formats] @cached_property def ignored_regexes(self) -> list[re.Pattern]: """Regexes for known but ignored tag formats""" - regexes = (self._format_regex(p, star=True) for p in self.ignored_tag_formats) - return [re.compile(r) for r in regexes] + return [ + re.compile(self._format_regex(f, star=True)) + for f in self.ignored_tag_formats + ] def _format_regex(self, tag_pattern: str, star: bool = False) -> str: """ @@ -240,10 +245,7 @@ def find_tag_for( ) -> GitTag | None: """Find the first matching tag for a given version.""" version = self.scheme(version) if isinstance(version, str) else version - possible_tags = set( - self.normalize_tag(version, f) - for f in (self.tag_format, *self.legacy_tag_formats) - ) + possible_tags = set(self.normalize_tag(version, f) for f in self.tag_formats) candidates = [t for t in tags if t.name in possible_tags] if len(candidates) > 1: warnings.warn( From 4ff20886b6be6c38c0642329bf09c9fb56764b97 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 11:46:44 +0800 Subject: [PATCH 015/221] refactor(Init): use ternary operator --- commitizen/commands/init.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 1207cd02ee..356c4ce27d 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -159,9 +159,9 @@ def __call__(self) -> None: out.success("Configuration complete 🚀") def _ask_config_path(self) -> str: - default_path = ".cz.toml" - if self.project_info.has_pyproject: - default_path = "pyproject.toml" + default_path = ( + "pyproject.toml" if self.project_info.has_pyproject else ".cz.toml" + ) name: str = questionary.select( "Please choose a supported config file: ", @@ -270,15 +270,13 @@ def _ask_version_provider(self) -> str: def _ask_version_scheme(self) -> str: """Ask for setting: version_scheme""" - default = "semver" - if self.project_info.is_python: - default = "pep440" + default_scheme = "pep440" if self.project_info.is_python else "semver" scheme: str = questionary.select( "Choose version scheme: ", - choices=list(KNOWN_SCHEMES), + choices=KNOWN_SCHEMES, style=self.cz.style, - default=default, + default=default_scheme, ).unsafe_ask() return scheme @@ -318,10 +316,9 @@ def _gen_pre_commit_cmd(self, hook_types: list[str]) -> str: """Generate pre-commit command according to given hook types""" if not hook_types: raise ValueError("At least 1 hook type should be provided.") - cmd_str = "pre-commit install " + " ".join( + return "pre-commit install " + " ".join( f"--hook-type {ty}" for ty in hook_types ) - return cmd_str def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None: pre_commit_config_filename = ".pre-commit-config.yaml" From d294d2f9a864eb38cc45682ac4d103a9e39c6545 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 00:11:54 +0800 Subject: [PATCH 016/221] refactor(bump): use a loop to shorten a series of similar NotAllowed exceptions --- commitizen/commands/bump.py | 40 ++++++++++++------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index e07a359cf5..49d90f14d2 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -177,36 +177,22 @@ def __call__(self) -> None: build_metadata = self.arguments["build_metadata"] get_next = self.arguments["get_next"] allow_no_commit = self.arguments["allow_no_commit"] + major_version_zero = self.arguments["major_version_zero"] if manual_version: - if increment: - raise NotAllowed("--increment cannot be combined with MANUAL_VERSION") - - if prerelease: - raise NotAllowed("--prerelease cannot be combined with MANUAL_VERSION") - - if devrelease is not None: - raise NotAllowed("--devrelease cannot be combined with MANUAL_VERSION") - - if is_local_version: - raise NotAllowed( - "--local-version cannot be combined with MANUAL_VERSION" - ) - - if build_metadata: - raise NotAllowed( - "--build-metadata cannot be combined with MANUAL_VERSION" - ) - - if self.bump_settings["major_version_zero"]: - raise NotAllowed( - "--major-version-zero cannot be combined with MANUAL_VERSION" - ) - - if get_next: - raise NotAllowed("--get-next cannot be combined with MANUAL_VERSION") + for val, option in ( + (increment, "--increment"), + (prerelease, "--prerelease"), + (devrelease is not None, "--devrelease"), + (is_local_version, "--local-version"), + (build_metadata, "--build-metadata"), + (major_version_zero, "--major-version-zero"), + (get_next, "--get-next"), + ): + if val: + raise NotAllowed(f"{option} cannot be combined with MANUAL_VERSION") - if self.bump_settings["major_version_zero"] and current_version.release[0]: + if major_version_zero and current_version.release[0]: raise NotAllowed( f"--major-version-zero is meaningless for current version {current_version}" ) From 4a3afff1f503fa5f29b3b7842fea49b4d7740304 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 13 Jun 2025 20:26:51 +0800 Subject: [PATCH 017/221] fix: raise NoVersionSpecifiedError if version is None, and adjust call sites of get_version --- commitizen/commands/bump.py | 7 +---- commitizen/commands/version.py | 32 +++++++++++---------- commitizen/providers/commitizen_provider.py | 5 +++- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 49d90f14d2..07338afb86 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -23,7 +23,6 @@ NoPatternMapError, NotAGitProjectError, NotAllowed, - NoVersionSpecifiedError, ) from commitizen.providers import get_provider from commitizen.tags import TagRules @@ -163,11 +162,7 @@ def _find_increment(self, commits: list[git.GitCommit]) -> Increment | None: def __call__(self) -> None: """Steps executed to bump.""" provider = get_provider(self.config) - - try: - current_version = self.scheme(provider.get_version()) - except TypeError: - raise NoVersionSpecifiedError() + current_version = self.scheme(provider.get_version()) increment = self.arguments["increment"] prerelease = self.arguments["prerelease"] diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 6b0aa331ad..35e9aa6cd6 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -5,6 +5,7 @@ from commitizen import out from commitizen.__version__ import __version__ from commitizen.config import BaseConfig +from commitizen.exceptions import NoVersionSpecifiedError from commitizen.providers import get_provider @@ -28,19 +29,20 @@ def __call__(self) -> None: out.write(f"Commitizen Version: {__version__}") out.write(f"Python Version: {self.python_version}") out.write(f"Operating System: {self.operating_system}") - elif self.parameter.get("project"): - version = get_provider(self.config).get_version() - if version: - out.write(f"{version}") - else: - out.error("No project information in this project.") - elif self.parameter.get("verbose"): - out.write(f"Installed Commitizen Version: {__version__}") - version = get_provider(self.config).get_version() - if version: - out.write(f"Project Version: {version}") - else: + return + + if (verbose := self.parameter.get("verbose")) or self.parameter.get("project"): + if verbose: + out.write(f"Installed Commitizen Version: {__version__}") + + try: + version = get_provider(self.config).get_version() + except NoVersionSpecifiedError: out.error("No project information in this project.") - else: - # if no argument is given, show installed commitizen version - out.write(f"{__version__}") + return + + out.write(f"Project Version: {version}" if verbose else version) + return + + # if no argument is given, show installed commitizen version + out.write(f"{__version__}") diff --git a/commitizen/providers/commitizen_provider.py b/commitizen/providers/commitizen_provider.py index d9207b19ff..f90d7d9b6e 100644 --- a/commitizen/providers/commitizen_provider.py +++ b/commitizen/providers/commitizen_provider.py @@ -1,5 +1,6 @@ from __future__ import annotations +from commitizen.exceptions import NoVersionSpecifiedError from commitizen.providers.base_provider import VersionProvider @@ -9,7 +10,9 @@ class CommitizenProvider(VersionProvider): """ def get_version(self) -> str: - return self.config.settings["version"] # type: ignore[return-value] # TODO: check if we can fix this by tweaking the `Settings` type + if ret := self.config.settings["version"]: + return ret + raise NoVersionSpecifiedError() def set_version(self, version: str) -> None: self.config.set_key("version", version) From 908f29c8f99b8955160c08447fe40bb4adab2dbd Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 25 May 2025 17:46:33 +0800 Subject: [PATCH 018/221] docs(taplo): add toml formatter --- .taplo.toml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .taplo.toml diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 0000000000..36a3453ac9 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,4 @@ +include = ["pyproject.toml", ".taplo.toml"] + +[formatting] +indent_string = " " From f15b7186d2fd4df55794d86da92d77c92c2020d2 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 25 May 2025 20:25:49 +0800 Subject: [PATCH 019/221] docs(pre-commit): add taplo to pre-commit hook --- .pre-commit-config.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3dfd50ee68..46f6d04e34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: - id: debug-statements - id: no-commit-to-branch - id: check-merge-conflict - - id: check-toml + - id: check-toml # TOML linter (syntax checker) - id: check-yaml args: [ '--unsafe' ] # for mkdocs.yml - id: detect-private-key @@ -55,17 +55,22 @@ repos: stages: - post-commit + - repo: https://github.com/ComPWA/taplo-pre-commit + rev: v0.9.3 + hooks: + - id: taplo-format + - repo: local hooks: - id: format - name: Format + name: Format Python code via Poetry language: system pass_filenames: false entry: poetry format types: [ python ] - id: linter and test - name: Linters + name: Linters via Poetry language: system pass_filenames: false entry: poetry lint From 38397b26d24731c398859143335e228e04828782 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 13 Jun 2025 20:09:07 +0800 Subject: [PATCH 020/221] refactor(Changelog): remove unnecessary intermediate variables for better readability --- commitizen/commands/changelog.py | 36 +++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index 8668dd44c6..0fffd8ed7c 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -11,7 +11,6 @@ from commitizen import changelog, defaults, factory, git, out from commitizen.changelog_formats import get_changelog_format from commitizen.config import BaseConfig -from commitizen.cz.base import ChangelogReleaseHook, MessageBuilderHook from commitizen.cz.utils import strip_local_version from commitizen.exceptions import ( DryRunExit, @@ -188,15 +187,6 @@ def __call__(self) -> None: commit_parser = self.cz.commit_parser changelog_pattern = self.cz.changelog_pattern start_rev = self.start_rev - unreleased_version = self.unreleased_version - changelog_meta = changelog.Metadata() - change_type_map: dict[str, str] | None = self.change_type_map - changelog_message_builder_hook: MessageBuilderHook | None = ( - self.cz.changelog_message_builder_hook - ) - changelog_release_hook: ChangelogReleaseHook | None = ( - self.cz.changelog_release_hook - ) if self.export_template_to: return self._export_template(self.export_template_to) @@ -213,33 +203,37 @@ def __call__(self) -> None: assert self.file_name tags = self.tag_rules.get_version_tags(git.get_tags(), warn=True) - end_rev = "" + changelog_meta = changelog.Metadata() if self.incremental: changelog_meta = self.changelog_format.get_metadata(self.file_name) if changelog_meta.latest_version: start_rev = self._find_incremental_rev( strip_local_version(changelog_meta.latest_version_tag or ""), tags ) + + end_rev = "" if self.rev_range: start_rev, end_rev = changelog.get_oldest_and_newest_rev( tags, self.rev_range, self.tag_rules, ) + commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order") if not commits and ( self.current_version is None or not self.current_version.is_prerelease ): raise NoCommitsFoundError("No commits found") + tree = changelog.generate_tree_from_commits( commits, tags, commit_parser, changelog_pattern, - unreleased_version, - change_type_map=change_type_map, - changelog_message_builder_hook=changelog_message_builder_hook, - changelog_release_hook=changelog_release_hook, + self.unreleased_version, + change_type_map=self.change_type_map, + changelog_message_builder_hook=self.cz.changelog_message_builder_hook, + changelog_release_hook=self.cz.changelog_release_hook, rules=self.tag_rules, ) if self.change_type_order: @@ -247,11 +241,15 @@ def __call__(self) -> None: tree, self.change_type_order ) - extras = self.cz.template_extras.copy() - extras.update(self.config.settings["extras"]) - extras.update(self.extras) changelog_out = changelog.render_changelog( - tree, loader=self.cz.template_loader, template=self.template, **extras + tree, + self.cz.template_loader, + self.template, + **{ + **self.cz.template_extras, + **self.config.settings["extras"], + **self.extras, + }, ).lstrip("\n") # Dry_run is executed here to avoid checking and reading the files From 34a483658440b47c94d916528750feccf0dd2b63 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 17:52:46 +0800 Subject: [PATCH 021/221] refactor(changelog): shorten condition expression and early return --- commitizen/changelog.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/commitizen/changelog.py b/commitizen/changelog.py index ba6fbbc6b3..8721734af7 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -251,6 +251,7 @@ def incremental_build( unreleased_start = metadata.unreleased_start unreleased_end = metadata.unreleased_end latest_version_position = metadata.latest_version_position + skip = False output_lines: list[str] = [] for index, line in enumerate(lines): @@ -260,9 +261,7 @@ def incremental_build( skip = False if ( latest_version_position is None - or isinstance(latest_version_position, int) - and isinstance(unreleased_end, int) - and latest_version_position > unreleased_end + or latest_version_position > unreleased_end ): continue @@ -271,13 +270,15 @@ def incremental_build( if index == latest_version_position: output_lines.extend([new_content, "\n"]) - output_lines.append(line) - if not isinstance(latest_version_position, int): - if output_lines and output_lines[-1].strip(): - # Ensure at least one blank line between existing and new content. - output_lines.append("\n") - output_lines.append(new_content) + + if latest_version_position is not None: + return output_lines + + if output_lines and output_lines[-1].strip(): + # Ensure at least one blank line between existing and new content. + output_lines.append("\n") + output_lines.append(new_content) return output_lines From 14f7db52223f6efee4a96c628ae1f6ecc22bd168 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 11 Jun 2025 22:40:59 +0800 Subject: [PATCH 022/221] refactor(Init): extract _get_config_data for readability --- commitizen/commands/init.py | 45 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 356c4ce27d..c298ffec8b 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -79,6 +79,8 @@ def is_pre_commit_installed(self) -> bool: class Init: + _PRE_COMMIT_CONFIG_PATH = ".pre-commit-config.yaml" + def __init__(self, config: BaseConfig, *args: object) -> None: self.config: BaseConfig = config self.encoding = config.settings["encoding"] @@ -320,9 +322,8 @@ def _gen_pre_commit_cmd(self, hook_types: list[str]) -> str: f"--hook-type {ty}" for ty in hook_types ) - def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None: - pre_commit_config_filename = ".pre-commit-config.yaml" - cz_hook_config = { + def _get_config_data(self) -> dict[str, Any]: + CZ_HOOK_CONFIG = { "repo": "https://github.com/commitizen-tools/commitizen", "rev": f"v{__version__}", "hooks": [ @@ -331,31 +332,29 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None: ], } - config_data = {} if not self.project_info.has_pre_commit_config: # .pre-commit-config.yaml does not exist - config_data["repos"] = [cz_hook_config] + return {"repos": [CZ_HOOK_CONFIG]} + + with open(self._PRE_COMMIT_CONFIG_PATH, encoding=self.encoding) as config_file: + config_data: dict[str, Any] = yaml.safe_load(config_file) or {} + + if not isinstance(repos := config_data.get("repos"), list): + # .pre-commit-config.yaml exists but there's no "repos" key + config_data["repos"] = [CZ_HOOK_CONFIG] + return config_data + + # Check if commitizen pre-commit hook is already in the config + if any("commitizen" in hook_config["repo"] for hook_config in repos): + out.write("commitizen already in pre-commit config") else: - with open( - pre_commit_config_filename, encoding=self.encoding - ) as config_file: - yaml_data = yaml.safe_load(config_file) - if yaml_data: - config_data = yaml_data - - if "repos" in config_data: - for pre_commit_hook in config_data["repos"]: - if "commitizen" in pre_commit_hook["repo"]: - out.write("commitizen already in pre-commit config") - break - else: - config_data["repos"].append(cz_hook_config) - else: - # .pre-commit-config.yaml exists but there's no "repos" key - config_data["repos"] = [cz_hook_config] + repos.append(CZ_HOOK_CONFIG) + return config_data + def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None: + config_data = self._get_config_data() with smart_open( - pre_commit_config_filename, "w", encoding=self.encoding + self._PRE_COMMIT_CONFIG_PATH, "w", encoding=self.encoding ) as config_file: yaml.safe_dump(config_data, stream=config_file) From eca23bac01fca9a8b0b9221d004bc34370401f5c Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 20:32:51 +0800 Subject: [PATCH 023/221] refactor(process_commit_message): better type and early return --- commitizen/changelog.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/commitizen/changelog.py b/commitizen/changelog.py index 8721734af7..93b5339962 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -29,7 +29,7 @@ import re from collections import OrderedDict, defaultdict -from collections.abc import Generator, Iterable, Mapping, Sequence +from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence from dataclasses import dataclass from datetime import date from typing import TYPE_CHECKING, Any @@ -167,8 +167,8 @@ def process_commit_message( hook: MessageBuilderHook | None, parsed: re.Match[str], commit: GitCommit, - changes: dict[str | None, list], - change_type_map: dict[str, str] | None = None, + ref_changes: MutableMapping[str | None, list], + change_type_map: Mapping[str, str] | None = None, ) -> None: message: dict[str, Any] = { "sha1": commit.rev, @@ -178,13 +178,16 @@ def process_commit_message( **parsed.groupdict(), } - if processed := hook(message, commit) if hook else message: - messages = [processed] if isinstance(processed, dict) else processed - for msg in messages: - change_type = msg.pop("change_type", None) - if change_type_map: - change_type = change_type_map.get(change_type, change_type) - changes[change_type].append(msg) + processed_msg = hook(message, commit) if hook else message + if not processed_msg: + return + + messages = [processed_msg] if isinstance(processed_msg, dict) else processed_msg + for msg in messages: + change_type = msg.pop("change_type", None) + if change_type_map: + change_type = change_type_map.get(change_type, change_type) + ref_changes[change_type].append(msg) def generate_ordered_changelog_tree( From f92357a3b54f27ebdf5f2f1f0219b88f02154743 Mon Sep 17 00:00:00 2001 From: timsu92 <33785401+timsu92@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:13:11 +0800 Subject: [PATCH 024/221] refactor(init): remote extra words --- commitizen/commands/init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index c298ffec8b..8acc3ae5cb 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -238,7 +238,7 @@ def _ask_version_provider(self) -> str: "npm": "npm: Get and set version from package.json:project.version field", "pep621": "pep621: Get and set version from pyproject.toml:project.version field", "poetry": "poetry: Get and set version from pyproject.toml:tool.poetry.version field", - "uv": "uv: Get and Get and set version from pyproject.toml and uv.lock", + "uv": "uv: Get and set version from pyproject.toml and uv.lock", "scm": "scm: Fetch the version from git and does not need to set it back", } From 80f2812378f23d8a3dc57a9bff3815b65969ca15 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 12:25:24 +0800 Subject: [PATCH 025/221] refactor(Init): fix unbounded variable in _ask_tag_format --- commitizen/commands/init.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 8acc3ae5cb..eed7ff2d69 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -210,23 +210,20 @@ def _ask_tag(self) -> str: return latest_tag def _ask_tag_format(self, latest_tag: str) -> str: - is_correct_format = False if latest_tag.startswith("v"): - tag_format = r"v$version" - is_correct_format = questionary.confirm( - f'Is "{tag_format}" the correct tag format?', style=self.cz.style - ).unsafe_ask() + v_tag_format = r"v$version" + if questionary.confirm( + f'Is "{v_tag_format}" the correct tag format?', style=self.cz.style + ).unsafe_ask(): + return v_tag_format default_format = DEFAULT_SETTINGS["tag_format"] - if not is_correct_format: - tag_format = questionary.text( - f'Please enter the correct version format: (default: "{default_format}")', - style=self.cz.style, - ).unsafe_ask() + tag_format: str = questionary.text( + f'Please enter the correct version format: (default: "{default_format}")', + style=self.cz.style, + ).unsafe_ask() - if not tag_format: - tag_format = default_format - return tag_format + return tag_format or default_format def _ask_version_provider(self) -> str: """Ask for setting: version_provider""" From 07e78bcac775d67637bf87a6b4d345e62938c973 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 13:22:44 +0800 Subject: [PATCH 026/221] test(Init): improve coverage for _ask_tag_format --- tests/commands/test_init_command.py | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 3f12d0bd7f..2d39ae085e 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -255,6 +255,38 @@ def test_pre_commit_exec_failed( commands.Init(config)() +class TestAskTagFormat: + def test_confirm_v_tag_format(self, mocker: MockFixture, config): + init = commands.Init(config) + mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) + + result = init._ask_tag_format("v1.0.0") + assert result == r"v$version" + + def test_reject_v_tag_format(self, mocker: MockFixture, config): + init = commands.Init(config) + mocker.patch("questionary.confirm", return_value=FakeQuestion(False)) + mocker.patch("questionary.text", return_value=FakeQuestion("custom-$version")) + + result = init._ask_tag_format("v1.0.0") + assert result == "custom-$version" + + def test_non_v_tag_format(self, mocker: MockFixture, config): + init = commands.Init(config) + mocker.patch("questionary.text", return_value=FakeQuestion("custom-$version")) + + result = init._ask_tag_format("1.0.0") + assert result == "custom-$version" + + def test_empty_input_returns_default(self, mocker: MockFixture, config): + init = commands.Init(config) + mocker.patch("questionary.confirm", return_value=FakeQuestion(False)) + mocker.patch("questionary.text", return_value=FakeQuestion("")) + + result = init._ask_tag_format("v1.0.0") + assert result == "$version" # This is the default format from DEFAULT_SETTINGS + + @skip_below_py_3_10 def test_init_command_shows_description_when_use_help_option( mocker: MockFixture, capsys, file_regression From 263125330d3a02821220d9f49292d37b1a7585d8 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 22:17:06 +0800 Subject: [PATCH 027/221] fix(ExitCode): add from_str in ExitCode and replace parse_no_raise with it Warn if a given decimal string is not in range --- commitizen/cli.py | 25 ++++++++++++------------- commitizen/exceptions.py | 12 ++++++++++-- tests/test_exceptions.py | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 tests/test_exceptions.py diff --git a/commitizen/cli.py b/commitizen/cli.py index a73377fe45..3862b8843e 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -580,20 +580,19 @@ def parse_no_raise(comma_separated_no_raise: str) -> list[int]: Receives digits and strings and outputs the parsed integer which represents the exit code found in exceptions. """ - no_raise_items: list[str] = comma_separated_no_raise.split(",") - no_raise_codes: list[int] = [] - for item in no_raise_items: - if item.isdecimal(): - no_raise_codes.append(int(item)) - continue + + def exit_code_from_str_or_skip(s: str) -> ExitCode | None: try: - exit_code = ExitCode[item.strip()] - except KeyError: - out.warn(f"WARN: no_raise key `{item}` does not exist. Skipping.") - continue - else: - no_raise_codes.append(exit_code.value) - return no_raise_codes + return ExitCode.from_str(s) + except (KeyError, ValueError): + out.warn(f"WARN: no_raise value `{s}` is not a valid exit code. Skipping.") + return None + + return [ + code.value + for s in comma_separated_no_raise.split(",") + if (code := exit_code_from_str_or_skip(s)) is not None + ] if TYPE_CHECKING: diff --git a/commitizen/exceptions.py b/commitizen/exceptions.py index 8be792258a..75b0ab2fb7 100644 --- a/commitizen/exceptions.py +++ b/commitizen/exceptions.py @@ -1,10 +1,12 @@ -import enum +from __future__ import annotations + +from enum import IntEnum from typing import Any from commitizen import out -class ExitCode(enum.IntEnum): +class ExitCode(IntEnum): EXPECTED_EXIT = 0 NO_COMMITIZEN_FOUND = 1 NOT_A_GIT_PROJECT = 2 @@ -39,6 +41,12 @@ class ExitCode(enum.IntEnum): CONFIG_FILE_IS_EMPTY = 31 COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED = 32 + @classmethod + def from_str(cls, value: str) -> ExitCode: + if value.isdecimal(): + return cls(int(value)) + return cls[value.strip()] + class CommitizenException(Exception): def __init__(self, *args: str, **kwargs: Any) -> None: diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py new file mode 100644 index 0000000000..1a66c79d02 --- /dev/null +++ b/tests/test_exceptions.py @@ -0,0 +1,38 @@ +import pytest + +from commitizen.exceptions import ExitCode + + +def test_from_str_with_decimal(): + """Test from_str with decimal values.""" + assert ExitCode.from_str("0") == ExitCode.EXPECTED_EXIT + assert ExitCode.from_str("1") == ExitCode.NO_COMMITIZEN_FOUND + assert ExitCode.from_str("32") == ExitCode.COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED + + +def test_from_str_with_enum_name(): + """Test from_str with enum names.""" + assert ExitCode.from_str("EXPECTED_EXIT") == ExitCode.EXPECTED_EXIT + assert ExitCode.from_str("NO_COMMITIZEN_FOUND") == ExitCode.NO_COMMITIZEN_FOUND + assert ( + ExitCode.from_str("COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED") + == ExitCode.COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED + ) + + +def test_from_str_with_whitespace(): + """Test from_str with whitespace in enum names.""" + assert ExitCode.from_str(" EXPECTED_EXIT ") == ExitCode.EXPECTED_EXIT + assert ExitCode.from_str("\tNO_COMMITIZEN_FOUND\t") == ExitCode.NO_COMMITIZEN_FOUND + + +def test_from_str_with_invalid_values(): + """Test from_str with invalid values.""" + with pytest.raises(KeyError): + ExitCode.from_str("invalid_name") + with pytest.raises(ValueError): + ExitCode.from_str("999") # Out of range decimal + with pytest.raises(KeyError): + ExitCode.from_str("") + with pytest.raises(KeyError): + ExitCode.from_str(" ") From 2cd0f88bd7faf8d137d708bee96a8f3ad8ec687b Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 12:05:16 +0800 Subject: [PATCH 028/221] fix(Init): fix a typo in _ask_version_provider options and remove unnecessary filter, use named tuple for options --- commitizen/commands/init.py | 105 ++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 35 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index eed7ff2d69..33be58544a 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -2,7 +2,7 @@ import os import shutil -from typing import Any +from typing import Any, NamedTuple import questionary import yaml @@ -17,6 +17,54 @@ from commitizen.version_schemes import KNOWN_SCHEMES, Version, get_version_scheme +class _VersionProviderOption(NamedTuple): + provider_name: str + description: str + + @property + def title(self) -> str: + return f"{self.provider_name}: {self.description}" + + +_VERSION_PROVIDER_CHOICES = tuple( + questionary.Choice(title=option.title, value=option.provider_name) + for option in ( + _VersionProviderOption( + provider_name="commitizen", + description="Fetch and set version in commitizen config (default)", + ), + _VersionProviderOption( + provider_name="cargo", + description="Get and set version from Cargo.toml:project.version field", + ), + _VersionProviderOption( + provider_name="composer", + description="Get and set version from composer.json:project.version field", + ), + _VersionProviderOption( + provider_name="npm", + description="Get and set version from package.json:project.version field", + ), + _VersionProviderOption( + provider_name="pep621", + description="Get and set version from pyproject.toml:project.version field", + ), + _VersionProviderOption( + provider_name="poetry", + description="Get and set version from pyproject.toml:tool.poetry.version field", + ), + _VersionProviderOption( + provider_name="uv", + description="Get and set version from pyproject.toml and uv.lock", + ), + _VersionProviderOption( + provider_name="scm", + description="Fetch the version from git and does not need to set it back", + ), + ) +) + + class ProjectInfo: """Discover information about the current folder.""" @@ -228,45 +276,32 @@ def _ask_tag_format(self, latest_tag: str) -> str: def _ask_version_provider(self) -> str: """Ask for setting: version_provider""" - OPTS = { - "commitizen": "commitizen: Fetch and set version in commitizen config (default)", - "cargo": "cargo: Get and set version from Cargo.toml:project.version field", - "composer": "composer: Get and set version from composer.json:project.version field", - "npm": "npm: Get and set version from package.json:project.version field", - "pep621": "pep621: Get and set version from pyproject.toml:project.version field", - "poetry": "poetry: Get and set version from pyproject.toml:tool.poetry.version field", - "uv": "uv: Get and set version from pyproject.toml and uv.lock", - "scm": "scm: Fetch the version from git and does not need to set it back", - } - - default_val = "commitizen" - if self.project_info.is_python: - if self.project_info.is_python_poetry: - default_val = "poetry" - elif self.project_info.is_python_uv: - default_val = "uv" - else: - default_val = "pep621" - elif self.project_info.is_rust_cargo: - default_val = "cargo" - elif self.project_info.is_npm_package: - default_val = "npm" - elif self.project_info.is_php_composer: - default_val = "composer" - - choices = [ - questionary.Choice(title=title, value=value) - for value, title in OPTS.items() - ] - default = next(filter(lambda x: x.value == default_val, choices)) version_provider: str = questionary.select( "Choose the source of the version:", - choices=choices, + choices=_VERSION_PROVIDER_CHOICES, style=self.cz.style, - default=default, + default=self._default_version_provider, ).unsafe_ask() return version_provider + @property + def _default_version_provider(self) -> str: + if self.project_info.is_python: + if self.project_info.is_python_poetry: + return "poetry" + if self.project_info.is_python_uv: + return "uv" + return "pep621" + + if self.project_info.is_rust_cargo: + return "cargo" + if self.project_info.is_npm_package: + return "npm" + if self.project_info.is_php_composer: + return "composer" + + return "commitizen" + def _ask_version_scheme(self) -> str: """Ask for setting: version_scheme""" default_scheme = "pep440" if self.project_info.is_python else "semver" @@ -291,7 +326,7 @@ def _ask_major_version_zero(self, version: Version) -> bool: return major_version_zero def _ask_update_changelog_on_bump(self) -> bool: - "Ask for setting: update_changelog_on_bump" + """Ask for setting: update_changelog_on_bump""" update_changelog_on_bump: bool = questionary.confirm( "Create changelog automatically on bump", default=True, From 1b39ae41571b8c2b710725e22e89ffed33dc324d Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 00:51:31 +0800 Subject: [PATCH 029/221] fix(init): make welcome message easier to read --- commitizen/commands/init.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 33be58544a..0f19786d0b 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -142,8 +142,8 @@ def __call__(self) -> None: out.info("Welcome to commitizen!\n") out.line( - "Answer the questions to configure your project.\n" - "For further configuration visit:\n" + "Answer the following questions to configure your project.\n" + "For further configuration, visit:\n" "\n" "https://commitizen-tools.github.io/commitizen/config/" "\n" From 78b1fb12ecad52f8b4c3639d070229b443ac5de0 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 11:37:15 +0800 Subject: [PATCH 030/221] refactor(Init): remove unnecessary methods from ProjectInfo and refactor _ask_tag --- commitizen/commands/init.py | 49 +++++++++++++++---------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 0f19786d0b..4b5649b670 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -111,16 +111,6 @@ def is_npm_package(self) -> bool: def is_php_composer(self) -> bool: return os.path.isfile("composer.json") - @property - def latest_tag(self) -> str | None: - return get_latest_tag_name() - - def tags(self) -> list | None: - """Not a property, only use if necessary""" - if self.latest_tag is None: - return None - return get_tag_names() - @property def is_pre_commit_installed(self) -> bool: return bool(shutil.which("pre-commit")) @@ -231,31 +221,32 @@ def _ask_name(self) -> str: return name def _ask_tag(self) -> str: - latest_tag = self.project_info.latest_tag + latest_tag = get_latest_tag_name() if not latest_tag: out.error("No Existing Tag. Set tag to v0.0.1") return "0.0.1" - is_correct_tag = questionary.confirm( + if questionary.confirm( f"Is {latest_tag} the latest tag?", style=self.cz.style, default=False + ).unsafe_ask(): + return latest_tag + + existing_tags = get_tag_names() + if not existing_tags: + out.error("No Existing Tag. Set tag to v0.0.1") + return "0.0.1" + + answer: str = questionary.select( + "Please choose the latest tag: ", + # The latest tag is most likely with the largest number. + # Thus, listing the existing_tags in reverse order makes more sense. + choices=sorted(existing_tags, reverse=True), + style=self.cz.style, ).unsafe_ask() - if not is_correct_tag: - tags = self.project_info.tags() - if not tags: - out.error("No Existing Tag. Set tag to v0.0.1") - return "0.0.1" - - # the latest tag is most likely with the largest number. Thus list the tags in reverse order makes more sense - sorted_tags = sorted(tags, reverse=True) - latest_tag = questionary.select( - "Please choose the latest tag: ", - choices=sorted_tags, - style=self.cz.style, - ).unsafe_ask() - - if not latest_tag: - raise NoAnswersError("Tag is required!") - return latest_tag + + if not answer: + raise NoAnswersError("Tag is required!") + return answer def _ask_tag_format(self, latest_tag: str) -> str: if latest_tag.startswith("v"): From 4ca11909927def4aaa60d1cbab3abd93280a2855 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 10 Jun 2025 11:51:03 +0800 Subject: [PATCH 031/221] test(Init): cover _ask_tag test --- tests/commands/test_init_command.py | 122 ++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 2d39ae085e..7feaf18ef2 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -298,3 +298,125 @@ def test_init_command_shows_description_when_use_help_option( out, _ = capsys.readouterr() file_regression.check(out, extension=".txt") + + +def test_init_with_confirmed_tag_format(config, mocker: MockFixture, tmpdir): + mocker.patch( + "commitizen.commands.init.get_tag_names", return_value=["v0.0.2", "v0.0.1"] + ) + mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v0.0.2") + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), + FakeQuestion("cz_conventional_commits"), + FakeQuestion("commitizen"), + FakeQuestion("semver"), + ], + ) + mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + with open("pyproject.toml", encoding="utf-8") as toml_file: + assert 'tag_format = "v$version"' in toml_file.read() + + +def test_init_with_no_existing_tags(config, mocker: MockFixture, tmpdir): + mocker.patch("commitizen.commands.init.get_tag_names", return_value=[]) + mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v1.0.0") + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), + FakeQuestion("cz_conventional_commits"), + FakeQuestion("commitizen"), + FakeQuestion("semver"), + ], + ) + mocker.patch("questionary.confirm", return_value=FakeQuestion(False)) + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + with open("pyproject.toml", encoding="utf-8") as toml_file: + assert 'version = "0.0.1"' in toml_file.read() + + +def test_init_with_no_existing_latest_tag(config, mocker: MockFixture, tmpdir): + mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value=None) + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), + FakeQuestion("cz_conventional_commits"), + FakeQuestion("commitizen"), + FakeQuestion("semver"), + ], + ) + mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + with open("pyproject.toml", encoding="utf-8") as toml_file: + assert 'version = "0.0.1"' in toml_file.read() + + +def test_init_with_existing_tags(config, mocker: MockFixture, tmpdir): + expected_tags = ["v1.0.0", "v0.9.0", "v0.8.0"] + mocker.patch("commitizen.commands.init.get_tag_names", return_value=expected_tags) + mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v1.0.0") + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), + FakeQuestion("cz_conventional_commits"), + FakeQuestion("commitizen"), + FakeQuestion("semver"), # Select version scheme first + FakeQuestion("v1.0.0"), # Then select the latest tag + ], + ) + mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + with open("pyproject.toml", encoding="utf-8") as toml_file: + assert 'version = "1.0.0"' in toml_file.read() + + +def test_init_with_valid_tag_selection(config, mocker: MockFixture, tmpdir): + expected_tags = ["v1.0.0", "v0.9.0", "v0.8.0"] + mocker.patch("commitizen.commands.init.get_tag_names", return_value=expected_tags) + mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v1.0.0") + + # Mock all questionary.select calls in the exact order they appear in Init.__call__ + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), # _ask_config_path + FakeQuestion("cz_conventional_commits"), # _ask_name + FakeQuestion("commitizen"), # _ask_version_provider + FakeQuestion("v0.9.0"), # _ask_tag (after confirm=False) + FakeQuestion("semver"), # _ask_version_scheme + ], + ) + + mocker.patch( + "questionary.confirm", return_value=FakeQuestion(False) + ) # Don't confirm latest tag + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + with open("pyproject.toml", encoding="utf-8") as toml_file: + content = toml_file.read() + assert 'version = "0.9.0"' in content + assert 'version_scheme = "semver"' in content From 4cbf48518daf11e9d6cb55bef0ae783605c96f70 Mon Sep 17 00:00:00 2001 From: timsu92 <33785401+timsu92@users.noreply.github.com> Date: Wed, 6 Aug 2025 20:49:58 +0800 Subject: [PATCH 032/221] fix(init): use pre-push as pre-commit stage Original "push" stage has been deprecated since pre-commit v3.2.0. See https://github.com/pre-commit/pre-commit/issues/2732 and https://github.com/pre-commit/pre-commit/pull/2808 for detailed information. --- .pre-commit-hooks.yaml | 2 +- commitizen/commands/init.py | 2 +- poetry.lock | 784 ++++++++++++++++++------------------ pyproject.toml | 2 +- 4 files changed, 401 insertions(+), 389 deletions(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 2a3a088484..c142634581 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -24,4 +24,4 @@ pass_filenames: false language: python language_version: python3 - minimum_pre_commit_version: "1.4.3" + minimum_pre_commit_version: "3.2.0" diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 4b5649b670..a6efe0acc0 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -351,7 +351,7 @@ def _get_config_data(self) -> dict[str, Any]: "rev": f"v{__version__}", "hooks": [ {"id": "commitizen"}, - {"id": "commitizen-branch", "stages": ["push"]}, + {"id": "commitizen-branch", "stages": ["pre-push"]}, ], } diff --git a/poetry.lock b/poetry.lock index f8fb9aa803..829789632f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -48,18 +48,19 @@ dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)" [[package]] name = "backrefs" -version = "5.8" +version = "5.9" description = "A wrapper around re and regex that adds additional back references." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "backrefs-5.8-py310-none-any.whl", hash = "sha256:c67f6638a34a5b8730812f5101376f9d41dc38c43f1fdc35cb54700f6ed4465d"}, - {file = "backrefs-5.8-py311-none-any.whl", hash = "sha256:2e1c15e4af0e12e45c8701bd5da0902d326b2e200cafcd25e49d9f06d44bb61b"}, - {file = "backrefs-5.8-py312-none-any.whl", hash = "sha256:bbef7169a33811080d67cdf1538c8289f76f0942ff971222a16034da88a73486"}, - {file = "backrefs-5.8-py313-none-any.whl", hash = "sha256:e3a63b073867dbefd0536425f43db618578528e3896fb77be7141328642a1585"}, - {file = "backrefs-5.8-py39-none-any.whl", hash = "sha256:a66851e4533fb5b371aa0628e1fee1af05135616b86140c9d787a2ffdf4b8fdc"}, - {file = "backrefs-5.8.tar.gz", hash = "sha256:2cab642a205ce966af3dd4b38ee36009b31fa9502a35fd61d59ccc116e40a6bd"}, + {file = "backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f"}, + {file = "backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf"}, + {file = "backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa"}, + {file = "backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b"}, + {file = "backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9"}, + {file = "backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60"}, + {file = "backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59"}, ] [package.extras] @@ -67,26 +68,26 @@ extras = ["regex"] [[package]] name = "cachetools" -version = "6.0.0" +version = "6.2.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "cachetools-6.0.0-py3-none-any.whl", hash = "sha256:82e73ba88f7b30228b5507dce1a1f878498fc669d972aef2dde4f3a3c24f103e"}, - {file = "cachetools-6.0.0.tar.gz", hash = "sha256:f225782b84438f828328fc2ad74346522f27e5b1440f4e9fd18b20ebfd1aa2cf"}, + {file = "cachetools-6.2.0-py3-none-any.whl", hash = "sha256:1c76a8960c0041fcc21097e357f882197c79da0dbff766e7317890a65d7d8ba6"}, + {file = "cachetools-6.2.0.tar.gz", hash = "sha256:38b328c0889450f05f5e120f56ab68c8abaf424e1275522b138ffc93253f7e32"}, ] [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" groups = ["documentation"] files = [ - {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, - {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, ] [[package]] @@ -115,104 +116,91 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.4.2" +version = "3.4.3" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["main", "documentation"] files = [ - {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, - {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, - {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, + {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, + {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, ] [[package]] @@ -244,79 +232,100 @@ files = [ [[package]] name = "coverage" -version = "7.8.2" +version = "7.10.5" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, - {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, - {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, - {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, - {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, - {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, - {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, - {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, - {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, - {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, - {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, - {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, - {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, - {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, - {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, - {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, - {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, - {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, - {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, - {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, - {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, - {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, - {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, - {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, - {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, - {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, - {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, - {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, - {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, - {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, - {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, - {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, - {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, - {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, - {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, - {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, - {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, - {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, - {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, - {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, - {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, - {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, - {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, - {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, - {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, - {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, - {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, - {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, - {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, - {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, - {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, - {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, - {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, - {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, - {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, - {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, - {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, - {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, - {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, - {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, - {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, - {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, - {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, - {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, - {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, - {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, - {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, + {file = "coverage-7.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c6a5c3414bfc7451b879141ce772c546985163cf553f08e0f135f0699a911801"}, + {file = "coverage-7.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bc8e4d99ce82f1710cc3c125adc30fd1487d3cf6c2cd4994d78d68a47b16989a"}, + {file = "coverage-7.10.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:02252dc1216e512a9311f596b3169fad54abcb13827a8d76d5630c798a50a754"}, + {file = "coverage-7.10.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:73269df37883e02d460bee0cc16be90509faea1e3bd105d77360b512d5bb9c33"}, + {file = "coverage-7.10.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f8a81b0614642f91c9effd53eec284f965577591f51f547a1cbeb32035b4c2f"}, + {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6a29f8e0adb7f8c2b95fa2d4566a1d6e6722e0a637634c6563cb1ab844427dd9"}, + {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fcf6ab569436b4a647d4e91accba12509ad9f2554bc93d3aee23cc596e7f99c3"}, + {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:90dc3d6fb222b194a5de60af8d190bedeeddcbc7add317e4a3cd333ee6b7c879"}, + {file = "coverage-7.10.5-cp310-cp310-win32.whl", hash = "sha256:414a568cd545f9dc75f0686a0049393de8098414b58ea071e03395505b73d7a8"}, + {file = "coverage-7.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:e551f9d03347196271935fd3c0c165f0e8c049220280c1120de0084d65e9c7ff"}, + {file = "coverage-7.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c177e6ffe2ebc7c410785307758ee21258aa8e8092b44d09a2da767834f075f2"}, + {file = "coverage-7.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:14d6071c51ad0f703d6440827eaa46386169b5fdced42631d5a5ac419616046f"}, + {file = "coverage-7.10.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:61f78c7c3bc272a410c5ae3fde7792b4ffb4acc03d35a7df73ca8978826bb7ab"}, + {file = "coverage-7.10.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f39071caa126f69d63f99b324fb08c7b1da2ec28cbb1fe7b5b1799926492f65c"}, + {file = "coverage-7.10.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343a023193f04d46edc46b2616cdbee68c94dd10208ecd3adc56fcc54ef2baa1"}, + {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:585ffe93ae5894d1ebdee69fc0b0d4b7c75d8007983692fb300ac98eed146f78"}, + {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0ef4e66f006ed181df29b59921bd8fc7ed7cd6a9289295cd8b2824b49b570df"}, + {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb7b0bbf7cc1d0453b843eca7b5fa017874735bef9bfdfa4121373d2cc885ed6"}, + {file = "coverage-7.10.5-cp311-cp311-win32.whl", hash = "sha256:1d043a8a06987cc0c98516e57c4d3fc2c1591364831e9deb59c9e1b4937e8caf"}, + {file = "coverage-7.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:fefafcca09c3ac56372ef64a40f5fe17c5592fab906e0fdffd09543f3012ba50"}, + {file = "coverage-7.10.5-cp311-cp311-win_arm64.whl", hash = "sha256:7e78b767da8b5fc5b2faa69bb001edafcd6f3995b42a331c53ef9572c55ceb82"}, + {file = "coverage-7.10.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c2d05c7e73c60a4cecc7d9b60dbfd603b4ebc0adafaef371445b47d0f805c8a9"}, + {file = "coverage-7.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32ddaa3b2c509778ed5373b177eb2bf5662405493baeff52278a0b4f9415188b"}, + {file = "coverage-7.10.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dd382410039fe062097aa0292ab6335a3f1e7af7bba2ef8d27dcda484918f20c"}, + {file = "coverage-7.10.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7fa22800f3908df31cea6fb230f20ac49e343515d968cc3a42b30d5c3ebf9b5a"}, + {file = "coverage-7.10.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f366a57ac81f5e12797136552f5b7502fa053c861a009b91b80ed51f2ce651c6"}, + {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1dc8f1980a272ad4a6c84cba7981792344dad33bf5869361576b7aef42733a"}, + {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2285c04ee8676f7938b02b4936d9b9b672064daab3187c20f73a55f3d70e6b4a"}, + {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2492e4dd9daab63f5f56286f8a04c51323d237631eb98505d87e4c4ff19ec34"}, + {file = "coverage-7.10.5-cp312-cp312-win32.whl", hash = "sha256:38a9109c4ee8135d5df5505384fc2f20287a47ccbe0b3f04c53c9a1989c2bbaf"}, + {file = "coverage-7.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:6b87f1ad60b30bc3c43c66afa7db6b22a3109902e28c5094957626a0143a001f"}, + {file = "coverage-7.10.5-cp312-cp312-win_arm64.whl", hash = "sha256:672a6c1da5aea6c629819a0e1461e89d244f78d7b60c424ecf4f1f2556c041d8"}, + {file = "coverage-7.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ef3b83594d933020f54cf65ea1f4405d1f4e41a009c46df629dd964fcb6e907c"}, + {file = "coverage-7.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b96bfdf7c0ea9faebce088a3ecb2382819da4fbc05c7b80040dbc428df6af44"}, + {file = "coverage-7.10.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:63df1fdaffa42d914d5c4d293e838937638bf75c794cf20bee12978fc8c4e3bc"}, + {file = "coverage-7.10.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8002dc6a049aac0e81ecec97abfb08c01ef0c1fbf962d0c98da3950ace89b869"}, + {file = "coverage-7.10.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:63d4bb2966d6f5f705a6b0c6784c8969c468dbc4bcf9d9ded8bff1c7e092451f"}, + {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1f672efc0731a6846b157389b6e6d5d5e9e59d1d1a23a5c66a99fd58339914d5"}, + {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3f39cef43d08049e8afc1fde4a5da8510fc6be843f8dea350ee46e2a26b2f54c"}, + {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2968647e3ed5a6c019a419264386b013979ff1fb67dd11f5c9886c43d6a31fc2"}, + {file = "coverage-7.10.5-cp313-cp313-win32.whl", hash = "sha256:0d511dda38595b2b6934c2b730a1fd57a3635c6aa2a04cb74714cdfdd53846f4"}, + {file = "coverage-7.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:9a86281794a393513cf117177fd39c796b3f8e3759bb2764259a2abba5cce54b"}, + {file = "coverage-7.10.5-cp313-cp313-win_arm64.whl", hash = "sha256:cebd8e906eb98bb09c10d1feed16096700b1198d482267f8bf0474e63a7b8d84"}, + {file = "coverage-7.10.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0520dff502da5e09d0d20781df74d8189ab334a1e40d5bafe2efaa4158e2d9e7"}, + {file = "coverage-7.10.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d9cd64aca68f503ed3f1f18c7c9174cbb797baba02ca8ab5112f9d1c0328cd4b"}, + {file = "coverage-7.10.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0913dd1613a33b13c4f84aa6e3f4198c1a21ee28ccb4f674985c1f22109f0aae"}, + {file = "coverage-7.10.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1b7181c0feeb06ed8a02da02792f42f829a7b29990fef52eff257fef0885d760"}, + {file = "coverage-7.10.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36d42b7396b605f774d4372dd9c49bed71cbabce4ae1ccd074d155709dd8f235"}, + {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b4fdc777e05c4940b297bf47bf7eedd56a39a61dc23ba798e4b830d585486ca5"}, + {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:42144e8e346de44a6f1dbd0a56575dd8ab8dfa7e9007da02ea5b1c30ab33a7db"}, + {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:66c644cbd7aed8fe266d5917e2c9f65458a51cfe5eeff9c05f15b335f697066e"}, + {file = "coverage-7.10.5-cp313-cp313t-win32.whl", hash = "sha256:2d1b73023854068c44b0c554578a4e1ef1b050ed07cf8b431549e624a29a66ee"}, + {file = "coverage-7.10.5-cp313-cp313t-win_amd64.whl", hash = "sha256:54a1532c8a642d8cc0bd5a9a51f5a9dcc440294fd06e9dda55e743c5ec1a8f14"}, + {file = "coverage-7.10.5-cp313-cp313t-win_arm64.whl", hash = "sha256:74d5b63fe3f5f5d372253a4ef92492c11a4305f3550631beaa432fc9df16fcff"}, + {file = "coverage-7.10.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:68c5e0bc5f44f68053369fa0d94459c84548a77660a5f2561c5e5f1e3bed7031"}, + {file = "coverage-7.10.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cf33134ffae93865e32e1e37df043bef15a5e857d8caebc0099d225c579b0fa3"}, + {file = "coverage-7.10.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ad8fa9d5193bafcf668231294241302b5e683a0518bf1e33a9a0dfb142ec3031"}, + {file = "coverage-7.10.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:146fa1531973d38ab4b689bc764592fe6c2f913e7e80a39e7eeafd11f0ef6db2"}, + {file = "coverage-7.10.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6013a37b8a4854c478d3219ee8bc2392dea51602dd0803a12d6f6182a0061762"}, + {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:eb90fe20db9c3d930fa2ad7a308207ab5b86bf6a76f54ab6a40be4012d88fcae"}, + {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:384b34482272e960c438703cafe63316dfbea124ac62006a455c8410bf2a2262"}, + {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:467dc74bd0a1a7de2bedf8deaf6811f43602cb532bd34d81ffd6038d6d8abe99"}, + {file = "coverage-7.10.5-cp314-cp314-win32.whl", hash = "sha256:556d23d4e6393ca898b2e63a5bca91e9ac2d5fb13299ec286cd69a09a7187fde"}, + {file = "coverage-7.10.5-cp314-cp314-win_amd64.whl", hash = "sha256:f4446a9547681533c8fa3e3c6cf62121eeee616e6a92bd9201c6edd91beffe13"}, + {file = "coverage-7.10.5-cp314-cp314-win_arm64.whl", hash = "sha256:5e78bd9cf65da4c303bf663de0d73bf69f81e878bf72a94e9af67137c69b9fe9"}, + {file = "coverage-7.10.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5661bf987d91ec756a47c7e5df4fbcb949f39e32f9334ccd3f43233bbb65e508"}, + {file = "coverage-7.10.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a46473129244db42a720439a26984f8c6f834762fc4573616c1f37f13994b357"}, + {file = "coverage-7.10.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1f64b8d3415d60f24b058b58d859e9512624bdfa57a2d1f8aff93c1ec45c429b"}, + {file = "coverage-7.10.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:44d43de99a9d90b20e0163f9770542357f58860a26e24dc1d924643bd6aa7cb4"}, + {file = "coverage-7.10.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a931a87e5ddb6b6404e65443b742cb1c14959622777f2a4efd81fba84f5d91ba"}, + {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9559b906a100029274448f4c8b8b0a127daa4dade5661dfd821b8c188058842"}, + {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b08801e25e3b4526ef9ced1aa29344131a8f5213c60c03c18fe4c6170ffa2874"}, + {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ed9749bb8eda35f8b636fb7632f1c62f735a236a5d4edadd8bbcc5ea0542e732"}, + {file = "coverage-7.10.5-cp314-cp314t-win32.whl", hash = "sha256:609b60d123fc2cc63ccee6d17e4676699075db72d14ac3c107cc4976d516f2df"}, + {file = "coverage-7.10.5-cp314-cp314t-win_amd64.whl", hash = "sha256:0666cf3d2c1626b5a3463fd5b05f5e21f99e6aec40a3192eee4d07a15970b07f"}, + {file = "coverage-7.10.5-cp314-cp314t-win_arm64.whl", hash = "sha256:bc85eb2d35e760120540afddd3044a5bf69118a91a296a8b3940dfc4fdcfe1e2"}, + {file = "coverage-7.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:62835c1b00c4a4ace24c1a88561a5a59b612fbb83a525d1c70ff5720c97c0610"}, + {file = "coverage-7.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5255b3bbcc1d32a4069d6403820ac8e6dbcc1d68cb28a60a1ebf17e47028e898"}, + {file = "coverage-7.10.5-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3876385722e335d6e991c430302c24251ef9c2a9701b2b390f5473199b1b8ebf"}, + {file = "coverage-7.10.5-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8048ce4b149c93447a55d279078c8ae98b08a6951a3c4d2d7e87f4efc7bfe100"}, + {file = "coverage-7.10.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4028e7558e268dd8bcf4d9484aad393cafa654c24b4885f6f9474bf53183a82a"}, + {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:03f47dc870eec0367fcdd603ca6a01517d2504e83dc18dbfafae37faec66129a"}, + {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2d488d7d42b6ded7ea0704884f89dcabd2619505457de8fc9a6011c62106f6e5"}, + {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b3dcf2ead47fa8be14224ee817dfc1df98043af568fe120a22f81c0eb3c34ad2"}, + {file = "coverage-7.10.5-cp39-cp39-win32.whl", hash = "sha256:02650a11324b80057b8c9c29487020073d5e98a498f1857f37e3f9b6ea1b2426"}, + {file = "coverage-7.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:b45264dd450a10f9e03237b41a9a24e85cbb1e278e5a32adb1a303f58f0017f3"}, + {file = "coverage-7.10.5-py3-none-any.whl", hash = "sha256:0be24d35e4db1d23d0db5c0f6a74a962e2ec83c426b5cac09f4234aadef38e4a"}, + {file = "coverage-7.10.5.tar.gz", hash = "sha256:f2e57716a78bc3ae80b2207be0709a3b2b63b9f2dcf9740ee6ac03588a2015b6"}, ] [package.dependencies] @@ -369,14 +378,14 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version [[package]] name = "distlib" -version = "0.3.9" +version = "0.4.0" description = "Distribution utilities" optional = false python-versions = "*" groups = ["dev", "linters"] files = [ - {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, - {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, + {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, + {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, ] [[package]] @@ -430,31 +439,26 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "filelock" -version = "3.18.0" +version = "3.19.1" description = "A platform independent file lock." optional = false python-versions = ">=3.9" groups = ["dev", "linters"] files = [ - {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, - {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, + {file = "filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"}, + {file = "filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58"}, ] -[package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] - [[package]] name = "freezegun" -version = "1.5.2" +version = "1.5.5" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.8" groups = ["test"] files = [ - {file = "freezegun-1.5.2-py3-none-any.whl", hash = "sha256:5aaf3ba229cda57afab5bd311f0108d86b6fb119ae89d2cd9c43ec8c1733c85b"}, - {file = "freezegun-1.5.2.tar.gz", hash = "sha256:a54ae1d2f9c02dbf42e02c18a3ab95ab4295818b549a34dac55592d72a905181"}, + {file = "freezegun-1.5.5-py3-none-any.whl", hash = "sha256:cd557f4a75cf074e84bc374249b9dd491eaeacd61376b9eb3c423282211619d2"}, + {file = "freezegun-1.5.5.tar.gz", hash = "sha256:ac7742a6cc6c25a2c35e9292dfd554b897b517d2dec26891a2e8debf205cb94a"}, ] [package.dependencies] @@ -480,14 +484,14 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "identify" -version = "2.6.12" +version = "2.6.13" description = "File identification library for Python" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2"}, - {file = "identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6"}, + {file = "identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b"}, + {file = "identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32"}, ] [package.extras] @@ -623,14 +627,14 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "markdown" -version = "3.8" +version = "3.8.2" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc"}, - {file = "markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"}, + {file = "markdown-3.8.2-py3-none-any.whl", hash = "sha256:5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24"}, + {file = "markdown-3.8.2.tar.gz", hash = "sha256:247b9a70dd12e27f67431ce62523e675b866d254f900c4fe75ce3dda62237c45"}, ] [package.dependencies] @@ -827,19 +831,20 @@ pyyaml = ">=5.1" [[package]] name = "mkdocs-material" -version = "9.6.14" +version = "9.6.18" description = "Documentation that simply works" optional = false python-versions = ">=3.8" groups = ["documentation"] files = [ - {file = "mkdocs_material-9.6.14-py3-none-any.whl", hash = "sha256:3b9cee6d3688551bf7a8e8f41afda97a3c39a12f0325436d76c86706114b721b"}, - {file = "mkdocs_material-9.6.14.tar.gz", hash = "sha256:39d795e90dce6b531387c255bd07e866e027828b7346d3eba5ac3de265053754"}, + {file = "mkdocs_material-9.6.18-py3-none-any.whl", hash = "sha256:dbc1e146a0ecce951a4d84f97b816a54936cdc9e1edd1667fc6868878ac06701"}, + {file = "mkdocs_material-9.6.18.tar.gz", hash = "sha256:a2eb253bcc8b66f8c6eaf8379c10ed6e9644090c2e2e9d0971c7722dc7211c05"}, ] [package.dependencies] babel = ">=2.10,<3.0" backrefs = ">=5.7.post1,<6.0" +click = "<8.2.2" colorama = ">=0.4,<1.0" jinja2 = ">=3.1,<4.0" markdown = ">=3.2,<4.0" @@ -869,44 +874,50 @@ files = [ [[package]] name = "mypy" -version = "1.16.0" +version = "1.17.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c"}, - {file = "mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571"}, - {file = "mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491"}, - {file = "mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777"}, - {file = "mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b"}, - {file = "mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93"}, - {file = "mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab"}, - {file = "mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2"}, - {file = "mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff"}, - {file = "mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666"}, - {file = "mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c"}, - {file = "mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b"}, - {file = "mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13"}, - {file = "mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090"}, - {file = "mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1"}, - {file = "mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8"}, - {file = "mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730"}, - {file = "mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec"}, - {file = "mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b"}, - {file = "mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0"}, - {file = "mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b"}, - {file = "mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d"}, - {file = "mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52"}, - {file = "mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb"}, - {file = "mypy-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3"}, - {file = "mypy-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92"}, - {file = "mypy-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436"}, - {file = "mypy-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2"}, - {file = "mypy-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20"}, - {file = "mypy-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21"}, - {file = "mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031"}, - {file = "mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab"}, + {file = "mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972"}, + {file = "mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7"}, + {file = "mypy-1.17.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df"}, + {file = "mypy-1.17.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390"}, + {file = "mypy-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94"}, + {file = "mypy-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b"}, + {file = "mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58"}, + {file = "mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5"}, + {file = "mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd"}, + {file = "mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b"}, + {file = "mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5"}, + {file = "mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b"}, + {file = "mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb"}, + {file = "mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403"}, + {file = "mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056"}, + {file = "mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341"}, + {file = "mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb"}, + {file = "mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19"}, + {file = "mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7"}, + {file = "mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81"}, + {file = "mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6"}, + {file = "mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849"}, + {file = "mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14"}, + {file = "mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a"}, + {file = "mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733"}, + {file = "mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd"}, + {file = "mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0"}, + {file = "mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a"}, + {file = "mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91"}, + {file = "mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed"}, + {file = "mypy-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9"}, + {file = "mypy-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99"}, + {file = "mypy-1.17.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8"}, + {file = "mypy-1.17.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8"}, + {file = "mypy-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259"}, + {file = "mypy-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d"}, + {file = "mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9"}, + {file = "mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01"}, ] [package.dependencies] @@ -976,14 +987,14 @@ lint = ["black"] [[package]] name = "parso" -version = "0.8.4" +version = "0.8.5" description = "A Python Parser" optional = false python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, - {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, + {file = "parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887"}, + {file = "parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a"}, ] [package.extras] @@ -1032,14 +1043,14 @@ ptyprocess = ">=0.5" [[package]] name = "platformdirs" -version = "4.3.8" +version = "4.4.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" groups = ["dev", "documentation", "linters"] files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, + {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, + {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, ] [package.extras] @@ -1085,14 +1096,14 @@ poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""] [[package]] name = "pre-commit" -version = "4.2.0" +version = "4.3.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"}, - {file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"}, + {file = "pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8"}, + {file = "pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16"}, ] [package.dependencies] @@ -1147,14 +1158,14 @@ tests = ["pytest"] [[package]] name = "pygments" -version = "2.19.1" +version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" groups = ["dev", "documentation", "script", "test"] files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, ] [package.extras] @@ -1162,14 +1173,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.15" +version = "10.16.1" description = "Extension pack for Python Markdown." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "pymdown_extensions-10.15-py3-none-any.whl", hash = "sha256:46e99bb272612b0de3b7e7caf6da8dd5f4ca5212c0b273feb9304e236c484e5f"}, - {file = "pymdown_extensions-10.15.tar.gz", hash = "sha256:0e5994e32155f4b03504f939e501b981d306daf7ec2aa1cd2eb6bd300784f8f7"}, + {file = "pymdown_extensions-10.16.1-py3-none-any.whl", hash = "sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d"}, + {file = "pymdown_extensions-10.16.1.tar.gz", hash = "sha256:aace82bcccba3efc03e25d584e6a22d27a8e17caa3f4dd9f207e49b787aa9a91"}, ] [package.dependencies] @@ -1201,14 +1212,14 @@ testing = ["covdefaults (>=2.3)", "pytest (>=8.3.5)", "pytest-cov (>=6.1.1)", "p [[package]] name = "pytest" -version = "8.4.0" +version = "8.4.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e"}, - {file = "pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6"}, + {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, + {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, ] [package.dependencies] @@ -1225,33 +1236,34 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests [[package]] name = "pytest-cov" -version = "6.1.1" +version = "6.2.1" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde"}, - {file = "pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a"}, + {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, + {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, ] [package.dependencies] coverage = {version = ">=7.5", extras = ["toml"]} -pytest = ">=4.6" +pluggy = ">=1.2" +pytest = ">=6.2.5" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-datadir" -version = "1.7.2" +version = "1.8.0" description = "pytest plugin for test data directories and files" optional = false python-versions = ">=3.8" groups = ["test"] files = [ - {file = "pytest_datadir-1.7.2-py3-none-any.whl", hash = "sha256:8392ba0e9eaf37030e663dcd91cc5123dec99c44300f0c5eac44f35f13f0e086"}, - {file = "pytest_datadir-1.7.2.tar.gz", hash = "sha256:15f5228a35d0a3205e4968e75d3b9cca91762424e1eafc21eb637d380a48443e"}, + {file = "pytest_datadir-1.8.0-py3-none-any.whl", hash = "sha256:5c677bc097d907ac71ca418109adc3abe34cf0bddfe6cf78aecfbabd96a15cf0"}, + {file = "pytest_datadir-1.8.0.tar.gz", hash = "sha256:7a15faed76cebe87cc91941dd1920a9a38eba56a09c11e9ddf1434d28a0f78eb"}, ] [package.dependencies] @@ -1297,14 +1309,14 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "pytest-regressions" -version = "2.8.0" +version = "2.8.2" description = "Easy to use fixtures to write regression tests." optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest_regressions-2.8.0-py3-none-any.whl", hash = "sha256:2926f37efa5fd6793806b10352e274c5284a5469a845aeab6243e86f9214766f"}, - {file = "pytest_regressions-2.8.0.tar.gz", hash = "sha256:775044e17117f5427df2caad3ab1c66889abe770a0ce2bc3f24fdeac99af76fe"}, + {file = "pytest_regressions-2.8.2-py3-none-any.whl", hash = "sha256:a0804c1ce66d8e4d9a3c7c68f42a3d436182edca8e86565c232caeaf9e080fc2"}, + {file = "pytest_regressions-2.8.2.tar.gz", hash = "sha256:1d8f4767be58b9994bfa7d60271099469ad32b8ca9f9d9ceca1c1d6827156b19"}, ] [package.dependencies] @@ -1320,14 +1332,14 @@ num = ["numpy", "pandas"] [[package]] name = "pytest-xdist" -version = "3.7.0" +version = "3.8.0" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest_xdist-3.7.0-py3-none-any.whl", hash = "sha256:7d3fbd255998265052435eb9daa4e99b62e6fb9cfb6efd1f858d4d8c0c7f0ca0"}, - {file = "pytest_xdist-3.7.0.tar.gz", hash = "sha256:f9248c99a7c15b7d2f90715df93610353a485827bc06eefb6566d23f6400f126"}, + {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, + {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, ] [package.dependencies] @@ -1449,19 +1461,19 @@ prompt_toolkit = ">=2.0,<4.0" [[package]] name = "requests" -version = "2.32.3" +version = "2.32.5" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, ] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" +charset_normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" @@ -1621,31 +1633,28 @@ files = [ [[package]] name = "tox" -version = "4.26.0" +version = "4.28.4" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tox-4.26.0-py3-none-any.whl", hash = "sha256:75f17aaf09face9b97bd41645028d9f722301e912be8b4c65a3f938024560224"}, - {file = "tox-4.26.0.tar.gz", hash = "sha256:a83b3b67b0159fa58e44e646505079e35a43317a62d2ae94725e0586266faeca"}, + {file = "tox-4.28.4-py3-none-any.whl", hash = "sha256:8d4ad9ee916ebbb59272bb045e154a10fa12e3bbdcf94cc5185cbdaf9b241f99"}, + {file = "tox-4.28.4.tar.gz", hash = "sha256:b5b14c6307bd8994ff1eba5074275826620325ee1a4f61316959d562bfd70b9d"}, ] [package.dependencies] -cachetools = ">=5.5.1" +cachetools = ">=6.1" chardet = ">=5.2" colorama = ">=0.4.6" -filelock = ">=3.16.1" -packaging = ">=24.2" -platformdirs = ">=4.3.6" -pluggy = ">=1.5" -pyproject-api = ">=1.8" +filelock = ">=3.18" +packaging = ">=25" +platformdirs = ">=4.3.8" +pluggy = ">=1.6" +pyproject-api = ">=1.9.1" tomli = {version = ">=2.2.1", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} -virtualenv = ">=20.31" - -[package.extras] -test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.4)", "pytest-mock (>=3.14)"] +typing-extensions = {version = ">=4.14.1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.31.2" [[package]] name = "traitlets" @@ -1665,14 +1674,14 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "types-colorama" -version = "0.4.15.20240311" +version = "0.4.15.20250801" description = "Typing stubs for colorama" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "types-colorama-0.4.15.20240311.tar.gz", hash = "sha256:a28e7f98d17d2b14fb9565d32388e419f4108f557a7d939a66319969b2b99c7a"}, - {file = "types_colorama-0.4.15.20240311-py3-none-any.whl", hash = "sha256:6391de60ddc0db3f147e31ecb230006a6823e81e380862ffca1e4695c13a0b8e"}, + {file = "types_colorama-0.4.15.20250801-py3-none-any.whl", hash = "sha256:b6e89bd3b250fdad13a8b6a465c933f4a5afe485ea2e2f104d739be50b13eea9"}, + {file = "types_colorama-0.4.15.20250801.tar.gz", hash = "sha256:02565d13d68963d12237d3f330f5ecd622a3179f7b5b14ee7f16146270c357f5"}, ] [[package]] @@ -1689,26 +1698,26 @@ files = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20250516" +version = "2.9.0.20250822" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93"}, - {file = "types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5"}, + {file = "types_python_dateutil-2.9.0.20250822-py3-none-any.whl", hash = "sha256:849d52b737e10a6dc6621d2bd7940ec7c65fcb69e6aa2882acf4e56b2b508ddc"}, + {file = "types_python_dateutil-2.9.0.20250822.tar.gz", hash = "sha256:84c92c34bd8e68b117bff742bc00b692a1e8531262d4507b33afcc9f7716cd53"}, ] [[package]] name = "types-pyyaml" -version = "6.0.12.20250516" +version = "6.0.12.20250822" description = "Typing stubs for PyYAML" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "types_pyyaml-6.0.12.20250516-py3-none-any.whl", hash = "sha256:8478208feaeb53a34cb5d970c56a7cd76b72659442e733e268a94dc72b2d0530"}, - {file = "types_pyyaml-6.0.12.20250516.tar.gz", hash = "sha256:9f21a70216fc0fa1b216a8176db5f9e0af6eb35d2f2932acb87689d03a5bf6ba"}, + {file = "types_pyyaml-6.0.12.20250822-py3-none-any.whl", hash = "sha256:1fe1a5e146aa315483592d292b72a172b65b946a6d98aa6ddd8e4aa838ab7098"}, + {file = "types_pyyaml-6.0.12.20250822.tar.gz", hash = "sha256:259f1d93079d335730a9db7cff2bcaf65d7e04b4a56b5927d49a612199b59413"}, ] [[package]] @@ -1725,27 +1734,27 @@ files = [ [[package]] name = "typing-extensions" -version = "4.14.0" +version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["main", "dev", "linters", "script", "test"] files = [ - {file = "typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"}, - {file = "typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"", script = "python_version < \"3.11\"", test = "python_version < \"3.11\""} [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, - {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, + {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, + {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, ] [package.extras] @@ -1756,20 +1765,21 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.31.2" +version = "20.34.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" groups = ["dev", "linters"] files = [ - {file = "virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11"}, - {file = "virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af"}, + {file = "virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026"}, + {file = "virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = ">=3.12.2,<4" platformdirs = ">=3.9.1,<5" +typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] @@ -1832,104 +1842,106 @@ files = [ [[package]] name = "wrapt" -version = "1.17.2" +version = "1.17.3" description = "Module for decorators, wrappers and monkey patching." optional = false python-versions = ">=3.8" groups = ["test"] files = [ - {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, - {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, - {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, - {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, - {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, - {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, - {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, - {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, - {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, - {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, - {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, - {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, - {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, - {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, - {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, - {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, - {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, - {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, - {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"}, + {file = "wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775"}, + {file = "wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd"}, + {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05"}, + {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418"}, + {file = "wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390"}, + {file = "wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6"}, + {file = "wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f"}, + {file = "wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311"}, + {file = "wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1"}, + {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5"}, + {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2"}, + {file = "wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89"}, + {file = "wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77"}, + {file = "wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"}, + {file = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"}, + {file = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"}, + {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"}, + {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"}, + {file = "wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"}, + {file = "wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"}, + {file = "wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"}, + {file = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"}, + {file = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"}, + {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"}, + {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"}, + {file = "wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"}, + {file = "wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"}, + {file = "wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"}, + {file = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"}, + {file = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"}, + {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"}, + {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"}, + {file = "wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"}, + {file = "wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"}, + {file = "wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"}, + {file = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"}, + {file = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"}, + {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"}, + {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"}, + {file = "wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"}, + {file = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"}, + {file = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f"}, + {file = "wrapt-1.17.3-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00"}, + {file = "wrapt-1.17.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56"}, + {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5"}, + {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22"}, + {file = "wrapt-1.17.3-cp38-cp38-win32.whl", hash = "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c"}, + {file = "wrapt-1.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d"}, + {file = "wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a"}, + {file = "wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139"}, + {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df"}, + {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b"}, + {file = "wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81"}, + {file = "wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f"}, + {file = "wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f"}, + {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, + {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, ] [[package]] name = "zipp" -version = "3.22.0" +version = "3.23.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.9" groups = ["main", "documentation"] markers = "python_version == \"3.9\"" files = [ - {file = "zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343"}, - {file = "zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5"}, + {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, + {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, ] [package.extras] @@ -1937,10 +1949,10 @@ check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \" cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib_resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "0c750c9d3befb187e16df9b2524cedd8319da36c1311ac74d083b9e8ff54ff1d" +content-hash = "79d126ebbb9e2d0976e3b2853980826e4b32b62ca9d982507bf21aff9bffacd0" diff --git a/pyproject.toml b/pyproject.toml index ebb2244770..6ff5219328 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -120,7 +120,7 @@ deprecated = "^1.2.13" [tool.poetry.group.linters.dependencies] ruff = "^0.11.5" -pre-commit = ">=2.18,<5.0" +pre-commit = ">=3.2.0,<5.0" mypy = "^1.16.0" types-deprecated = "^1.2.9.2" types-python-dateutil = "^2.8.19.13" From 8097cb3d102ec79641cc6e4a95628fdc54dab42a Mon Sep 17 00:00:00 2001 From: timsu92 <33785401+timsu92@users.noreply.github.com> Date: Wed, 6 Aug 2025 21:25:30 +0800 Subject: [PATCH 033/221] test(init): check "pre-" is showing in outputs --- tests/commands/test_init_command.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 7feaf18ef2..26f67dfae4 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -32,7 +32,7 @@ def unsafe_ask(self): "rev": f"v{__version__}", "hooks": [ {"id": "commitizen"}, - {"id": "commitizen-branch", "stages": ["push"]}, + {"id": "commitizen-branch", "stages": ["pre-push"]}, ], } From 2df5098aa334f3323257fc709921f8d3385d9268 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 11 Jun 2025 15:41:05 +0800 Subject: [PATCH 034/221] refactor(Init): remove the variable values_to_add and the update_config function for readability --- commitizen/commands/init.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index a6efe0acc0..2ce3981f44 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -160,21 +160,6 @@ def __call__(self) -> None: self.config = JsonConfig(data="{}", path=config_path) elif "yaml" in config_path: self.config = YAMLConfig(data="", path=config_path) - values_to_add: dict[str, Any] = {} - values_to_add["name"] = cz_name - values_to_add["tag_format"] = tag_format - values_to_add["version_scheme"] = version_scheme - - if version_provider == "commitizen": - values_to_add["version"] = version.public - else: - values_to_add["version_provider"] = version_provider - - if update_changelog_on_bump: - values_to_add["update_changelog_on_bump"] = update_changelog_on_bump - - if major_version_zero: - values_to_add["major_version_zero"] = major_version_zero # Collect hook data hook_types = questionary.checkbox( @@ -192,7 +177,18 @@ def __call__(self) -> None: # Create and initialize config self.config.init_empty_config_content() - self._update_config_file(values_to_add) + + self.config.set_key("name", cz_name) + self.config.set_key("tag_format", tag_format) + self.config.set_key("version_scheme", version_scheme) + if version_provider == "commitizen": + self.config.set_key("version", version.public) + else: + self.config.set_key("version_provider", version_provider) + if update_changelog_on_bump: + self.config.set_key("update_changelog_on_bump", update_changelog_on_bump) + if major_version_zero: + self.config.set_key("major_version_zero", major_version_zero) out.write("\nYou can bump the version running:\n") out.info("\tcz bump\n") @@ -387,7 +383,3 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None: hook_types = ["commit-msg", "pre-push"] self._exec_install_pre_commit_hook(hook_types) out.write("commitizen pre-commit hook is now installed in your '.git'\n") - - def _update_config_file(self, values: dict[str, Any]) -> None: - for key, value in values.items(): - self.config.set_key(key, value) From 3e94cec3d5c6f396b626c5b73536f0f2da010e89 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 11 Jun 2025 15:55:35 +0800 Subject: [PATCH 035/221] test(Init): improve test coverage on config initialization --- tests/commands/test_init_command.py | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 26f67dfae4..c156fb0234 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -420,3 +420,66 @@ def test_init_with_valid_tag_selection(config, mocker: MockFixture, tmpdir): content = toml_file.read() assert 'version = "0.9.0"' in content assert 'version_scheme = "semver"' in content + + +def test_init_configuration_settings(tmpdir, mocker: MockFixture, config): + """Test that all configuration settings are properly initialized.""" + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), + FakeQuestion("cz_conventional_commits"), + FakeQuestion("commitizen"), + FakeQuestion("semver"), + ], + ) + mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + + with open("pyproject.toml", encoding="utf-8") as toml_file: + config_data = toml_file.read() + + # Verify all expected settings are present + assert 'name = "cz_conventional_commits"' in config_data + assert 'tag_format = "$version"' in config_data + assert 'version_scheme = "semver"' in config_data + assert 'version = "0.0.1"' in config_data + assert "update_changelog_on_bump = true" in config_data + assert "major_version_zero = true" in config_data + + +def test_init_configuration_with_version_provider(tmpdir, mocker: MockFixture, config): + """Test configuration initialization with a different version provider.""" + mocker.patch( + "questionary.select", + side_effect=[ + FakeQuestion("pyproject.toml"), + FakeQuestion("cz_conventional_commits"), + FakeQuestion("pep621"), # Different version provider + FakeQuestion("semver"), + ], + ) + mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) + mocker.patch("questionary.text", return_value=FakeQuestion("$version")) + mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) + + with tmpdir.as_cwd(): + commands.Init(config)() + + with open("pyproject.toml", encoding="utf-8") as toml_file: + config_data = toml_file.read() + + # Verify version provider is set instead of version + assert 'name = "cz_conventional_commits"' in config_data + assert 'tag_format = "$version"' in config_data + assert 'version_scheme = "semver"' in config_data + assert 'version_provider = "pep621"' in config_data + assert "update_changelog_on_bump = true" in config_data + assert "major_version_zero = true" in config_data + assert ( + "version = " not in config_data + ) # Version should not be set when using version_provider From 73f09ee4de0aee418be5d59c53a2b6e59831c248 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 16:59:11 +0800 Subject: [PATCH 036/221] refactor(changelog): shorten generate_tree_from_commits --- commitizen/changelog.py | 57 +++++++++++++++++------------------------ commitizen/git.py | 3 +++ 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/commitizen/changelog.py b/commitizen/changelog.py index 93b5339962..1a1938c7c3 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -32,6 +32,7 @@ from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence from dataclasses import dataclass from datetime import date +from itertools import chain from typing import TYPE_CHECKING, Any from jinja2 import ( @@ -88,33 +89,32 @@ def generate_tree_from_commits( pat = re.compile(changelog_pattern) map_pat = re.compile(commit_parser, re.MULTILINE) body_map_pat = re.compile(commit_parser, re.MULTILINE | re.DOTALL) - current_tag: GitTag | None = None rules = rules or TagRules() # Check if the latest commit is not tagged - if commits: - latest_commit = commits[0] - current_tag = get_commit_tag(latest_commit, tags) - - current_tag_name: str = unreleased_version or "Unreleased" - current_tag_date: str = "" - if unreleased_version is not None: - current_tag_date = date.today().isoformat() - if current_tag is not None and current_tag.name: - current_tag_name = current_tag.name - current_tag_date = current_tag.date + current_tag = get_commit_tag(commits[0], tags) if commits else None + current_tag_name = unreleased_version or "Unreleased" + current_tag_date = ( + date.today().isoformat() if unreleased_version is not None else "" + ) + + used_tags: set[GitTag] = set() + if current_tag: + used_tags.add(current_tag) + if current_tag.name: + current_tag_name = current_tag.name + current_tag_date = current_tag.date + + commit_tag: GitTag | None = None changes: dict = defaultdict(list) - used_tags: list = [current_tag] for commit in commits: - commit_tag = get_commit_tag(commit, tags) - if ( - commit_tag + (commit_tag := get_commit_tag(commit, tags)) and commit_tag not in used_tags and rules.include_in_changelog(commit_tag) ): - used_tags.append(commit_tag) + used_tags.add(commit_tag) release = { "version": current_tag_name, "date": current_tag_date, @@ -127,24 +127,15 @@ def generate_tree_from_commits( current_tag_date = commit_tag.date changes = defaultdict(list) - matches = pat.match(commit.message) - if not matches: + if not pat.match(commit.message): continue - # Process subject from commit message - if message := map_pat.match(commit.message): - process_commit_message( - changelog_message_builder_hook, - message, - commit, - changes, - change_type_map, - ) - - # Process body from commit message - body_parts = commit.body.split("\n\n") - for body_part in body_parts: - if message := body_map_pat.match(body_part): + # Process subject and body from commit message + for message in chain( + [map_pat.match(commit.message)], + (body_map_pat.match(block) for block in commit.body.split("\n\n")), + ): + if message: process_commit_message( changelog_message_builder_hook, message, diff --git a/commitizen/git.py b/commitizen/git.py index 4883b34e7d..c2bab176ea 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -49,6 +49,9 @@ class GitObject: def __eq__(self, other: object) -> bool: return hasattr(other, "rev") and self.rev == other.rev + def __hash__(self) -> int: + return hash(self.rev) + class GitCommit(GitObject): def __init__( From 9d392a4714aa24750241ea3a39d4a5df0326f70b Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 3 Jun 2025 20:13:03 +0800 Subject: [PATCH 037/221] feat(check): add check against default branch --- commitizen/cli.py | 7 ++++ commitizen/commands/check.py | 34 ++++++++++++------- commitizen/git.py | 7 ++++ docs/commands/check.md | 24 ++++++++----- ...shows_description_when_use_help_option.txt | 5 ++- tests/test_git.py | 19 +++++++++++ 6 files changed, 74 insertions(+), 22 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 3862b8843e..ed4305ea1f 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -471,6 +471,13 @@ def __call__( "help": "a range of git rev to check. e.g, master..HEAD", "exclusive_group": "group1", }, + { + "name": ["-d", "--use-default-range"], + "action": "store_true", + "default": False, + "help": "check from the default branch to HEAD. e.g, refs/remotes/origin/master..HEAD", + "exclusive_group": "group1", + }, { "name": ["-m", "--message"], "help": "commit message that needs to be checked", diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index 69147bcfbe..e6ebc928ed 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -21,6 +21,7 @@ class CheckArgs(TypedDict, total=False): message_length_limit: int allowed_prefixes: list[str] message: str + use_default_range: bool class Check: @@ -40,6 +41,7 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N self.allow_abort = bool( arguments.get("allow_abort", config.settings["allow_abort"]) ) + self.use_default_range = bool(arguments.get("use_default_range")) self.max_msg_length = arguments.get("message_length_limit", 0) # we need to distinguish between None and [], which is a valid value @@ -50,25 +52,28 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N else config.settings["allowed_prefixes"] ) - self._valid_command_argument() - - self.config: BaseConfig = config - self.encoding = config.settings["encoding"] - self.cz = factory.committer_factory(self.config) - - def _valid_command_argument(self) -> None: num_exclusive_args_provided = sum( arg is not None - for arg in (self.commit_msg_file, self.commit_msg, self.rev_range) + for arg in ( + self.commit_msg_file, + self.commit_msg, + self.rev_range, + ) ) - if num_exclusive_args_provided == 0 and not sys.stdin.isatty(): - self.commit_msg = sys.stdin.read() - elif num_exclusive_args_provided != 1: + + if num_exclusive_args_provided > 1: raise InvalidCommandArgumentError( "Only one of --rev-range, --message, and --commit-msg-file is permitted by check command! " "See 'cz check -h' for more information" ) + if num_exclusive_args_provided == 0 and not sys.stdin.isatty(): + self.commit_msg = sys.stdin.read() + + self.config: BaseConfig = config + self.encoding = config.settings["encoding"] + self.cz = factory.committer_factory(self.config) + def __call__(self) -> None: """Validate if commit messages follows the conventional pattern. @@ -109,7 +114,10 @@ def _get_commits(self) -> list[git.GitCommit]: return [git.GitCommit(rev="", title="", body=self._filter_comments(msg))] # Get commit messages from git log (--rev-range) - return git.get_commits(end=self.rev_range) + return git.get_commits( + git.get_default_branch() if self.use_default_range else None, + self.rev_range, + ) @staticmethod def _filter_comments(msg: str) -> str: @@ -134,7 +142,7 @@ def _filter_comments(msg: str) -> str: The filtered commit message without comments. """ - lines = [] + lines: list[str] = [] for line in msg.split("\n"): if "# ------------------------ >8 ------------------------" in line: break diff --git a/commitizen/git.py b/commitizen/git.py index c2bab176ea..c124cd9371 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -332,3 +332,10 @@ def _get_log_as_str_list(start: str | None, end: str, args: str) -> list[str]: if c.return_code != 0: raise GitCommandError(c.err) return c.out.split(f"{delimiter}\n") + + +def get_default_branch() -> str: + c = cmd.run("git symbolic-ref refs/remotes/origin/HEAD") + if c.return_code != 0: + raise GitCommandError(c.err) + return c.out.strip() diff --git a/docs/commands/check.md b/docs/commands/check.md index 33e41e04f8..320bffb881 100644 --- a/docs/commands/check.md +++ b/docs/commands/check.md @@ -27,19 +27,21 @@ $ cz check --rev-range REV_RANGE For example, if you'd like to check all commits on a branch, you can use `--rev-range master..HEAD`. Or, if you'd like to check all commits starting from when you first implemented commit message linting, you can use `--rev-range ..HEAD`. +You can also use `--use-default-range` to check all commits from the default branch up to HEAD. This is equivalent to using `--rev-range ..HEAD`. + For more information on how git commit ranges work, you can check the [git documentation](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#_commit_ranges). ### Commit Message There are two ways you can provide your plain message and check it. -#### Method 1: use -m or --message +#### Method 1: use `-m` or `--message` ```bash $ cz check --message MESSAGE ``` -In this option, MESSAGE is the commit message to be checked. +In this option, `MESSAGE` is the commit message to be checked. #### Method 2: use pipe to pipe it to `cz check` @@ -47,7 +49,7 @@ In this option, MESSAGE is the commit message to be checked. $ echo MESSAGE | cz check ``` -In this option, MESSAGE is piped to cz check and will be checked. +In this option, `MESSAGE` is piped to `cz check` and will be checked. ### Commit Message File @@ -55,7 +57,7 @@ In this option, MESSAGE is piped to cz check and will be checked. $ cz check --commit-msg-file COMMIT_MSG_FILE ``` -In this option, COMMIT_MSG_FILE is the path of the temporary file that contains the commit message. +In this option, `COMMIT_MSG_FILE` is the path of the temporary file that contains the commit message. This argument can be useful when cooperating with git hooks. Please check [Automatically check message before commit](../tutorials/auto_check.md) for more information about how to use this argument with git hooks. ### Allow Abort @@ -65,12 +67,18 @@ cz check --message MESSAGE --allow-abort ``` Empty commit messages typically instruct Git to abort a commit, so you can pass `--allow-abort` to -permit them. Since `git commit` accepts an `--allow-empty-message` flag (primarily for wrapper scripts), you may wish to disallow such commits in CI. `--allow-abort` may be used in conjunction with any of the other options. +permit them. Since `git commit` accepts the `--allow-empty-message` flag (primarily for wrapper scripts), you may wish to disallow such commits in CI. `--allow-abort` may be used in conjunction with any of the other options. ### Allowed Prefixes If the commit message starts with some specific prefixes, `cz check` returns `True` without checking the regex. -By default, the following prefixes are allowed: `Merge`, `Revert`, `Pull request`, `fixup!` and `squash!`. +By default, the following prefixes are allowed: + +- `Merge` +- `Revert` +- `Pull request` +- `fixup!` +- `squash!` ```bash cz check --message MESSAGE --allowed-prefixes 'Merge' 'Revert' 'Custom Prefix' @@ -83,5 +91,5 @@ For example, `cz check --message MESSAGE -l 3` would fail the check, since `MESS By default, the limit is set to 0, which means no limit on the length. **Note that the limit applies only to the first line of the message.** -Specifically, for `ConventionalCommitsCz` the length only counts from the type of change to the subject, -while the body and the footer are not counted. + +Specifically, for `ConventionalCommitsCz` the length only counts from the type of change to the subject, while the body and the footer are not counted. diff --git a/tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt b/tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt index 85f42f6d2a..4066748557 100644 --- a/tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt +++ b/tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt @@ -1,5 +1,5 @@ usage: cz check [-h] [--commit-msg-file COMMIT_MSG_FILE | - --rev-range REV_RANGE | -m MESSAGE] [--allow-abort] + --rev-range REV_RANGE | -d | -m MESSAGE] [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] [-l MESSAGE_LENGTH_LIMIT] @@ -13,6 +13,9 @@ options: MSG_FILE=$1 --rev-range REV_RANGE a range of git rev to check. e.g, master..HEAD + -d, --use-default-range + check from the default branch to HEAD. e.g, + refs/remotes/origin/master..HEAD -m, --message MESSAGE commit message that needs to be checked --allow-abort allow empty commit messages, which typically abort a diff --git a/tests/test_git.py b/tests/test_git.py index e242b3a2ae..2a31d9c0b8 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -480,3 +480,22 @@ def test_create_commit_cmd_string(mocker, os_name, committer_date, expected_cmd) mocker.patch("os.name", os_name) result = git._create_commit_cmd_string("", committer_date, "temp.txt") assert result == expected_cmd + + +def test_get_default_branch_success(mocker: MockFixture): + mocker.patch( + "commitizen.cmd.run", return_value=FakeCommand(out="refs/remotes/origin/main\n") + ) + assert git.get_default_branch() == "refs/remotes/origin/main" + + +def test_get_default_branch_error(mocker: MockFixture): + mocker.patch( + "commitizen.cmd.run", + return_value=FakeCommand( + err="fatal: ref refs/remotes/origin/HEAD is not a symbolic ref", + return_code=1, + ), + ) + with pytest.raises(exceptions.GitCommandError): + git.get_default_branch() From 028ab2e33796fd94c1b2c075e9212b8836c72141 Mon Sep 17 00:00:00 2001 From: ongdisheng Date: Sun, 6 Jul 2025 22:11:09 +0800 Subject: [PATCH 038/221] test(changelog): ensure error on missing changelog template filename --- tests/commands/test_changelog_command.py | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index 0eb29cdb04..1f3dabd761 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -1914,6 +1914,32 @@ def test_export_changelog_template_from_plugin( assert target.read_text() == tpl +def test_export_changelog_template_fails_when_template_has_no_filename( + mocker: MockFixture, + tmp_commitizen_project: Path, +): + project_root = Path(tmp_commitizen_project) + target = project_root / "changelog.jinja" + + # Mock a template object with no filename + class FakeTemplate: + filename = None + + # Patch get_changelog_template to return a template without a filename + mocker.patch( + "commitizen.changelog.get_changelog_template", return_value=FakeTemplate() + ) + + args = ["cz", "changelog", "--export-template", str(target)] + mocker.patch.object(sys, "argv", args) + + with pytest.raises(NotAllowed) as exc_info: + cli.main() + + assert not target.exists() + assert "Template filename is not set" in str(exc_info.value) + + @skip_below_py_3_13 def test_changelog_command_shows_description_when_use_help_option( mocker: MockFixture, capsys, file_regression From 1fb11e00345bb6d475df07e32ccc233392e012af Mon Sep 17 00:00:00 2001 From: timsu92 <33785401+timsu92@users.noreply.github.com> Date: Wed, 6 Aug 2025 20:49:58 +0800 Subject: [PATCH 039/221] fix(init): use pre-push as pre-commit stage Original "push" stage has been deprecated since pre-commit v3.2.0. See https://github.com/pre-commit/pre-commit/issues/2732 and https://github.com/pre-commit/pre-commit/pull/2808 for detailed information. --- poetry.lock | 192 ++++++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/poetry.lock b/poetry.lock index 829789632f..42af6b9c99 100644 --- a/poetry.lock +++ b/poetry.lock @@ -232,100 +232,100 @@ files = [ [[package]] name = "coverage" -version = "7.10.5" +version = "7.10.6" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "coverage-7.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c6a5c3414bfc7451b879141ce772c546985163cf553f08e0f135f0699a911801"}, - {file = "coverage-7.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bc8e4d99ce82f1710cc3c125adc30fd1487d3cf6c2cd4994d78d68a47b16989a"}, - {file = "coverage-7.10.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:02252dc1216e512a9311f596b3169fad54abcb13827a8d76d5630c798a50a754"}, - {file = "coverage-7.10.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:73269df37883e02d460bee0cc16be90509faea1e3bd105d77360b512d5bb9c33"}, - {file = "coverage-7.10.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f8a81b0614642f91c9effd53eec284f965577591f51f547a1cbeb32035b4c2f"}, - {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6a29f8e0adb7f8c2b95fa2d4566a1d6e6722e0a637634c6563cb1ab844427dd9"}, - {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fcf6ab569436b4a647d4e91accba12509ad9f2554bc93d3aee23cc596e7f99c3"}, - {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:90dc3d6fb222b194a5de60af8d190bedeeddcbc7add317e4a3cd333ee6b7c879"}, - {file = "coverage-7.10.5-cp310-cp310-win32.whl", hash = "sha256:414a568cd545f9dc75f0686a0049393de8098414b58ea071e03395505b73d7a8"}, - {file = "coverage-7.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:e551f9d03347196271935fd3c0c165f0e8c049220280c1120de0084d65e9c7ff"}, - {file = "coverage-7.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c177e6ffe2ebc7c410785307758ee21258aa8e8092b44d09a2da767834f075f2"}, - {file = "coverage-7.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:14d6071c51ad0f703d6440827eaa46386169b5fdced42631d5a5ac419616046f"}, - {file = "coverage-7.10.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:61f78c7c3bc272a410c5ae3fde7792b4ffb4acc03d35a7df73ca8978826bb7ab"}, - {file = "coverage-7.10.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f39071caa126f69d63f99b324fb08c7b1da2ec28cbb1fe7b5b1799926492f65c"}, - {file = "coverage-7.10.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343a023193f04d46edc46b2616cdbee68c94dd10208ecd3adc56fcc54ef2baa1"}, - {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:585ffe93ae5894d1ebdee69fc0b0d4b7c75d8007983692fb300ac98eed146f78"}, - {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0ef4e66f006ed181df29b59921bd8fc7ed7cd6a9289295cd8b2824b49b570df"}, - {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb7b0bbf7cc1d0453b843eca7b5fa017874735bef9bfdfa4121373d2cc885ed6"}, - {file = "coverage-7.10.5-cp311-cp311-win32.whl", hash = "sha256:1d043a8a06987cc0c98516e57c4d3fc2c1591364831e9deb59c9e1b4937e8caf"}, - {file = "coverage-7.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:fefafcca09c3ac56372ef64a40f5fe17c5592fab906e0fdffd09543f3012ba50"}, - {file = "coverage-7.10.5-cp311-cp311-win_arm64.whl", hash = "sha256:7e78b767da8b5fc5b2faa69bb001edafcd6f3995b42a331c53ef9572c55ceb82"}, - {file = "coverage-7.10.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c2d05c7e73c60a4cecc7d9b60dbfd603b4ebc0adafaef371445b47d0f805c8a9"}, - {file = "coverage-7.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32ddaa3b2c509778ed5373b177eb2bf5662405493baeff52278a0b4f9415188b"}, - {file = "coverage-7.10.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dd382410039fe062097aa0292ab6335a3f1e7af7bba2ef8d27dcda484918f20c"}, - {file = "coverage-7.10.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7fa22800f3908df31cea6fb230f20ac49e343515d968cc3a42b30d5c3ebf9b5a"}, - {file = "coverage-7.10.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f366a57ac81f5e12797136552f5b7502fa053c861a009b91b80ed51f2ce651c6"}, - {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1dc8f1980a272ad4a6c84cba7981792344dad33bf5869361576b7aef42733a"}, - {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2285c04ee8676f7938b02b4936d9b9b672064daab3187c20f73a55f3d70e6b4a"}, - {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2492e4dd9daab63f5f56286f8a04c51323d237631eb98505d87e4c4ff19ec34"}, - {file = "coverage-7.10.5-cp312-cp312-win32.whl", hash = "sha256:38a9109c4ee8135d5df5505384fc2f20287a47ccbe0b3f04c53c9a1989c2bbaf"}, - {file = "coverage-7.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:6b87f1ad60b30bc3c43c66afa7db6b22a3109902e28c5094957626a0143a001f"}, - {file = "coverage-7.10.5-cp312-cp312-win_arm64.whl", hash = "sha256:672a6c1da5aea6c629819a0e1461e89d244f78d7b60c424ecf4f1f2556c041d8"}, - {file = "coverage-7.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ef3b83594d933020f54cf65ea1f4405d1f4e41a009c46df629dd964fcb6e907c"}, - {file = "coverage-7.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b96bfdf7c0ea9faebce088a3ecb2382819da4fbc05c7b80040dbc428df6af44"}, - {file = "coverage-7.10.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:63df1fdaffa42d914d5c4d293e838937638bf75c794cf20bee12978fc8c4e3bc"}, - {file = "coverage-7.10.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8002dc6a049aac0e81ecec97abfb08c01ef0c1fbf962d0c98da3950ace89b869"}, - {file = "coverage-7.10.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:63d4bb2966d6f5f705a6b0c6784c8969c468dbc4bcf9d9ded8bff1c7e092451f"}, - {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1f672efc0731a6846b157389b6e6d5d5e9e59d1d1a23a5c66a99fd58339914d5"}, - {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3f39cef43d08049e8afc1fde4a5da8510fc6be843f8dea350ee46e2a26b2f54c"}, - {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2968647e3ed5a6c019a419264386b013979ff1fb67dd11f5c9886c43d6a31fc2"}, - {file = "coverage-7.10.5-cp313-cp313-win32.whl", hash = "sha256:0d511dda38595b2b6934c2b730a1fd57a3635c6aa2a04cb74714cdfdd53846f4"}, - {file = "coverage-7.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:9a86281794a393513cf117177fd39c796b3f8e3759bb2764259a2abba5cce54b"}, - {file = "coverage-7.10.5-cp313-cp313-win_arm64.whl", hash = "sha256:cebd8e906eb98bb09c10d1feed16096700b1198d482267f8bf0474e63a7b8d84"}, - {file = "coverage-7.10.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0520dff502da5e09d0d20781df74d8189ab334a1e40d5bafe2efaa4158e2d9e7"}, - {file = "coverage-7.10.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d9cd64aca68f503ed3f1f18c7c9174cbb797baba02ca8ab5112f9d1c0328cd4b"}, - {file = "coverage-7.10.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0913dd1613a33b13c4f84aa6e3f4198c1a21ee28ccb4f674985c1f22109f0aae"}, - {file = "coverage-7.10.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1b7181c0feeb06ed8a02da02792f42f829a7b29990fef52eff257fef0885d760"}, - {file = "coverage-7.10.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36d42b7396b605f774d4372dd9c49bed71cbabce4ae1ccd074d155709dd8f235"}, - {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b4fdc777e05c4940b297bf47bf7eedd56a39a61dc23ba798e4b830d585486ca5"}, - {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:42144e8e346de44a6f1dbd0a56575dd8ab8dfa7e9007da02ea5b1c30ab33a7db"}, - {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:66c644cbd7aed8fe266d5917e2c9f65458a51cfe5eeff9c05f15b335f697066e"}, - {file = "coverage-7.10.5-cp313-cp313t-win32.whl", hash = "sha256:2d1b73023854068c44b0c554578a4e1ef1b050ed07cf8b431549e624a29a66ee"}, - {file = "coverage-7.10.5-cp313-cp313t-win_amd64.whl", hash = "sha256:54a1532c8a642d8cc0bd5a9a51f5a9dcc440294fd06e9dda55e743c5ec1a8f14"}, - {file = "coverage-7.10.5-cp313-cp313t-win_arm64.whl", hash = "sha256:74d5b63fe3f5f5d372253a4ef92492c11a4305f3550631beaa432fc9df16fcff"}, - {file = "coverage-7.10.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:68c5e0bc5f44f68053369fa0d94459c84548a77660a5f2561c5e5f1e3bed7031"}, - {file = "coverage-7.10.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cf33134ffae93865e32e1e37df043bef15a5e857d8caebc0099d225c579b0fa3"}, - {file = "coverage-7.10.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ad8fa9d5193bafcf668231294241302b5e683a0518bf1e33a9a0dfb142ec3031"}, - {file = "coverage-7.10.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:146fa1531973d38ab4b689bc764592fe6c2f913e7e80a39e7eeafd11f0ef6db2"}, - {file = "coverage-7.10.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6013a37b8a4854c478d3219ee8bc2392dea51602dd0803a12d6f6182a0061762"}, - {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:eb90fe20db9c3d930fa2ad7a308207ab5b86bf6a76f54ab6a40be4012d88fcae"}, - {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:384b34482272e960c438703cafe63316dfbea124ac62006a455c8410bf2a2262"}, - {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:467dc74bd0a1a7de2bedf8deaf6811f43602cb532bd34d81ffd6038d6d8abe99"}, - {file = "coverage-7.10.5-cp314-cp314-win32.whl", hash = "sha256:556d23d4e6393ca898b2e63a5bca91e9ac2d5fb13299ec286cd69a09a7187fde"}, - {file = "coverage-7.10.5-cp314-cp314-win_amd64.whl", hash = "sha256:f4446a9547681533c8fa3e3c6cf62121eeee616e6a92bd9201c6edd91beffe13"}, - {file = "coverage-7.10.5-cp314-cp314-win_arm64.whl", hash = "sha256:5e78bd9cf65da4c303bf663de0d73bf69f81e878bf72a94e9af67137c69b9fe9"}, - {file = "coverage-7.10.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5661bf987d91ec756a47c7e5df4fbcb949f39e32f9334ccd3f43233bbb65e508"}, - {file = "coverage-7.10.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a46473129244db42a720439a26984f8c6f834762fc4573616c1f37f13994b357"}, - {file = "coverage-7.10.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1f64b8d3415d60f24b058b58d859e9512624bdfa57a2d1f8aff93c1ec45c429b"}, - {file = "coverage-7.10.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:44d43de99a9d90b20e0163f9770542357f58860a26e24dc1d924643bd6aa7cb4"}, - {file = "coverage-7.10.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a931a87e5ddb6b6404e65443b742cb1c14959622777f2a4efd81fba84f5d91ba"}, - {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9559b906a100029274448f4c8b8b0a127daa4dade5661dfd821b8c188058842"}, - {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b08801e25e3b4526ef9ced1aa29344131a8f5213c60c03c18fe4c6170ffa2874"}, - {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ed9749bb8eda35f8b636fb7632f1c62f735a236a5d4edadd8bbcc5ea0542e732"}, - {file = "coverage-7.10.5-cp314-cp314t-win32.whl", hash = "sha256:609b60d123fc2cc63ccee6d17e4676699075db72d14ac3c107cc4976d516f2df"}, - {file = "coverage-7.10.5-cp314-cp314t-win_amd64.whl", hash = "sha256:0666cf3d2c1626b5a3463fd5b05f5e21f99e6aec40a3192eee4d07a15970b07f"}, - {file = "coverage-7.10.5-cp314-cp314t-win_arm64.whl", hash = "sha256:bc85eb2d35e760120540afddd3044a5bf69118a91a296a8b3940dfc4fdcfe1e2"}, - {file = "coverage-7.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:62835c1b00c4a4ace24c1a88561a5a59b612fbb83a525d1c70ff5720c97c0610"}, - {file = "coverage-7.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5255b3bbcc1d32a4069d6403820ac8e6dbcc1d68cb28a60a1ebf17e47028e898"}, - {file = "coverage-7.10.5-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3876385722e335d6e991c430302c24251ef9c2a9701b2b390f5473199b1b8ebf"}, - {file = "coverage-7.10.5-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8048ce4b149c93447a55d279078c8ae98b08a6951a3c4d2d7e87f4efc7bfe100"}, - {file = "coverage-7.10.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4028e7558e268dd8bcf4d9484aad393cafa654c24b4885f6f9474bf53183a82a"}, - {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:03f47dc870eec0367fcdd603ca6a01517d2504e83dc18dbfafae37faec66129a"}, - {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2d488d7d42b6ded7ea0704884f89dcabd2619505457de8fc9a6011c62106f6e5"}, - {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b3dcf2ead47fa8be14224ee817dfc1df98043af568fe120a22f81c0eb3c34ad2"}, - {file = "coverage-7.10.5-cp39-cp39-win32.whl", hash = "sha256:02650a11324b80057b8c9c29487020073d5e98a498f1857f37e3f9b6ea1b2426"}, - {file = "coverage-7.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:b45264dd450a10f9e03237b41a9a24e85cbb1e278e5a32adb1a303f58f0017f3"}, - {file = "coverage-7.10.5-py3-none-any.whl", hash = "sha256:0be24d35e4db1d23d0db5c0f6a74a962e2ec83c426b5cac09f4234aadef38e4a"}, - {file = "coverage-7.10.5.tar.gz", hash = "sha256:f2e57716a78bc3ae80b2207be0709a3b2b63b9f2dcf9740ee6ac03588a2015b6"}, + {file = "coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356"}, + {file = "coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301"}, + {file = "coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460"}, + {file = "coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd"}, + {file = "coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb"}, + {file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6"}, + {file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945"}, + {file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e"}, + {file = "coverage-7.10.6-cp310-cp310-win32.whl", hash = "sha256:86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1"}, + {file = "coverage-7.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528"}, + {file = "coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f"}, + {file = "coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc"}, + {file = "coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a"}, + {file = "coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a"}, + {file = "coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62"}, + {file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153"}, + {file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5"}, + {file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619"}, + {file = "coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba"}, + {file = "coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e"}, + {file = "coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c"}, + {file = "coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea"}, + {file = "coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634"}, + {file = "coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6"}, + {file = "coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9"}, + {file = "coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c"}, + {file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a"}, + {file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5"}, + {file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972"}, + {file = "coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d"}, + {file = "coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629"}, + {file = "coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80"}, + {file = "coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6"}, + {file = "coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80"}, + {file = "coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003"}, + {file = "coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27"}, + {file = "coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4"}, + {file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d"}, + {file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc"}, + {file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc"}, + {file = "coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e"}, + {file = "coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32"}, + {file = "coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2"}, + {file = "coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b"}, + {file = "coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393"}, + {file = "coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27"}, + {file = "coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df"}, + {file = "coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb"}, + {file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282"}, + {file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4"}, + {file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21"}, + {file = "coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0"}, + {file = "coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5"}, + {file = "coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b"}, + {file = "coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e"}, + {file = "coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb"}, + {file = "coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034"}, + {file = "coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1"}, + {file = "coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a"}, + {file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb"}, + {file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d"}, + {file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747"}, + {file = "coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5"}, + {file = "coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713"}, + {file = "coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32"}, + {file = "coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65"}, + {file = "coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6"}, + {file = "coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0"}, + {file = "coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e"}, + {file = "coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5"}, + {file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7"}, + {file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5"}, + {file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0"}, + {file = "coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7"}, + {file = "coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930"}, + {file = "coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b"}, + {file = "coverage-7.10.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90558c35af64971d65fbd935c32010f9a2f52776103a259f1dee865fe8259352"}, + {file = "coverage-7.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8953746d371e5695405806c46d705a3cd170b9cc2b9f93953ad838f6c1e58612"}, + {file = "coverage-7.10.6-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c83f6afb480eae0313114297d29d7c295670a41c11b274e6bca0c64540c1ce7b"}, + {file = "coverage-7.10.6-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7eb68d356ba0cc158ca535ce1381dbf2037fa8cb5b1ae5ddfc302e7317d04144"}, + {file = "coverage-7.10.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b15a87265e96307482746d86995f4bff282f14b027db75469c446da6127433b"}, + {file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fc53ba868875bfbb66ee447d64d6413c2db91fddcfca57025a0e7ab5b07d5862"}, + {file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efeda443000aa23f276f4df973cb82beca682fd800bb119d19e80504ffe53ec2"}, + {file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9702b59d582ff1e184945d8b501ffdd08d2cee38d93a2206aa5f1365ce0b8d78"}, + {file = "coverage-7.10.6-cp39-cp39-win32.whl", hash = "sha256:2195f8e16ba1a44651ca684db2ea2b2d4b5345da12f07d9c22a395202a05b23c"}, + {file = "coverage-7.10.6-cp39-cp39-win_amd64.whl", hash = "sha256:f32ff80e7ef6a5b5b606ea69a36e97b219cd9dc799bcf2963018a4d8f788cfbf"}, + {file = "coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3"}, + {file = "coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90"}, ] [package.dependencies] @@ -1446,14 +1446,14 @@ pyyaml = "*" [[package]] name = "questionary" -version = "2.1.0" +version = "2.1.1" description = "Python library to build pretty command line user prompts ⭐️" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec"}, - {file = "questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587"}, + {file = "questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59"}, + {file = "questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d"}, ] [package.dependencies] @@ -1633,14 +1633,14 @@ files = [ [[package]] name = "tox" -version = "4.28.4" +version = "4.29.0" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tox-4.28.4-py3-none-any.whl", hash = "sha256:8d4ad9ee916ebbb59272bb045e154a10fa12e3bbdcf94cc5185cbdaf9b241f99"}, - {file = "tox-4.28.4.tar.gz", hash = "sha256:b5b14c6307bd8994ff1eba5074275826620325ee1a4f61316959d562bfd70b9d"}, + {file = "tox-4.29.0-py3-none-any.whl", hash = "sha256:b914f134176cea74c5e01c29cb4befc8afa4cd38b356c3756eff85832d27b5c0"}, + {file = "tox-4.29.0.tar.gz", hash = "sha256:7b3a2bb43974285110eee35a859f2b3f2e87a24f6e1011d83f466b7c75835bd2"}, ] [package.dependencies] From 2d5f7bfb7b287bde6f2dfc5770c6357920534893 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 16:31:42 +0800 Subject: [PATCH 040/221] refactor(changelog): simplify logic for get_oldest_and_newest_rev --- commitizen/changelog.py | 45 ++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/commitizen/changelog.py b/commitizen/changelog.py index 1a1938c7c3..7f5fe471ff 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -313,39 +313,28 @@ def get_oldest_and_newest_rev( - `0.1.0..0.4.0`: as a range - `0.3.0`: as a single version """ - oldest: str | None = None - newest: str | None = None - try: - oldest, newest = version.split("..") - except ValueError: - newest = version - if not (newest_tag := rules.find_tag_for(tags, newest)): + oldest_version, sep, newest_version = version.partition("..") + if not sep: + newest_version = version + oldest_version = "" + + def get_tag_name(v: str) -> str: + if tag := rules.find_tag_for(tags, v): + return tag.name raise NoCommitsFoundError("Could not find a valid revision range.") - oldest_tag = None - oldest_tag_name = None - if oldest: - if not (oldest_tag := rules.find_tag_for(tags, oldest)): - raise NoCommitsFoundError("Could not find a valid revision range.") - oldest_tag_name = oldest_tag.name + newest_tag_name = get_tag_name(newest_version) + oldest_tag_name = get_tag_name(oldest_version) if oldest_version else None - tags_range = get_smart_tag_range( - tags, newest=newest_tag.name, oldest=oldest_tag_name - ) + tags_range = get_smart_tag_range(tags, newest_tag_name, oldest_tag_name) if not tags_range: raise NoCommitsFoundError("Could not find a valid revision range.") oldest_rev: str | None = tags_range[-1].name - newest_rev = newest_tag.name - - # check if it's the first tag created - # and it's also being requested as part of the range - if oldest_rev == tags[-1].name and oldest_rev == oldest_tag_name: - return None, newest_rev - - # when they are the same, and it's also the - # first tag created - if oldest_rev == newest_rev: - return None, newest_rev - return oldest_rev, newest_rev + # Return None for oldest_rev if: + # 1. The oldest tag is the last tag in the list and matches the requested oldest tag + # 2. The oldest and the newest tag are the same + if oldest_rev == oldest_tag_name == tags[-1].name or oldest_rev == newest_tag_name: + oldest_rev = None + return oldest_rev, newest_tag_name From 8172be7eeb03863055b39ca31f7b464d79a87423 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 21:24:30 +0800 Subject: [PATCH 041/221] refactor(changelog): add get_next_tag_name_after_version and test, mark unused for get_smart_tag_range --- commitizen/changelog.py | 24 ++++++++++++++++-------- tests/test_changelog.py | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/commitizen/changelog.py b/commitizen/changelog.py index 7f5fe471ff..df04ad5c09 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -276,6 +276,16 @@ def incremental_build( return output_lines +def get_next_tag_name_after_version(tags: Iterable[GitTag], version: str) -> str | None: + it = iter(tag.name for tag in tags) + for name in it: + if name == version: + return next(it, None) + + raise NoCommitsFoundError(f"Could not find a valid revision range. {version=}") + + +# TODO: unused, deprecate this? def get_smart_tag_range( tags: Sequence[GitTag], newest: str, oldest: str | None = None ) -> list[GitTag]: @@ -303,7 +313,7 @@ def get_smart_tag_range( def get_oldest_and_newest_rev( - tags: Sequence[GitTag], + tags: Iterable[GitTag], version: str, rules: TagRules, ) -> tuple[str | None, str]: @@ -326,15 +336,13 @@ def get_tag_name(v: str) -> str: newest_tag_name = get_tag_name(newest_version) oldest_tag_name = get_tag_name(oldest_version) if oldest_version else None - tags_range = get_smart_tag_range(tags, newest_tag_name, oldest_tag_name) - if not tags_range: - raise NoCommitsFoundError("Could not find a valid revision range.") - - oldest_rev: str | None = tags_range[-1].name + oldest_rev = get_next_tag_name_after_version( + tags, oldest_tag_name or newest_tag_name + ) # Return None for oldest_rev if: # 1. The oldest tag is the last tag in the list and matches the requested oldest tag # 2. The oldest and the newest tag are the same - if oldest_rev == oldest_tag_name == tags[-1].name or oldest_rev == newest_tag_name: - oldest_rev = None + if oldest_rev == newest_tag_name: + return None, newest_tag_name return oldest_rev, newest_tag_name diff --git a/tests/test_changelog.py b/tests/test_changelog.py index ed90ed08e4..4465fcccbc 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -1535,6 +1535,24 @@ def test_get_smart_tag_range_returns_an_extra_for_a_single_tag(tags): assert 2 == len(res) +def test_get_next_tag_name_after_version(tags): + # Test finding next tag after a version + next_tag_name = changelog.get_next_tag_name_after_version(tags, "v1.2.0") + assert next_tag_name == "v1.1.1" + + next_tag_name = changelog.get_next_tag_name_after_version(tags, "v1.1.0") + assert next_tag_name == "v1.0.0" + + # Test finding last tag when given version is last + last_tag_name = changelog.get_next_tag_name_after_version(tags, "v0.9.1") + assert last_tag_name is None + + # Test error when version not found + with pytest.raises(changelog.NoCommitsFoundError) as exc_info: + changelog.get_next_tag_name_after_version(tags, "nonexistent") + assert "Could not find a valid revision range" in str(exc_info.value) + + @dataclass class TagDef: name: str From 67a828c01d3614c789d0ce43d71ab6a718ff670a Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 24 Aug 2025 21:03:13 +0800 Subject: [PATCH 042/221] fix(changelog): mark get_smart_tag_range as deprecated --- commitizen/changelog.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/commitizen/changelog.py b/commitizen/changelog.py index df04ad5c09..bdf11326be 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -35,6 +35,7 @@ from itertools import chain from typing import TYPE_CHECKING, Any +from deprecated import deprecated from jinja2 import ( BaseLoader, ChoiceLoader, @@ -285,7 +286,11 @@ def get_next_tag_name_after_version(tags: Iterable[GitTag], version: str) -> str raise NoCommitsFoundError(f"Could not find a valid revision range. {version=}") -# TODO: unused, deprecate this? +@deprecated( + reason="This function is unused and will be removed in v5", + version="5.0.0", + category=DeprecationWarning, +) def get_smart_tag_range( tags: Sequence[GitTag], newest: str, oldest: str | None = None ) -> list[GitTag]: From 73136ed6f38bd7bff1f37835c47b9753a40e956c Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sat, 30 Aug 2025 12:12:20 +0800 Subject: [PATCH 043/221] style(pyproject.toml): fix toml format --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6ff5219328..99f78caa36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,8 @@ readme = "docs/README.md" requires-python = ">=3.9,<4.0" dependencies = [ "questionary (>=2.0,<3.0)", - "prompt_toolkit!=3.0.52", # Exclude transitive dependency due to known issue in questionary: https://github.com/tmbo/questionary/issues/454 + # Exclude transitive dependency due to known issue in questionary: https://github.com/tmbo/questionary/issues/454 + "prompt_toolkit!=3.0.52", "decli (>=0.6.0,<1.0)", "colorama (>=0.4.1,<1.0)", "termcolor (>=1.1.0,<4.0.0)", From 98bba31fe6c9214cd49767e41802fa099d0c47a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 Sep 2025 06:09:44 +0000 Subject: [PATCH 044/221] =?UTF-8?q?bump:=20version=204.8.4=20=E2=86=92=204?= =?UTF-8?q?.9.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 39 +++++++++++++++++++++++++++++++++++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 46f6d04e34..10182d08e2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.8.4 # automatically updated by Commitizen + rev: v4.9.0 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 5723e11274..6b528c0f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ +## v4.9.0 (2025-09-09) + +### Feat + +- **check**: add check against default branch + +### Fix + +- **changelog**: mark get_smart_tag_range as deprecated +- **init**: use pre-push as pre-commit stage +- **init**: use pre-push as pre-commit stage +- **init**: make welcome message easier to read +- **Init**: fix a typo in _ask_version_provider options and remove unnecessary filter, use named tuple for options +- **ExitCode**: add from_str in ExitCode and replace parse_no_raise with it +- raise NoVersionSpecifiedError if version is None, and adjust call sites of get_version +- **Changelog**: fix _export_template variable type +- **Bump**: rewrite --get-next NotAllowed error message for consistency + +### Refactor + +- **changelog**: add get_next_tag_name_after_version and test, mark unused for get_smart_tag_range +- **changelog**: simplify logic for get_oldest_and_newest_rev +- **changelog**: shorten generate_tree_from_commits +- **Init**: remove the variable values_to_add and the update_config function for readability +- **Init**: remove unnecessary methods from ProjectInfo and refactor _ask_tag +- **Init**: fix unbounded variable in _ask_tag_format +- **init**: remote extra words +- **process_commit_message**: better type and early return +- **Init**: extract _get_config_data for readability +- **changelog**: shorten condition expression and early return +- **Changelog**: remove unnecessary intermediate variables for better readability +- **bump**: use a loop to shorten a series of similar NotAllowed exceptions +- **Init**: use ternary operator +- **TagRules**: extract tag_formats property and simplify list comprehension +- **git**: remove redundant if branch +- **ScmProvider**: replace sorted with max +- **ExpectedExit**: make the constructor more compact +- **ParseArgs**: simplify __call__ function body + ## v4.8.4 (2025-09-05) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index adba53e1e0..454a2edae2 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.8.4" +__version__ = "4.9.0" diff --git a/pyproject.toml b/pyproject.toml index 99f78caa36..986ac465c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.8.4" +version = "4.9.0" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -89,7 +89,7 @@ build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "4.8.4" +version = "4.9.0" tag_format = "v$version" version_files = [ "pyproject.toml:version", From 8f27018587f442c8e574a206dc14b5386e951fd8 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Tue, 9 Sep 2025 00:36:18 -0600 Subject: [PATCH 045/221] fix(dependency): move deprecated to project.dependencies --- poetry.lock | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 42af6b9c99..1a731e4f06 100644 --- a/poetry.lock +++ b/poetry.lock @@ -364,7 +364,7 @@ version = "1.2.18" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["test"] +groups = ["main"] files = [ {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"}, {file = "deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"}, @@ -1846,7 +1846,7 @@ version = "1.17.3" description = "Module for decorators, wrappers and monkey patching." optional = false python-versions = ">=3.8" -groups = ["test"] +groups = ["main"] files = [ {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"}, {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"}, @@ -1955,4 +1955,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "79d126ebbb9e2d0976e3b2853980826e4b32b62ca9d982507bf21aff9bffacd0" +content-hash = "bdc8773ed978a4265a2a099265db7e116d2f65c467c4980d984e546716cea244" diff --git a/pyproject.toml b/pyproject.toml index 986ac465c3..d033fc245e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ dependencies = [ "argcomplete >=1.12.1,<3.7", "typing-extensions (>=4.0.1,<5.0.0) ; python_version < '3.11'", "charset-normalizer (>=2.1.0,<4)", + "deprecated (>=1.2.13, <2)", # Use the Python 3.11 and 3.12 compatible API: https://github.com/python/importlib_metadata#compatibility "importlib-metadata >=8.0.0,<8.7.0 ; python_version < '3.10'", ] @@ -117,7 +118,6 @@ pytest-mock = "^3.10" pytest-regressions = "^2.4.0" pytest-freezer = "^0.4.6" pytest-xdist = "^3.1.0" -deprecated = "^1.2.13" [tool.poetry.group.linters.dependencies] ruff = "^0.11.5" From 8f903e7a6130aabb8836a60ebb747b07cf40ef9a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 10 Sep 2025 14:19:09 +0000 Subject: [PATCH 046/221] docs(cli/screenshots): update CLI screenshots [skip ci] --- docs/images/cli_help/cz_check___help.svg | 142 ++++++++++++----------- 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/docs/images/cli_help/cz_check___help.svg b/docs/images/cli_help/cz_check___help.svg index 690bfec684..397c0a2eeb 100644 --- a/docs/images/cli_help/cz_check___help.svg +++ b/docs/images/cli_help/cz_check___help.svg @@ -1,4 +1,4 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + - + - + - - $ cz check --help -usage: cz check [-h][--commit-msg-file COMMIT_MSG_FILE | -                --rev-range REV_RANGE | -m MESSAGE][--allow-abort] -[--allowed-prefixes [ALLOWED_PREFIXES ...]] -[-l MESSAGE_LENGTH_LIMIT] - -validates that a commit message matches the commitizen schema - -options: -  -h, --help            show this help message and exit -  --commit-msg-file COMMIT_MSG_FILE -                        ask for the name of the temporal file that contains -                        the commit message. Using it in a git hook script: -MSG_FILE=$1 -  --rev-range REV_RANGE -                        a range of git rev to check. e.g, master..HEAD -  -m, --message MESSAGE -                        commit message that needs to be checked -  --allow-abort         allow empty commit messages, which typically abort a -                        commit -  --allowed-prefixes [ALLOWED_PREFIXES ...] -                        allowed commit message prefixes. If the message starts -                        by one of these prefixes, the message won't be checked -                        against the regex -  -l, --message-length-limit MESSAGE_LENGTH_LIMIT -                        length limit of the commit message; 0 for no limit - + + $ cz check --help +usage: cz check [-h][--commit-msg-file COMMIT_MSG_FILE | +                --rev-range REV_RANGE | -d | -m MESSAGE][--allow-abort] +[--allowed-prefixes [ALLOWED_PREFIXES ...]] +[-l MESSAGE_LENGTH_LIMIT] + +validates that a commit message matches the commitizen schema + +options: +  -h, --help            show this help message and exit +  --commit-msg-file COMMIT_MSG_FILE +                        ask for the name of the temporal file that contains +                        the commit message. Using it in a git hook script: +MSG_FILE=$1 +  --rev-range REV_RANGE +                        a range of git rev to check. e.g, master..HEAD +  -d, --use-default-range +                        check from the default branch to HEAD. e.g, +                        refs/remotes/origin/master..HEAD +  -m, --message MESSAGE +                        commit message that needs to be checked +  --allow-abort         allow empty commit messages, which typically abort a +                        commit +  --allowed-prefixes [ALLOWED_PREFIXES ...] +                        allowed commit message prefixes. If the message starts +                        by one of these prefixes, the message won't be checked +                        against the regex +  -l, --message-length-limit MESSAGE_LENGTH_LIMIT +                        length limit of the commit message; 0 for no limit + From cc981fcb065527b6de0033b0cbf0432e69781901 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 10 Sep 2025 14:19:10 +0000 Subject: [PATCH 047/221] =?UTF-8?q?bump:=20version=204.9.0=20=E2=86=92=204?= =?UTF-8?q?.9.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 10182d08e2..4af318e4eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.9.0 # automatically updated by Commitizen + rev: v4.9.1 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b528c0f83..a72dc0fda0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.9.1 (2025-09-10) + +### Fix + +- **dependency**: move deprecated to project.dependencies + ## v4.9.0 (2025-09-09) ### Feat diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 454a2edae2..0139b2ebd5 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.9.0" +__version__ = "4.9.1" diff --git a/pyproject.toml b/pyproject.toml index d033fc245e..f16ad596bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.9.0" +version = "4.9.1" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -90,7 +90,7 @@ build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "4.9.0" +version = "4.9.1" tag_format = "v$version" version_files = [ "pyproject.toml:version", From b76301d235b85610576dfd2c9f76933cb73183a1 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 15 Sep 2025 11:26:27 +0800 Subject: [PATCH 048/221] test(Init): add type hint and rename variable --- tests/commands/test_init_command.py | 71 +++++++++++++++++------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index c156fb0234..ba4a150622 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -11,6 +11,7 @@ from commitizen import cli, commands from commitizen.__version__ import __version__ +from commitizen.config.base_config import BaseConfig from commitizen.exceptions import InitFailedError, NoAnswersError from tests.utils import skip_below_py_3_10 @@ -58,7 +59,9 @@ def unsafe_ask(self): } -def test_init_without_setup_pre_commit_hook(tmpdir, mocker: MockFixture, config): +def test_init_without_setup_pre_commit_hook( + tmpdir, mocker: MockFixture, config: BaseConfig +): mocker.patch( "questionary.select", side_effect=[ @@ -72,7 +75,6 @@ def test_init_without_setup_pre_commit_hook(tmpdir, mocker: MockFixture, config) mocker.patch("questionary.text", return_value=FakeQuestion("$version")) # Return None to skip hook installation mocker.patch("questionary.checkbox", return_value=FakeQuestion(None)) - with tmpdir.as_cwd(): commands.Init(config)() @@ -83,7 +85,7 @@ def test_init_without_setup_pre_commit_hook(tmpdir, mocker: MockFixture, config) assert not os.path.isfile(pre_commit_config_filename) -def test_init_when_config_already_exists(config, capsys): +def test_init_when_config_already_exists(config: BaseConfig, capsys): # Set config path path = os.sep.join(["tests", "pyproject.toml"]) config.path = path @@ -93,7 +95,7 @@ def test_init_when_config_already_exists(config, capsys): assert captured.out == f"Config file {path} already exists\n" -def test_init_without_choosing_tag(config, mocker: MockFixture, tmpdir): +def test_init_without_choosing_tag(config: BaseConfig, mocker: MockFixture, tmpdir): mocker.patch( "commitizen.commands.init.get_tag_names", return_value=["0.0.2", "0.0.1"] ) @@ -115,7 +117,7 @@ def test_init_without_choosing_tag(config, mocker: MockFixture, tmpdir): commands.Init(config)() -def test_executed_pre_commit_command(config): +def test_executed_pre_commit_command(config: BaseConfig): init = commands.Init(config) expected_cmd = "pre-commit install --hook-type commit-msg --hook-type pre-push" assert init._gen_pre_commit_cmd(["commit-msg", "pre-push"]) == expected_cmd @@ -155,17 +157,14 @@ def default_choice(request, mocker: MockFixture): yield request.param -def check_cz_config(config: str): +def check_cz_config(config_filepath: str): """ Check the content of commitizen config is as expected - - Args: - config: The config path """ - with open(config) as file: - if "json" in config: + with open(config_filepath) as file: + if "json" in config_filepath: assert json.load(file) == EXPECTED_DICT_CONFIG - elif "yaml" in config: + elif "yaml" in config_filepath: assert yaml.load(file, Loader=yaml.FullLoader) == EXPECTED_DICT_CONFIG else: config_data = file.read() @@ -183,13 +182,17 @@ def check_pre_commit_config(expected: list[dict[str, Any]]): @pytest.mark.usefixtures("pre_commit_installed") class TestPreCommitCases: - def test_no_existing_pre_commit_config(_, default_choice, tmpdir, config): + def test_no_existing_pre_commit_config( + _, default_choice: str, tmpdir, config: BaseConfig + ): with tmpdir.as_cwd(): commands.Init(config)() check_cz_config(default_choice) check_pre_commit_config([cz_hook_config]) - def test_empty_pre_commit_config(_, default_choice, tmpdir, config): + def test_empty_pre_commit_config( + _, default_choice: str, tmpdir, config: BaseConfig + ): with tmpdir.as_cwd(): p = tmpdir.join(pre_commit_config_filename) p.write("") @@ -198,7 +201,9 @@ def test_empty_pre_commit_config(_, default_choice, tmpdir, config): check_cz_config(default_choice) check_pre_commit_config([cz_hook_config]) - def test_pre_commit_config_without_cz_hook(_, default_choice, tmpdir, config): + def test_pre_commit_config_without_cz_hook( + _, default_choice: str, tmpdir, config: BaseConfig + ): existing_hook_config = { "repo": "https://github.com/pre-commit/pre-commit-hooks", "rev": "v1.2.3", @@ -213,7 +218,9 @@ def test_pre_commit_config_without_cz_hook(_, default_choice, tmpdir, config): check_cz_config(default_choice) check_pre_commit_config([existing_hook_config, cz_hook_config]) - def test_cz_hook_exists_in_pre_commit_config(_, default_choice, tmpdir, config): + def test_cz_hook_exists_in_pre_commit_config( + _, default_choice: str, tmpdir, config: BaseConfig + ): with tmpdir.as_cwd(): p = tmpdir.join(pre_commit_config_filename) p.write(yaml.safe_dump({"repos": [cz_hook_config]})) @@ -226,7 +233,7 @@ def test_cz_hook_exists_in_pre_commit_config(_, default_choice, tmpdir, config): class TestNoPreCommitInstalled: def test_pre_commit_not_installed( - _, mocker: MockFixture, config, default_choice, tmpdir + _, mocker: MockFixture, config: BaseConfig, default_choice: str, tmpdir ): # Assume `pre-commit` is not installed mocker.patch( @@ -238,7 +245,7 @@ def test_pre_commit_not_installed( commands.Init(config)() def test_pre_commit_exec_failed( - _, mocker: MockFixture, config, default_choice, tmpdir + _, mocker: MockFixture, config: BaseConfig, default_choice: str, tmpdir ): # Assume `pre-commit` is installed mocker.patch( @@ -256,14 +263,14 @@ def test_pre_commit_exec_failed( class TestAskTagFormat: - def test_confirm_v_tag_format(self, mocker: MockFixture, config): + def test_confirm_v_tag_format(self, mocker: MockFixture, config: BaseConfig): init = commands.Init(config) mocker.patch("questionary.confirm", return_value=FakeQuestion(True)) result = init._ask_tag_format("v1.0.0") assert result == r"v$version" - def test_reject_v_tag_format(self, mocker: MockFixture, config): + def test_reject_v_tag_format(self, mocker: MockFixture, config: BaseConfig): init = commands.Init(config) mocker.patch("questionary.confirm", return_value=FakeQuestion(False)) mocker.patch("questionary.text", return_value=FakeQuestion("custom-$version")) @@ -271,14 +278,14 @@ def test_reject_v_tag_format(self, mocker: MockFixture, config): result = init._ask_tag_format("v1.0.0") assert result == "custom-$version" - def test_non_v_tag_format(self, mocker: MockFixture, config): + def test_non_v_tag_format(self, mocker: MockFixture, config: BaseConfig): init = commands.Init(config) mocker.patch("questionary.text", return_value=FakeQuestion("custom-$version")) result = init._ask_tag_format("1.0.0") assert result == "custom-$version" - def test_empty_input_returns_default(self, mocker: MockFixture, config): + def test_empty_input_returns_default(self, mocker: MockFixture, config: BaseConfig): init = commands.Init(config) mocker.patch("questionary.confirm", return_value=FakeQuestion(False)) mocker.patch("questionary.text", return_value=FakeQuestion("")) @@ -300,7 +307,9 @@ def test_init_command_shows_description_when_use_help_option( file_regression.check(out, extension=".txt") -def test_init_with_confirmed_tag_format(config, mocker: MockFixture, tmpdir): +def test_init_with_confirmed_tag_format( + config: BaseConfig, mocker: MockFixture, tmpdir +): mocker.patch( "commitizen.commands.init.get_tag_names", return_value=["v0.0.2", "v0.0.1"] ) @@ -324,7 +333,7 @@ def test_init_with_confirmed_tag_format(config, mocker: MockFixture, tmpdir): assert 'tag_format = "v$version"' in toml_file.read() -def test_init_with_no_existing_tags(config, mocker: MockFixture, tmpdir): +def test_init_with_no_existing_tags(config: BaseConfig, mocker: MockFixture, tmpdir): mocker.patch("commitizen.commands.init.get_tag_names", return_value=[]) mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v1.0.0") mocker.patch( @@ -346,7 +355,9 @@ def test_init_with_no_existing_tags(config, mocker: MockFixture, tmpdir): assert 'version = "0.0.1"' in toml_file.read() -def test_init_with_no_existing_latest_tag(config, mocker: MockFixture, tmpdir): +def test_init_with_no_existing_latest_tag( + config: BaseConfig, mocker: MockFixture, tmpdir +): mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value=None) mocker.patch( "questionary.select", @@ -367,7 +378,7 @@ def test_init_with_no_existing_latest_tag(config, mocker: MockFixture, tmpdir): assert 'version = "0.0.1"' in toml_file.read() -def test_init_with_existing_tags(config, mocker: MockFixture, tmpdir): +def test_init_with_existing_tags(config: BaseConfig, mocker: MockFixture, tmpdir): expected_tags = ["v1.0.0", "v0.9.0", "v0.8.0"] mocker.patch("commitizen.commands.init.get_tag_names", return_value=expected_tags) mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v1.0.0") @@ -391,7 +402,7 @@ def test_init_with_existing_tags(config, mocker: MockFixture, tmpdir): assert 'version = "1.0.0"' in toml_file.read() -def test_init_with_valid_tag_selection(config, mocker: MockFixture, tmpdir): +def test_init_with_valid_tag_selection(config: BaseConfig, mocker: MockFixture, tmpdir): expected_tags = ["v1.0.0", "v0.9.0", "v0.8.0"] mocker.patch("commitizen.commands.init.get_tag_names", return_value=expected_tags) mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="v1.0.0") @@ -422,7 +433,7 @@ def test_init_with_valid_tag_selection(config, mocker: MockFixture, tmpdir): assert 'version_scheme = "semver"' in content -def test_init_configuration_settings(tmpdir, mocker: MockFixture, config): +def test_init_configuration_settings(tmpdir, mocker: MockFixture, config: BaseConfig): """Test that all configuration settings are properly initialized.""" mocker.patch( "questionary.select", @@ -452,7 +463,9 @@ def test_init_configuration_settings(tmpdir, mocker: MockFixture, config): assert "major_version_zero = true" in config_data -def test_init_configuration_with_version_provider(tmpdir, mocker: MockFixture, config): +def test_init_configuration_with_version_provider( + tmpdir, mocker: MockFixture, config: BaseConfig +): """Test configuration initialization with a different version provider.""" mocker.patch( "questionary.select", From 6a2c806aac8fc3c382665a477fb29f712003bb99 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 21 Sep 2025 12:18:14 +0800 Subject: [PATCH 049/221] docs: enable blank issue and add url to contact links --- .github/ISSUE_TEMPLATE/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 884fe1663a..e624b37579 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,4 +3,5 @@ blank_issues_enabled: false contact_links: - name: Security Contact + url: https://github.com/woile about: Please report security vulnerabilities to santiwilly@gmail.com From d3893307eadb3676c60c571b18f185b3e75979b6 Mon Sep 17 00:00:00 2001 From: Philip Nelson Date: Tue, 28 Oct 2025 12:38:37 -0600 Subject: [PATCH 050/221] docs: fix typo in bump command hooks description --- docs/commands/bump.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index 548f6e3616..47e64dfc6e 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -589,7 +589,7 @@ execution of the script, some environment variables are available: | `CZ_PRE_NEW_VERSION` | New version, after the bump | | `CZ_PRE_NEW_TAG_VERSION` | New version tag, after the bump | | `CZ_PRE_MESSAGE` | Commit message of the bump | -| `CZ_PRE_INCREMENT` | Whether this is a `MAJOR`, `MINOR` or `PATH` release | +| `CZ_PRE_INCREMENT` | Whether this is a `MAJOR`, `MINOR` or `PATCH` release | | `CZ_PRE_CHANGELOG_FILE_NAME` | Path to the changelog file, if available | ```toml title="pyproject.toml" @@ -616,7 +616,7 @@ release. During execution of the script, some environment variables are availabl | `CZ_POST_CURRENT_VERSION` | Current version, after the bump | | `CZ_POST_CURRENT_TAG_VERSION` | Current version tag, after the bump | | `CZ_POST_MESSAGE` | Commit message of the bump | -| `CZ_POST_INCREMENT` | Whether this was a `MAJOR`, `MINOR` or `PATH` release | +| `CZ_POST_INCREMENT` | Whether this was a `MAJOR`, `MINOR` or `PATCH` release | | `CZ_POST_CHANGELOG_FILE_NAME` | Path to the changelog file, if available | ```toml title="pyproject.toml" From ef8e4bcdd077b02440581a83ee44f56f6adff5ce Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 15 Sep 2025 19:44:16 +0800 Subject: [PATCH 051/221] refactor(BaseCommitizen): construct Style object directly to get rid of potential type error --- commitizen/cz/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index cdc1476694..75981f0747 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -5,7 +5,7 @@ from typing import Any, Callable, Protocol from jinja2 import BaseLoader, PackageLoader -from prompt_toolkit.styles import Style, merge_styles +from prompt_toolkit.styles import Style from commitizen import git from commitizen.config.base_config import BaseConfig @@ -77,12 +77,12 @@ def message(self, answers: Mapping[str, Any]) -> str: @property def style(self) -> Style: - return merge_styles( + return Style( [ - Style(BaseCommitizen.default_style_config), - Style(self.config.settings["style"]), + *BaseCommitizen.default_style_config, + *self.config.settings["style"], ] - ) # type: ignore[return-value] + ) def example(self) -> str: """Example of the commit message.""" From bdcf2aa07c556fbb1462da45d6b52c867bcdf6a6 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 15 Sep 2025 20:04:10 +0800 Subject: [PATCH 052/221] refactor(BaseCommitizen): remove NotImplementedError and make them abstract method --- commitizen/cz/base.py | 8 ++++---- tests/conftest.py | 24 ++++++++++++++++++++++ tests/test_cz_base.py | 46 ------------------------------------------- 3 files changed, 28 insertions(+), 50 deletions(-) delete mode 100644 tests/test_cz_base.py diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index 75981f0747..ecb1a21962 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -84,18 +84,18 @@ def style(self) -> Style: ] ) + @abstractmethod def example(self) -> str: """Example of the commit message.""" - raise NotImplementedError("Not Implemented yet") + @abstractmethod def schema(self) -> str: """Schema definition of the commit message.""" - raise NotImplementedError("Not Implemented yet") + @abstractmethod def schema_pattern(self) -> str: """Regex matching the schema used for message validation.""" - raise NotImplementedError("Not Implemented yet") + @abstractmethod def info(self) -> str: """Information about the standardized commit message.""" - raise NotImplementedError("Not Implemented yet") diff --git a/tests/conftest.py b/tests/conftest.py index 324ef9bebb..61b64ae8d2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -215,6 +215,18 @@ def message(self, answers: Mapping) -> str: subject = answers.get("subject", "default message").trim() return f"{prefix}: {subject}" + def example(self) -> str: + return "" + + def schema(self) -> str: + return "" + + def schema_pattern(self) -> str: + return "" + + def info(self) -> str: + return "" + @pytest.fixture() def use_cz_semver(mocker): @@ -229,6 +241,18 @@ def questions(self) -> list[CzQuestion]: def message(self, answers: Mapping) -> str: return "" + def example(self) -> str: + return "" + + def schema(self) -> str: + return "" + + def schema_pattern(self) -> str: + return "" + + def info(self) -> str: + return "" + @pytest.fixture def mock_plugin(mocker: MockerFixture, config: BaseConfig) -> BaseCommitizen: diff --git a/tests/test_cz_base.py b/tests/test_cz_base.py deleted file mode 100644 index 0ee5a23fb8..0000000000 --- a/tests/test_cz_base.py +++ /dev/null @@ -1,46 +0,0 @@ -from collections.abc import Mapping - -import pytest - -from commitizen.cz.base import BaseCommitizen - - -class DummyCz(BaseCommitizen): - def questions(self): - return [{"type": "input", "name": "commit", "message": "Initial commit:\n"}] - - def message(self, answers: Mapping): - return answers["commit"] - - -def test_base_raises_error(config): - with pytest.raises(TypeError): - BaseCommitizen(config) - - -def test_questions(config): - cz = DummyCz(config) - assert isinstance(cz.questions(), list) - - -def test_message(config): - cz = DummyCz(config) - assert cz.message({"commit": "holis"}) == "holis" - - -def test_example(config): - cz = DummyCz(config) - with pytest.raises(NotImplementedError): - cz.example() - - -def test_schema(config): - cz = DummyCz(config) - with pytest.raises(NotImplementedError): - cz.schema() - - -def test_info(config): - cz = DummyCz(config) - with pytest.raises(NotImplementedError): - cz.info() From 5db95efd15baa3ed1ce32df572d115be7d772eba Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Tue, 16 Sep 2025 21:21:53 +0800 Subject: [PATCH 053/221] style(UvProvider): fix typo in comment --- commitizen/providers/uv_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commitizen/providers/uv_provider.py b/commitizen/providers/uv_provider.py index 36c8a49ad3..21e8322d94 100644 --- a/commitizen/providers/uv_provider.py +++ b/commitizen/providers/uv_provider.py @@ -13,7 +13,7 @@ class UvProvider(TomlProvider): """ - uv.lock and pyproject.tom version management + uv.lock and pyproject.toml version management """ filename = "pyproject.toml" From 319d89e494baa352f0c92b42c9683b8385e49e17 Mon Sep 17 00:00:00 2001 From: Christian Heissenberger Date: Fri, 5 Sep 2025 20:20:52 +0200 Subject: [PATCH 054/221] feat: allow `amend!` prefix as created by `git --fixup=reword:` https://git-scm.com/docs/git-commit/2.32.0#Documentation/git-commit.txt---fixupamendrewordcommit --- commitizen/defaults.py | 1 + tests/commands/test_check_command.py | 8 ++++++++ tests/test_conf.py | 18 ++++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 94d4d97b22..4840a69b6a 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -92,6 +92,7 @@ class Settings(TypedDict, total=False): "Pull request", "fixup!", "squash!", + "amend!", ], "changelog_file": "CHANGELOG.md", "changelog_format": None, # default guessed from changelog_file diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index d95a173d8a..365a556dda 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -452,3 +452,11 @@ def test_check_command_with_message_length_limit_exceeded(config, mocker: MockFi with pytest.raises(InvalidCommitMessageError): check_cmd() error_mock.assert_called_once() + + +def test_check_command_with_amend_prefix_default(config, mocker: MockFixture): + success_mock = mocker.patch("commitizen.out.success") + check_cmd = commands.Check(config=config, arguments={"message": "amend! test"}) + + check_cmd() + success_mock.assert_called_once() diff --git a/tests/test_conf.py b/tests/test_conf.py index f89a0049f4..cc38bf4b05 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -77,7 +77,14 @@ "bump_message": None, "retry_after_failure": False, "allow_abort": False, - "allowed_prefixes": ["Merge", "Revert", "Pull request", "fixup!", "squash!"], + "allowed_prefixes": [ + "Merge", + "Revert", + "Pull request", + "fixup!", + "squash!", + "amend!", + ], "version_files": ["commitizen/__version__.py", "pyproject.toml"], "style": [["pointer", "reverse"], ["question", "underline"]], "changelog_file": "CHANGELOG.md", @@ -108,7 +115,14 @@ "bump_message": None, "retry_after_failure": False, "allow_abort": False, - "allowed_prefixes": ["Merge", "Revert", "Pull request", "fixup!", "squash!"], + "allowed_prefixes": [ + "Merge", + "Revert", + "Pull request", + "fixup!", + "squash!", + "amend!", + ], "version_files": ["commitizen/__version__.py", "pyproject.toml"], "style": [["pointer", "reverse"], ["question", "underline"]], "changelog_file": "CHANGELOG.md", From 334b8405d3f95742fe20effe53c351bf9bec4a00 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 15 Sep 2025 13:25:40 +0800 Subject: [PATCH 055/221] fix(Init): raise InitFailedError on keyboard interrupt on pre-commit hook question, simplify logic, remove unreachable code path --- commitizen/commands/init.py | 82 ++++++++++++----------------- tests/commands/test_init_command.py | 29 ++-------- 2 files changed, 37 insertions(+), 74 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 2ce3981f44..92e7d06d7d 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -150,9 +150,43 @@ def __call__(self) -> None: tag_format = self._ask_tag_format(tag) # confirm & text update_changelog_on_bump = self._ask_update_changelog_on_bump() # confirm major_version_zero = self._ask_major_version_zero(version) # confirm + hook_types: list[str] | None = questionary.checkbox( + "What types of pre-commit hook you want to install? (Leave blank if you don't want to install)", + choices=[ + questionary.Choice("commit-msg", checked=False), + questionary.Choice("pre-push", checked=False), + ], + ).unsafe_ask() except KeyboardInterrupt: raise InitFailedError("Stopped by user") + if hook_types: + config_data = self._get_config_data() + with smart_open( + self._PRE_COMMIT_CONFIG_PATH, "w", encoding=self.encoding + ) as config_file: + yaml.safe_dump(config_data, stream=config_file) + + if not self.project_info.is_pre_commit_installed: + raise InitFailedError( + "Failed to install pre-commit hook.\n" + "pre-commit is not installed in current environment." + ) + + cmd_str = "pre-commit install " + " ".join( + f"--hook-type {ty}" for ty in hook_types + ) + c = cmd.run(cmd_str) + if c.return_code != 0: + raise InitFailedError( + "Failed to install pre-commit hook.\n" + f"Error running {cmd_str}." + "Outputs are attached below:\n" + f"stdout: {c.out}\n" + f"stderr: {c.err}" + ) + out.write("commitizen pre-commit hook is now installed in your '.git'\n") + # Initialize configuration if "toml" in config_path: self.config = TomlConfig(data="", path=config_path) @@ -161,20 +195,6 @@ def __call__(self) -> None: elif "yaml" in config_path: self.config = YAMLConfig(data="", path=config_path) - # Collect hook data - hook_types = questionary.checkbox( - "What types of pre-commit hook you want to install? (Leave blank if you don't want to install)", - choices=[ - questionary.Choice("commit-msg", checked=False), - questionary.Choice("pre-push", checked=False), - ], - ).unsafe_ask() - if hook_types: - try: - self._install_pre_commit_hook(hook_types) - except InitFailedError as e: - raise InitFailedError(f"Failed to install pre-commit hook.\n{e}") - # Create and initialize config self.config.init_empty_config_content() @@ -321,26 +341,6 @@ def _ask_update_changelog_on_bump(self) -> bool: ).unsafe_ask() return update_changelog_on_bump - def _exec_install_pre_commit_hook(self, hook_types: list[str]) -> None: - cmd_str = self._gen_pre_commit_cmd(hook_types) - c = cmd.run(cmd_str) - if c.return_code != 0: - err_msg = ( - f"Error running {cmd_str}." - "Outputs are attached below:\n" - f"stdout: {c.out}\n" - f"stderr: {c.err}" - ) - raise InitFailedError(err_msg) - - def _gen_pre_commit_cmd(self, hook_types: list[str]) -> str: - """Generate pre-commit command according to given hook types""" - if not hook_types: - raise ValueError("At least 1 hook type should be provided.") - return "pre-commit install " + " ".join( - f"--hook-type {ty}" for ty in hook_types - ) - def _get_config_data(self) -> dict[str, Any]: CZ_HOOK_CONFIG = { "repo": "https://github.com/commitizen-tools/commitizen", @@ -369,17 +369,3 @@ def _get_config_data(self) -> dict[str, Any]: else: repos.append(CZ_HOOK_CONFIG) return config_data - - def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None: - config_data = self._get_config_data() - with smart_open( - self._PRE_COMMIT_CONFIG_PATH, "w", encoding=self.encoding - ) as config_file: - yaml.safe_dump(config_data, stream=config_file) - - if not self.project_info.is_pre_commit_installed: - raise InitFailedError("pre-commit is not installed in current environment.") - if hook_types is None: - hook_types = ["commit-msg", "pre-push"] - self._exec_install_pre_commit_hook(hook_types) - out.write("commitizen pre-commit hook is now installed in your '.git'\n") diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index ba4a150622..8c632a2b67 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -9,7 +9,7 @@ import yaml from pytest_mock import MockFixture -from commitizen import cli, commands +from commitizen import cli, cmd, commands from commitizen.__version__ import __version__ from commitizen.config.base_config import BaseConfig from commitizen.exceptions import InitFailedError, NoAnswersError @@ -117,12 +117,6 @@ def test_init_without_choosing_tag(config: BaseConfig, mocker: MockFixture, tmpd commands.Init(config)() -def test_executed_pre_commit_command(config: BaseConfig): - init = commands.Init(config) - expected_cmd = "pre-commit install --hook-type commit-msg --hook-type pre-push" - assert init._gen_pre_commit_cmd(["commit-msg", "pre-push"]) == expected_cmd - - @pytest.fixture(scope="function") def pre_commit_installed(mocker: MockFixture): # Assume the `pre-commit` is installed @@ -132,8 +126,8 @@ def pre_commit_installed(mocker: MockFixture): ) # And installation success (i.e. no exception raised) mocker.patch( - "commitizen.commands.init.Init._exec_install_pre_commit_hook", - return_value=None, + "commitizen.cmd.run", + return_value=cmd.Command("0.0.1", "", b"", b"", 0), ) @@ -244,23 +238,6 @@ def test_pre_commit_not_installed( with pytest.raises(InitFailedError): commands.Init(config)() - def test_pre_commit_exec_failed( - _, mocker: MockFixture, config: BaseConfig, default_choice: str, tmpdir - ): - # Assume `pre-commit` is installed - mocker.patch( - "commitizen.commands.init.ProjectInfo.is_pre_commit_installed", - return_value=True, - ) - # But pre-commit installation will fail - mocker.patch( - "commitizen.commands.init.Init._exec_install_pre_commit_hook", - side_effect=InitFailedError("Mock init failed error."), - ) - with tmpdir.as_cwd(): - with pytest.raises(InitFailedError): - commands.Init(config)() - class TestAskTagFormat: def test_confirm_v_tag_format(self, mocker: MockFixture, config: BaseConfig): From 0a77488e240ab0742436a5cdbd800d8db4cba592 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 21 Sep 2025 00:43:07 +0800 Subject: [PATCH 056/221] test(changelog): remove unused timer fixture --- tests/commands/test_changelog_command.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index 1f3dabd761..f147c419b8 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -884,7 +884,6 @@ def test_changelog_with_filename_as_empty_string( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_first_version_from_arg( mocker: MockFixture, config_path, changelog_path, file_regression ): @@ -918,7 +917,6 @@ def test_changelog_from_rev_first_version_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_latest_version_from_arg( mocker: MockFixture, config_path, changelog_path, file_regression ): @@ -954,7 +952,6 @@ def test_changelog_from_rev_latest_version_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") @pytest.mark.parametrize( "rev_range,tag", ( @@ -986,7 +983,6 @@ def test_changelog_from_rev_range_not_found( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_multiple_matching_tags( mocker: MockFixture, config_path, changelog_path ): @@ -1016,7 +1012,6 @@ def test_changelog_multiple_matching_tags( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_range_default_tag_format( mocker, config_path, changelog_path ): @@ -1047,7 +1042,6 @@ def test_changelog_from_rev_range_default_tag_format( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_range_including_first_tag( mocker: MockFixture, config_path, changelog_path, file_regression ): @@ -1079,7 +1073,6 @@ def test_changelog_from_rev_version_range_including_first_tag( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_range_from_arg( mocker: MockFixture, config_path, changelog_path, file_regression ): @@ -1119,7 +1112,6 @@ def test_changelog_from_rev_version_range_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_range_with_legacy_tags( mocker: MockFixture, config_path, changelog_path, file_regression ): @@ -1154,7 +1146,6 @@ def test_changelog_from_rev_version_range_with_legacy_tags( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_with_big_range_from_arg( mocker: MockFixture, config_path, changelog_path, file_regression ): @@ -1214,7 +1205,6 @@ def test_changelog_from_rev_version_with_big_range_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_latest_version_dry_run( mocker: MockFixture, capsys, config_path, changelog_path, file_regression ): @@ -1267,7 +1257,6 @@ def test_invalid_subject_is_skipped(mocker: MockFixture, capsys): assert out == ("## Unreleased\n\n### Feat\n\n- a new world\n\n") -@pytest.mark.freeze_time("2022-02-13") @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_with_customized_change_type_order( mocker, config_path, changelog_path, file_regression @@ -1325,7 +1314,6 @@ def test_empty_commit_list(mocker): @pytest.mark.usefixtures("tmp_commitizen_project") -@pytest.mark.freeze_time("2022-02-13") def test_changelog_prerelease_rev_with_use_scheme_semver( mocker: MockFixture, capsys, config_path, changelog_path, file_regression ): From e34bc55f2d8fef6cbc21c6a28204f284cff2e7e9 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 22 Sep 2025 17:20:51 +0800 Subject: [PATCH 057/221] refactor(cmd): unnest try except --- commitizen/cmd.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/commitizen/cmd.py b/commitizen/cmd.py index 3f13087233..c8d4f33010 100644 --- a/commitizen/cmd.py +++ b/commitizen/cmd.py @@ -22,13 +22,15 @@ def _try_decode(bytes_: bytes) -> str: try: return bytes_.decode("utf-8") except UnicodeDecodeError: - charset_match = from_bytes(bytes_).best() - if charset_match is None: - raise CharacterSetDecodeError() - try: - return bytes_.decode(charset_match.encoding) - except UnicodeDecodeError as e: - raise CharacterSetDecodeError() from e + pass + + charset_match = from_bytes(bytes_).best() + if charset_match is None: + raise CharacterSetDecodeError() + try: + return bytes_.decode(charset_match.encoding) + except UnicodeDecodeError as e: + raise CharacterSetDecodeError() from e def run(cmd: str, env: Mapping[str, str] | None = None) -> Command: From 293645f7d58fc89542dd61a3d9685a3ee80aa468 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 21 Sep 2025 11:40:37 +0800 Subject: [PATCH 058/221] refactor(ConventionalCommitsCz): rewrite message method to make the pattern more clear --- .../cz/conventional_commits/conventional_commits.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/commitizen/cz/conventional_commits/conventional_commits.py b/commitizen/cz/conventional_commits/conventional_commits.py index 6893423478..c827cebb78 100644 --- a/commitizen/cz/conventional_commits/conventional_commits.py +++ b/commitizen/cz/conventional_commits/conventional_commits.py @@ -155,15 +155,16 @@ def message(self, answers: ConventionalCommitsAnswers) -> str: # type: ignore[o is_breaking_change = answers["is_breaking_change"] if scope: - scope = f"({scope})" - if body: - body = f"\n\n{body}" + # example: "fix(users): email pattern corrected" + first_line = f"{prefix}({scope}): {subject}" + else: + # example: "fix: email pattern corrected" + first_line = f"{prefix}: {subject}" + if is_breaking_change: footer = f"BREAKING CHANGE: {footer}" - if footer: - footer = f"\n\n{footer}" - return f"{prefix}{scope}: {subject}{body}{footer}" + return "\n\n".join(s for s in (first_line, body, footer) if s) def example(self) -> str: return ( From 3fdd15f82eb9f467377dcb275ff3f473d4ad698b Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 21 Sep 2025 00:24:12 +0800 Subject: [PATCH 059/221] refactor(Bump): remove use of getattr --- commitizen/commands/bump.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 07338afb86..fc9649c6c5 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -216,8 +216,8 @@ def __call__(self) -> None: rules = TagRules.from_settings(cast(Settings, self.bump_settings)) current_tag = rules.find_tag_for(git.get_tags(), current_version) - current_tag_version = getattr( - current_tag, "name", rules.normalize_tag(current_version) + current_tag_version = ( + current_tag.name if current_tag else rules.normalize_tag(current_version) ) is_initial = self._is_initial_tag(current_tag, self.arguments["yes"]) From 9c616c36402e692ec7ec2f39e25e2a02e997c6d5 Mon Sep 17 00:00:00 2001 From: Santiago Fraire Willemoes Date: Thu, 30 Oct 2025 07:47:06 +0000 Subject: [PATCH 060/221] docs: add contributing for nix users --- docs/contributing.md | 16 +++++++++++++++- docs/contributing_tldr.md | 13 ++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index 8389e9370d..4a068cf640 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -38,7 +38,7 @@ If you're a first-time contributor, please check out issues labeled [good first ```bash git remote add upstream https://github.com/commitizen-tools/commitizen.git ``` -4. Set up the development environment: +4. Set up the development environment (nix users go to [nix section](#nix)): ```bash poetry install ``` @@ -70,6 +70,7 @@ If you're a first-time contributor, please check out issues labeled [good first 5. **Documentation** - Update `docs/README.md` if needed - For CLI help screenshots: `poetry doc:screenshots` + - Prefer [Google style documentation](https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings), which works well with editors like VSCode and PyCharm - **DO NOT** update `CHANGELOG.md` (automatically generated) - **DO NOT** update version numbers (automatically handled) 6. **Pull Request** @@ -153,3 +154,16 @@ flowchart TD --modification-received--> review ``` + +## Nix + +If you have installed poetry globally, the project won't work because it requries `poethepoet` for command management. + +You'll have to install poetry locally. + +```sh +python -m venv .venv +. .venv/bin/activate +pip install -U pip && pip install poetry +poetry install +``` diff --git a/docs/contributing_tldr.md b/docs/contributing_tldr.md index f5483cddcd..9eecc3efa0 100644 --- a/docs/contributing_tldr.md +++ b/docs/contributing_tldr.md @@ -12,7 +12,7 @@ Please check the [pyproject.toml](https://github.com/commitizen-tools/commitizen ### Code Changes ```bash -# Ensure you have the correct dependencies +# Ensure you have the correct dependencies, for nix user's see below poetry install # Make ruff happy @@ -35,3 +35,14 @@ pytest -n auto # Build the documentation locally and check for broken links poetry doc ``` + +### Nix Users + +If you are using Nix, you can install poetry locally by running: + +```sh +python -m venv .venv +. .venv/bin/activate +pip install -U pip && pip install poetry +poetry install +``` From 459d83a647904987c2bf1967541321208f07a9d0 Mon Sep 17 00:00:00 2001 From: Santiago Fraire Willemoes Date: Thu, 30 Oct 2025 08:28:48 +0000 Subject: [PATCH 061/221] feat(version): add the ability to just print major or minor version --- commitizen/cli.py | 12 +++ commitizen/commands/version.py | 16 +++- commitizen/version_schemes.py | 4 +- docs/contributing.md | 2 +- docs/images/cli_help/cz_version___help.svg | 82 ++++++++++--------- tests/commands/test_version_command.py | 37 +++++++++ ...shows_description_when_use_help_option.txt | 4 +- 7 files changed, 116 insertions(+), 41 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index ed4305ea1f..e9689d75f3 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -543,6 +543,18 @@ def __call__( "action": "store_true", "exclusive_group": "group1", }, + { + "name": ["--major"], + "help": "get just the major version", + "action": "store_true", + "exclusive_group": "group2", + }, + { + "name": ["--minor"], + "help": "get just the minor version", + "action": "store_true", + "exclusive_group": "group2", + }, ], }, ], diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 35e9aa6cd6..04fa664f25 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -5,14 +5,17 @@ from commitizen import out from commitizen.__version__ import __version__ from commitizen.config import BaseConfig -from commitizen.exceptions import NoVersionSpecifiedError +from commitizen.exceptions import NoVersionSpecifiedError, VersionSchemeUnknown from commitizen.providers import get_provider +from commitizen.version_schemes import get_version_scheme class VersionArgs(TypedDict, total=False): report: bool project: bool verbose: bool + major: bool + minor: bool class Version: @@ -41,6 +44,17 @@ def __call__(self) -> None: out.error("No project information in this project.") return + try: + version_scheme = get_version_scheme(self.config.settings) + except VersionSchemeUnknown: + out.error("Unknown version scheme.") + _version = version_scheme(version) + + if self.parameter.get("major"): + version = f"{_version.major}" + elif self.parameter.get("minor"): + version = f"{_version.minor}" + out.write(f"Project Version: {version}" if verbose else version) return diff --git a/commitizen/version_schemes.py b/commitizen/version_schemes.py index e9f99c5514..0696d85aa5 100644 --- a/commitizen/version_schemes.py +++ b/commitizen/version_schemes.py @@ -410,7 +410,9 @@ def _get_prerelease(self) -> str: def get_version_scheme(settings: Settings, name: str | None = None) -> VersionScheme: """ Get the version scheme as defined in the configuration - or from an overridden `name` + or from an overridden `name`. + + :raises VersionSchemeUnknown: if the version scheme is not found. """ diff --git a/docs/contributing.md b/docs/contributing.md index 4a068cf640..16db930626 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -157,7 +157,7 @@ flowchart TD ## Nix -If you have installed poetry globally, the project won't work because it requries `poethepoet` for command management. +If you have installed poetry globally, the project won't work because it requires `poethepoet` for command management. You'll have to install poetry locally. diff --git a/docs/images/cli_help/cz_version___help.svg b/docs/images/cli_help/cz_version___help.svg index c7777db4df..7ddec177d8 100644 --- a/docs/images/cli_help/cz_version___help.svg +++ b/docs/images/cli_help/cz_version___help.svg @@ -1,4 +1,4 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - + - + - - $ cz version --help -usage: cz version [-h][-r | -p | -c | -v] - -get the version of the installed commitizen or the current project (default: -installed commitizen) - -options: -  -h, --help        show this help message and exit -  -r, --report      get system information for reporting bugs -  -p, --project     get the version of the current project -  -c, --commitizen  get the version of the installed commitizen -  -v, --verbose     get the version of both the installed commitizen and the -                    current project - + + $ cz version --help +usage: cz version [-h][-r | -p | -c | -v][--major | --minor] + +get the version of the installed commitizen or the current project (default: +installed commitizen) + +options: +  -h, --help        show this help message and exit +  -r, --report      get system information for reporting bugs +  -p, --project     get the version of the current project +  -c, --commitizen  get the version of the installed commitizen +  -v, --verbose     get the version of both the installed commitizen and the +                    current project +  --major           get just the major version +  --minor           get just the minor version + diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 3dcbed168b..cd2e7f77e0 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -119,3 +119,40 @@ def test_version_command_shows_description_when_use_help_option( out, _ = capsys.readouterr() file_regression.check(out, extension=".txt") + + +@pytest.mark.parametrize( + "version, expected_version", (("1.0.0", "1\n"), ("2.1.3", "2\n"), ("0.0.1", "0\n")) +) +def test_version_just_major(config, capsys, version: str, expected_version: str): + config.settings["version"] = version + commands.Version( + config, + { + "report": False, + "project": True, + "verbose": False, + "major": True, + }, + )() + captured = capsys.readouterr() + assert expected_version == captured.out + + +@pytest.mark.parametrize( + "version, expected_version", + (("1.0.0", "0\n"), ("2.1.3", "1\n"), ("0.0.1", "0\n"), ("0.1.0", "1\n")), +) +def test_version_just_minor(config, capsys, version: str, expected_version: str): + config.settings["version"] = version + commands.Version( + config, + { + "report": False, + "project": True, + "verbose": False, + "minor": True, + }, + )() + captured = capsys.readouterr() + assert expected_version == captured.out diff --git a/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt b/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt index c461b10bcd..b1ed94124e 100644 --- a/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt +++ b/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] get the version of the installed commitizen or the current project (default: installed commitizen) @@ -10,3 +10,5 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project + --major get just the major version + --minor get just the minor version From 056a02608babdf7bd849039545c5ef628f906b8e Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sat, 20 Sep 2025 01:17:54 +0800 Subject: [PATCH 062/221] refactor: remove unnecessary class member tag_format --- commitizen/changelog_formats/base.py | 3 +-- commitizen/commands/changelog.py | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/commitizen/changelog_formats/base.py b/commitizen/changelog_formats/base.py index cb5d385bf8..0a76ad68f9 100644 --- a/commitizen/changelog_formats/base.py +++ b/commitizen/changelog_formats/base.py @@ -25,10 +25,9 @@ def __init__(self, config: BaseConfig) -> None: # See: https://bugs.python.org/issue44807 self.config = config self.encoding = self.config.settings["encoding"] - self.tag_format = self.config.settings["tag_format"] self.tag_rules = TagRules( scheme=get_version_scheme(self.config.settings), - tag_format=self.tag_format, + tag_format=self.config.settings["tag_format"], legacy_tag_formats=self.config.settings["legacy_tag_formats"], ignored_tag_formats=self.config.settings["ignored_tag_formats"], ) diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index 0fffd8ed7c..c739419b8d 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -104,12 +104,10 @@ def __init__(self, config: BaseConfig, arguments: ChangelogArgs) -> None: or defaults.CHANGE_TYPE_ORDER, ) self.rev_range = arguments.get("rev_range") - self.tag_format = ( - arguments.get("tag_format") or self.config.settings["tag_format"] - ) self.tag_rules = TagRules( scheme=self.scheme, - tag_format=self.tag_format, + tag_format=arguments.get("tag_format") + or self.config.settings["tag_format"], legacy_tag_formats=self.config.settings["legacy_tag_formats"], ignored_tag_formats=self.config.settings["ignored_tag_formats"], merge_prereleases=arguments.get("merge_prerelease") From 71eba5a0d5222ff518eece792b771a415a15e30e Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 29 Sep 2025 11:42:31 +0800 Subject: [PATCH 063/221] refactor(utils): make get_backup_file_path to return a path for semantic correctness --- commitizen/commands/commit.py | 28 +++++++++++++-------------- commitizen/cz/utils.py | 6 +++--- hooks/post-commit.py | 7 +++---- hooks/prepare-commit-msg.py | 9 ++++----- tests/commands/test_commit_command.py | 8 ++++---- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 19bb72fb00..0a6349303c 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -51,15 +51,15 @@ def __init__(self, config: BaseConfig, arguments: CommitArgs) -> None: self.encoding = config.settings["encoding"] self.cz = factory.committer_factory(self.config) self.arguments = arguments - self.temp_file: str = get_backup_file_path() + self.backup_file_path = get_backup_file_path() def _read_backup_message(self) -> str | None: # Check the commit backup file exists - if not os.path.isfile(self.temp_file): + if not self.backup_file_path.is_file(): return None # Read commit message from backup - with open(self.temp_file, encoding=self.encoding) as f: + with open(self.backup_file_path, encoding=self.encoding) as f: return f.read().strip() def _prompt_commit_questions(self) -> str: @@ -108,10 +108,10 @@ def manual_edit(self, message: str) -> str: def _get_message(self) -> str: if self.arguments.get("retry"): - m = self._read_backup_message() - if m is None: + commit_message = self._read_backup_message() + if commit_message is None: raise NoCommitBackupError() - return m + return commit_message if self.config.settings.get("retry_after_failure") and not self.arguments.get( "no_retry" @@ -139,15 +139,15 @@ def __call__(self) -> None: if write_message_to_file is not None and write_message_to_file.is_dir(): raise NotAllowed(f"{write_message_to_file} is a directory") - m = self._get_message() + commit_message = self._get_message() if self.arguments.get("edit"): - m = self.manual_edit(m) + commit_message = self.manual_edit(commit_message) - out.info(f"\n{m}\n") + out.info(f"\n{commit_message}\n") if write_message_to_file: with smart_open(write_message_to_file, "w", encoding=self.encoding) as file: - file.write(m) + file.write(commit_message) if dry_run: raise DryRunExit() @@ -155,13 +155,13 @@ def __call__(self) -> None: if self.config.settings["always_signoff"] or signoff: extra_args = f"{extra_args} -s".strip() - c = git.commit(m, args=extra_args) + c = git.commit(commit_message, args=extra_args) if c.return_code != 0: out.error(c.err) # Create commit backup - with smart_open(self.temp_file, "w", encoding=self.encoding) as f: - f.write(m) + with smart_open(self.backup_file_path, "w", encoding=self.encoding) as f: + f.write(commit_message) raise CommitError() @@ -170,7 +170,7 @@ def __call__(self) -> None: return with contextlib.suppress(FileNotFoundError): - os.remove(self.temp_file) + self.backup_file_path.unlink() out.write(c.err) out.write(c.out) out.success("Commit successful!") diff --git a/commitizen/cz/utils.py b/commitizen/cz/utils.py index a6f687226c..ba5eace44a 100644 --- a/commitizen/cz/utils.py +++ b/commitizen/cz/utils.py @@ -1,6 +1,7 @@ import os import re import tempfile +from pathlib import Path from commitizen import git from commitizen.cz import exceptions @@ -22,10 +23,9 @@ def strip_local_version(version: str) -> str: return _RE_LOCAL_VERSION.sub("", version) -def get_backup_file_path() -> str: +def get_backup_file_path() -> Path: project_root = git.find_git_project_root() project = project_root.as_posix().replace("/", "%") if project_root else "" user = os.environ.get("USER", "") - - return os.path.join(tempfile.gettempdir(), f"cz.commit%{user}%{project}.backup") + return Path(tempfile.gettempdir(), f"cz.commit%{user}%{project}.backup") diff --git a/hooks/post-commit.py b/hooks/post-commit.py index c7dea825bd..d242b6b354 100755 --- a/hooks/post-commit.py +++ b/hooks/post-commit.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from pathlib import Path try: from commitizen.cz.utils import get_backup_file_path @@ -9,11 +8,11 @@ def post_commit() -> None: - backup_file = Path(get_backup_file_path()) + backup_file_path = get_backup_file_path() # remove backup file if it exists - if backup_file.is_file(): - backup_file.unlink() + if backup_file_path.is_file(): + backup_file_path.unlink() if __name__ == "__main__": diff --git a/hooks/prepare-commit-msg.py b/hooks/prepare-commit-msg.py index e666fa673b..a100f13afa 100755 --- a/hooks/prepare-commit-msg.py +++ b/hooks/prepare-commit-msg.py @@ -2,7 +2,6 @@ import shutil import subprocess import sys -from pathlib import Path from subprocess import CalledProcessError try: @@ -25,12 +24,12 @@ def prepare_commit_msg(commit_msg_file: str) -> int: capture_output=True, ).returncode if exit_code != 0: - backup_file = Path(get_backup_file_path()) - if backup_file.is_file(): + backup_file_path = get_backup_file_path() + if backup_file_path.is_file(): # confirm if commit message from backup file should be reused answer = input("retry with previous message? [y/N]: ") if answer.lower() == "y": - shutil.copyfile(backup_file, commit_msg_file) + shutil.copyfile(backup_file_path, commit_msg_file) return 0 # use commitizen to generate the commit message @@ -50,7 +49,7 @@ def prepare_commit_msg(commit_msg_file: str) -> int: return error.returncode # write message to backup file - shutil.copyfile(commit_msg_file, backup_file) + shutil.copyfile(commit_msg_file, backup_file_path) return 0 diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index 930e1a7a9b..8d0181f3e0 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -73,7 +73,7 @@ def test_commit_backup_on_failure(config, mocker: MockFixture): with pytest.raises(CommitError): commit_cmd = commands.Commit(config, {}) - temp_file = commit_cmd.temp_file + temp_file = commit_cmd.backup_file_path commit_cmd() prompt_mock.assert_called_once() @@ -101,7 +101,7 @@ def test_commit_retry_works(config, mocker: MockFixture): success_mock = mocker.patch("commitizen.out.success") commit_cmd = commands.Commit(config, {"retry": True}) - temp_file = commit_cmd.temp_file + temp_file = commit_cmd.backup_file_path commit_cmd() commit_mock.assert_called_with("backup commit", args="") @@ -144,7 +144,7 @@ def test_commit_retry_after_failure_works(config, mocker: MockFixture): config.settings["retry_after_failure"] = True commit_cmd = commands.Commit(config, {}) - temp_file = commit_cmd.temp_file + temp_file = commit_cmd.backup_file_path commit_cmd() commit_mock.assert_called_with("backup commit", args="") @@ -171,7 +171,7 @@ def test_commit_retry_after_failure_with_no_retry_works(config, mocker: MockFixt config.settings["retry_after_failure"] = True commit_cmd = commands.Commit(config, {"no_retry": True}) - temp_file = commit_cmd.temp_file + temp_file = commit_cmd.backup_file_path commit_cmd() commit_mock.assert_called_with("feat: user created\n\ncloses #21", args="") From 41835eacb07305ecf16df30bcdc099d22bd0371d Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sat, 20 Sep 2025 01:02:02 +0800 Subject: [PATCH 064/221] docs(Check): add missing raise exception in __call__ --- commitizen/commands/check.py | 1 + 1 file changed, 1 insertion(+) diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index e6ebc928ed..b79e6609e0 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -79,6 +79,7 @@ def __call__(self) -> None: Raises: InvalidCommitMessageError: if the commit provided not follows the conventional pattern + NoCommitsFoundError: if no commit is found with the given range """ commits = self._get_commits() if not commits: From 183301a65deb11f005ffdf6d1d6ce3165cd55712 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sat, 13 Sep 2025 17:25:15 +0800 Subject: [PATCH 065/221] test(SemVer): refine tests and remove unnecessary tests which test the behavior of library, improve readability with NamedTuple --- tests/test_version_scheme_pep440.py | 1629 +++++++++++++++++++++----- tests/test_version_scheme_semver.py | 1084 +++++++++++++---- tests/test_version_scheme_semver2.py | 824 ++++++++++--- tests/utils.py | 10 + 4 files changed, 2831 insertions(+), 716 deletions(-) diff --git a/tests/test_version_scheme_pep440.py b/tests/test_version_scheme_pep440.py index a983dad14a..0ce4f81545 100644 --- a/tests/test_version_scheme_pep440.py +++ b/tests/test_version_scheme_pep440.py @@ -1,258 +1,1356 @@ -import itertools -import random - import pytest from commitizen.version_schemes import Pep440, VersionProtocol - -simple_flow = [ - (("0.1.0", "PATCH", None, 0, None), "0.1.1"), - (("0.1.0", "PATCH", None, 0, 1), "0.1.1.dev1"), - (("0.1.1", "MINOR", None, 0, None), "0.2.0"), - (("0.2.0", "MINOR", None, 0, None), "0.3.0"), - (("0.2.0", "MINOR", None, 0, 1), "0.3.0.dev1"), - (("0.3.0", "PATCH", None, 0, None), "0.3.1"), - (("0.3.0", "PATCH", "alpha", 0, None), "0.3.1a0"), - (("0.3.1a0", None, "alpha", 0, None), "0.3.1a1"), - (("0.3.0", "PATCH", "alpha", 1, None), "0.3.1a1"), - (("0.3.1a0", None, "alpha", 1, None), "0.3.1a1"), - (("0.3.1a0", None, None, 0, None), "0.3.1"), - (("0.3.1", "PATCH", None, 0, None), "0.3.2"), - (("0.4.2", "MAJOR", "alpha", 0, None), "1.0.0a0"), - (("1.0.0a0", None, "alpha", 0, None), "1.0.0a1"), - (("1.0.0a1", None, "alpha", 0, None), "1.0.0a2"), - (("1.0.0a1", None, "alpha", 0, 1), "1.0.0a2.dev1"), - (("1.0.0a2.dev0", None, "alpha", 0, 1), "1.0.0a3.dev1"), - (("1.0.0a2.dev0", None, "alpha", 0, 0), "1.0.0a3.dev0"), - (("1.0.0a1", None, "beta", 0, None), "1.0.0b0"), - (("1.0.0b0", None, "beta", 0, None), "1.0.0b1"), - (("1.0.0b1", None, "rc", 0, None), "1.0.0rc0"), - (("1.0.0rc0", None, "rc", 0, None), "1.0.0rc1"), - (("1.0.0rc0", None, "rc", 0, 1), "1.0.0rc1.dev1"), - (("1.0.0rc0", "PATCH", None, 0, None), "1.0.0"), - (("1.0.0a3.dev0", None, "beta", 0, None), "1.0.0b0"), - (("1.0.0", "PATCH", None, 0, None), "1.0.1"), - (("1.0.1", "PATCH", None, 0, None), "1.0.2"), - (("1.0.2", "MINOR", None, 0, None), "1.1.0"), - (("1.1.0", "MINOR", None, 0, None), "1.2.0"), - (("1.2.0", "PATCH", None, 0, None), "1.2.1"), - (("1.2.1", "MAJOR", None, 0, None), "2.0.0"), -] - -local_versions = [ - (("4.5.0+0.1.0", "PATCH", None, 0, None), "4.5.0+0.1.1"), - (("4.5.0+0.1.1", "MINOR", None, 0, None), "4.5.0+0.2.0"), - (("4.5.0+0.2.0", "MAJOR", None, 0, None), "4.5.0+1.0.0"), -] - -# never bump backwards on pre-releases -linear_prerelease_cases = [ - (("0.1.1b1", None, "alpha", 0, None), "0.1.1b2"), - (("0.1.1rc0", None, "alpha", 0, None), "0.1.1rc1"), - (("0.1.1rc0", None, "beta", 0, None), "0.1.1rc1"), -] - -weird_cases = [ - (("1.1", "PATCH", None, 0, None), "1.1.1"), - (("1", "MINOR", None, 0, None), "1.1.0"), - (("1", "MAJOR", None, 0, None), "2.0.0"), - (("1a0", None, "alpha", 0, None), "1.0.0a1"), - (("1a0", None, "alpha", 1, None), "1.0.0a1"), - (("1", None, "beta", 0, None), "1.0.0b0"), - (("1", None, "beta", 1, None), "1.0.0b1"), - (("1beta", None, "beta", 0, None), "1.0.0b1"), - (("1.0.0alpha1", None, "alpha", 0, None), "1.0.0a2"), - (("1", None, "rc", 0, None), "1.0.0rc0"), - (("1.0.0rc1+e20d7b57f3eb", "PATCH", None, 0, None), "1.0.0"), -] - -# test driven development -tdd_cases = [ - (("0.1.1", "PATCH", None, 0, None), "0.1.2"), - (("0.1.1", "MINOR", None, 0, None), "0.2.0"), - (("2.1.1", "MAJOR", None, 0, None), "3.0.0"), - (("0.9.0", "PATCH", "alpha", 0, None), "0.9.1a0"), - (("0.9.0", "MINOR", "alpha", 0, None), "0.10.0a0"), - (("0.9.0", "MAJOR", "alpha", 0, None), "1.0.0a0"), - (("0.9.0", "MAJOR", "alpha", 1, None), "1.0.0a1"), - (("1.0.0a2", None, "beta", 0, None), "1.0.0b0"), - (("1.0.0a2", None, "beta", 1, None), "1.0.0b1"), - (("1.0.0beta1", None, "rc", 0, None), "1.0.0rc0"), - (("1.0.0rc1", None, "rc", 0, None), "1.0.0rc2"), -] - -# additional pre-release tests run through various release scenarios -prerelease_cases = [ - # - (("3.3.3", "PATCH", "alpha", 0, None), "3.3.4a0"), - (("3.3.4a0", "PATCH", "alpha", 0, None), "3.3.4a1"), - (("3.3.4a1", "MINOR", "alpha", 0, None), "3.4.0a0"), - (("3.4.0a0", "PATCH", "alpha", 0, None), "3.4.0a1"), - (("3.4.0a1", "MINOR", "alpha", 0, None), "3.4.0a2"), - (("3.4.0a2", "MAJOR", "alpha", 0, None), "4.0.0a0"), - (("4.0.0a0", "PATCH", "alpha", 0, None), "4.0.0a1"), - (("4.0.0a1", "MINOR", "alpha", 0, None), "4.0.0a2"), - (("4.0.0a2", "MAJOR", "alpha", 0, None), "4.0.0a3"), - # - (("1.0.0", "PATCH", "alpha", 0, None), "1.0.1a0"), - (("1.0.1a0", "PATCH", "alpha", 0, None), "1.0.1a1"), - (("1.0.1a1", "MINOR", "alpha", 0, None), "1.1.0a0"), - (("1.1.0a0", "PATCH", "alpha", 0, None), "1.1.0a1"), - (("1.1.0a1", "MINOR", "alpha", 0, None), "1.1.0a2"), - (("1.1.0a2", "MAJOR", "alpha", 0, None), "2.0.0a0"), - # - (("1.0.0", "MINOR", "alpha", 0, None), "1.1.0a0"), - (("1.1.0a0", "PATCH", "alpha", 0, None), "1.1.0a1"), - (("1.1.0a1", "MINOR", "alpha", 0, None), "1.1.0a2"), - (("1.1.0a2", "PATCH", "alpha", 0, None), "1.1.0a3"), - (("1.1.0a3", "MAJOR", "alpha", 0, None), "2.0.0a0"), - # - (("1.0.0", "MAJOR", "alpha", 0, None), "2.0.0a0"), - (("2.0.0a0", "MINOR", "alpha", 0, None), "2.0.0a1"), - (("2.0.0a1", "PATCH", "alpha", 0, None), "2.0.0a2"), - (("2.0.0a2", "MAJOR", "alpha", 0, None), "2.0.0a3"), - (("2.0.0a3", "MINOR", "alpha", 0, None), "2.0.0a4"), - (("2.0.0a4", "PATCH", "alpha", 0, None), "2.0.0a5"), - (("2.0.0a5", "MAJOR", "alpha", 0, None), "2.0.0a6"), - # - (("2.0.0b0", "MINOR", "alpha", 0, None), "2.0.0b1"), - (("2.0.0b0", "PATCH", "alpha", 0, None), "2.0.0b1"), - # - (("1.0.1a0", "PATCH", None, 0, None), "1.0.1"), - (("1.0.1a0", "MINOR", None, 0, None), "1.1.0"), - (("1.0.1a0", "MAJOR", None, 0, None), "2.0.0"), - # - (("1.1.0a0", "PATCH", None, 0, None), "1.1.0"), - (("1.1.0a0", "MINOR", None, 0, None), "1.1.0"), - (("1.1.0a0", "MAJOR", None, 0, None), "2.0.0"), - # - (("2.0.0a0", "MINOR", None, 0, None), "2.0.0"), - (("2.0.0a0", "MAJOR", None, 0, None), "2.0.0"), - (("2.0.0a0", "PATCH", None, 0, None), "2.0.0"), - # - (("3.0.0a1", None, None, 0, None), "3.0.0"), - (("3.0.0b1", None, None, 0, None), "3.0.0"), - (("3.0.0rc1", None, None, 0, None), "3.0.0"), - # - (("3.1.4", None, "alpha", 0, None), "3.1.4a0"), - (("3.1.4", None, "beta", 0, None), "3.1.4b0"), - (("3.1.4", None, "rc", 0, None), "3.1.4rc0"), - # - (("3.1.4", None, "alpha", 0, None), "3.1.4a0"), - (("3.1.4a0", "PATCH", "alpha", 0, None), "3.1.4a1"), # UNEXPECTED! - (("3.1.4a0", "MINOR", "alpha", 0, None), "3.2.0a0"), - (("3.1.4a0", "MAJOR", "alpha", 0, None), "4.0.0a0"), -] - -exact_cases = [ - (("1.0.0", "PATCH", None, 0, None), "1.0.1"), - (("1.0.0", "MINOR", None, 0, None), "1.1.0"), - # with exact_increment=False: "1.0.0b0" - (("1.0.0a1", "PATCH", "beta", 0, None), "1.0.1b0"), - # with exact_increment=False: "1.0.0b1" - (("1.0.0b0", "PATCH", "beta", 0, None), "1.0.1b0"), - # with exact_increment=False: "1.0.0rc0" - (("1.0.0b1", "PATCH", "rc", 0, None), "1.0.1rc0"), - # with exact_increment=False: "1.0.0-rc1" - (("1.0.0rc0", "PATCH", "rc", 0, None), "1.0.1rc0"), - # with exact_increment=False: "1.0.0rc1-dev1" - (("1.0.0rc0", "PATCH", "rc", 0, 1), "1.0.1rc0.dev1"), - # with exact_increment=False: "1.0.0b0" - (("1.0.0a1", "MINOR", "beta", 0, None), "1.1.0b0"), - # with exact_increment=False: "1.0.0b1" - (("1.0.0b0", "MINOR", "beta", 0, None), "1.1.0b0"), - # with exact_increment=False: "1.0.0b1" - (("1.0.0b0", "MINOR", "alpha", 0, None), "1.1.0a0"), - # with exact_increment=False: "1.0.0rc0" - (("1.0.0b1", "MINOR", "rc", 0, None), "1.1.0rc0"), - # with exact_increment=False: "1.0.0rc1" - (("1.0.0rc0", "MINOR", "rc", 0, None), "1.1.0rc0"), - # with exact_increment=False: "1.0.0rc1-dev1" - (("1.0.0rc0", "MINOR", "rc", 0, 1), "1.1.0rc0.dev1"), - # with exact_increment=False: "2.0.0" - (("2.0.0b0", "MAJOR", None, 0, None), "3.0.0"), - # with exact_increment=False: "2.0.0" - (("2.0.0b0", "MINOR", None, 0, None), "2.1.0"), - # with exact_increment=False: "2.0.0" - (("2.0.0b0", "PATCH", None, 0, None), "2.0.1"), - # same with exact_increment=False - (("2.0.0b0", "MAJOR", "alpha", 0, None), "3.0.0a0"), - # with exact_increment=False: "2.0.0b1" - (("2.0.0b0", "MINOR", "alpha", 0, None), "2.1.0a0"), - # with exact_increment=False: "2.0.0b1" - (("2.0.0b0", "PATCH", "alpha", 0, None), "2.0.1a0"), -] +from tests.utils import VersionSchemeTestArgs @pytest.mark.parametrize( - "test_input,expected", - itertools.chain( - tdd_cases, - weird_cases, - simple_flow, - linear_prerelease_cases, - prerelease_cases, - ), + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.1.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="2.1.1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.9.1a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.10.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0b0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2", + increment=None, + prerelease="beta", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0b1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0beta1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0rc2", + ), + # weird cases + ( + VersionSchemeTestArgs( + current_version="1.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="1a0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="1a0", + increment=None, + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0b0", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="beta", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0b1", + ), + ( + VersionSchemeTestArgs( + current_version="1beta", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0b1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0alpha1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc1+e20d7b57f3eb", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.0", + ), + # simple flow + ( + VersionSchemeTestArgs( + current_version="0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=1, + ), + "0.1.1.dev1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.2.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.2.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=1, + ), + "0.3.0.dev1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.3.1a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1a0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.3.1a1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "0.3.1a1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1a0", + increment=None, + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "0.3.1a1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1a0", + increment=None, + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.4.2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0a2.dev1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2.dev0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0a3.dev1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2.dev0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=0, + ), + "1.0.0a3.dev0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0b0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0b1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0b1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0rc1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0rc1.dev1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a3.dev0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0b0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.2", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.2.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.2.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.2.1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + # linear prerelease cases + ( + VersionSchemeTestArgs( + current_version="0.1.1b1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1b2", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1rc0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1rc1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1rc0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1rc1", + ), + # prerelease cases + ( + VersionSchemeTestArgs( + current_version="3.3.3", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.3.4a0", + ), + ( + VersionSchemeTestArgs( + current_version="3.3.4a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.3.4a1", + ), + ( + VersionSchemeTestArgs( + current_version="3.3.4a1", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.4.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="3.4.0a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.4.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="3.4.0a1", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.4.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="3.4.0a2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "4.0.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="4.0.0a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "4.0.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="4.0.0a1", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "4.0.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="4.0.0a2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "4.0.0a3", + ), + # + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1a0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1a1", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a1", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a0", + ), + # + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a1", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a2", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a3", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a3", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a0", + ), + # + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a1", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a1", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a2", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a3", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a3", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a4", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a4", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a5", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a5", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0a6", + ), + # + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0b1", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.0b1", + ), + # + ( + VersionSchemeTestArgs( + current_version="1.0.1a0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1a0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1a0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + # + ( + VersionSchemeTestArgs( + current_version="1.1.0a0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0a0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + # + ( + VersionSchemeTestArgs( + current_version="2.0.0a0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="2.0.0a0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + # + ( + VersionSchemeTestArgs( + current_version="3.0.0a1", + increment=None, + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="3.0.0b1", + increment=None, + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="3.0.0rc1", + increment=None, + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + # + ( + VersionSchemeTestArgs( + current_version="3.1.4", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.1.4a0", + ), + ( + VersionSchemeTestArgs( + current_version="3.1.4", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "3.1.4b0", + ), + ( + VersionSchemeTestArgs( + current_version="3.1.4", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "3.1.4rc0", + ), + # + ( + VersionSchemeTestArgs( + current_version="3.1.4", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.1.4a0", + ), + ( + VersionSchemeTestArgs( + current_version="3.1.4a0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.1.4a1", + ), + ( + VersionSchemeTestArgs( + current_version="3.1.4a0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.2.0a0", + ), + ( + VersionSchemeTestArgs( + current_version="3.1.4a0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "4.0.0a0", + ), + ], ) -def test_bump_pep440_version(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] +def test_bump_pep440_version(version_args, expected_version): assert ( str( - Pep440(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, + Pep440(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, ) ) - == expected + == expected_version ) -@pytest.mark.parametrize("test_input, expected", exact_cases) -def test_bump_pep440_version_force(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] +@pytest.mark.parametrize( + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + # with exact_increment=False: "1.0.0b0" + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment="PATCH", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1b0", + ), + # with exact_increment=False: "1.0.0b1" + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment="PATCH", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1b0", + ), + # with exact_increment=False: "1.0.0rc0" + ( + VersionSchemeTestArgs( + current_version="1.0.0b1", + increment="PATCH", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1rc0", + ), + # with exact_increment=False: "1.0.0-rc1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="PATCH", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1rc0", + ), + # with exact_increment=False: "1.0.0rc1-dev1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="PATCH", + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.0.1rc0.dev1", + ), + # with exact_increment=False: "1.0.0b0" + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment="MINOR", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0b0", + ), + # with exact_increment=False: "1.0.0b1" + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment="MINOR", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0b0", + ), + # with exact_increment=False: "1.0.0b1" + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0a0", + ), + # with exact_increment=False: "1.0.0rc0" + ( + VersionSchemeTestArgs( + current_version="1.0.0b1", + increment="MINOR", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0rc0", + ), + # with exact_increment=False: "1.0.0rc1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="MINOR", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0rc0", + ), + # with exact_increment=False: "1.0.0rc1-dev1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="MINOR", + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.1.0rc0.dev1", + ), + # with exact_increment=False: "2.0.0" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + # with exact_increment=False: "2.0.0" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.1.0", + ), + # with exact_increment=False: "2.0.0" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.1", + ), + # same with exact_increment=False + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.0.0a0", + ), + # with exact_increment=False: "2.0.0b1" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.1.0a0", + ), + # with exact_increment=False: "2.0.0b1" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.1a0", + ), + ], +) +def test_bump_pep440_version_force(version_args, expected_version): assert ( str( - Pep440(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, + Pep440(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, exact_increment=True, ) ) - == expected + == expected_version ) -@pytest.mark.parametrize("test_input,expected", local_versions) -def test_bump_pep440_version_local(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] - is_local_version = True +@pytest.mark.parametrize( + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+0.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.2.0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+1.0.0", + ), + ], +) +def test_bump_pep440_version_local(version_args, expected_version): assert ( str( - Pep440(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, - is_local_version=is_local_version, + Pep440(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, + is_local_version=True, ) ) - == expected + == expected_version ) @@ -263,76 +1361,3 @@ def test_pep440_scheme_property(): def test_pep440_implement_version_protocol(): assert isinstance(Pep440("0.0.1"), VersionProtocol) - - -def test_pep440_sortable(): - test_input = [x[0][0] for x in simple_flow] - test_input.extend([x[1] for x in simple_flow]) - # randomize - random_input = [Pep440(x) for x in random.sample(test_input, len(test_input))] - assert len(random_input) == len(test_input) - sorted_result = [str(x) for x in sorted(random_input)] - assert sorted_result == [ - "0.1.0", - "0.1.0", - "0.1.1.dev1", - "0.1.1", - "0.1.1", - "0.2.0", - "0.2.0", - "0.2.0", - "0.3.0.dev1", - "0.3.0", - "0.3.0", - "0.3.0", - "0.3.0", - "0.3.1a0", - "0.3.1a0", - "0.3.1a0", - "0.3.1a0", - "0.3.1a1", - "0.3.1a1", - "0.3.1a1", - "0.3.1", - "0.3.1", - "0.3.1", - "0.3.2", - "0.4.2", - "1.0.0a0", - "1.0.0a0", - "1.0.0a1", - "1.0.0a1", - "1.0.0a1", - "1.0.0a1", - "1.0.0a2.dev0", - "1.0.0a2.dev0", - "1.0.0a2.dev1", - "1.0.0a2", - "1.0.0a3.dev0", - "1.0.0a3.dev0", - "1.0.0a3.dev1", - "1.0.0b0", - "1.0.0b0", - "1.0.0b0", - "1.0.0b1", - "1.0.0b1", - "1.0.0rc0", - "1.0.0rc0", - "1.0.0rc0", - "1.0.0rc0", - "1.0.0rc1.dev1", - "1.0.0rc1", - "1.0.0", - "1.0.0", - "1.0.1", - "1.0.1", - "1.0.2", - "1.0.2", - "1.1.0", - "1.1.0", - "1.2.0", - "1.2.0", - "1.2.1", - "1.2.1", - "2.0.0", - ] diff --git a/tests/test_version_scheme_semver.py b/tests/test_version_scheme_semver.py index 8785717a34..8a163d4f6b 100644 --- a/tests/test_version_scheme_semver.py +++ b/tests/test_version_scheme_semver.py @@ -1,189 +1,882 @@ -import itertools -import random +from __future__ import annotations import pytest from commitizen.version_schemes import SemVer, VersionProtocol - -simple_flow = [ - (("0.1.0", "PATCH", None, 0, None), "0.1.1"), - (("0.1.0", "PATCH", None, 0, 1), "0.1.1-dev1"), - (("0.1.1", "MINOR", None, 0, None), "0.2.0"), - (("0.2.0", "MINOR", None, 0, None), "0.3.0"), - (("0.2.0", "MINOR", None, 0, 1), "0.3.0-dev1"), - (("0.3.0", "PATCH", None, 0, None), "0.3.1"), - (("0.3.0", "PATCH", "alpha", 0, None), "0.3.1-a0"), - (("0.3.1a0", None, "alpha", 0, None), "0.3.1-a1"), - (("0.3.0", "PATCH", "alpha", 1, None), "0.3.1-a1"), - (("0.3.1a0", None, "alpha", 1, None), "0.3.1-a1"), - (("0.3.1a0", None, None, 0, None), "0.3.1"), - (("0.3.1", "PATCH", None, 0, None), "0.3.2"), - (("0.4.2", "MAJOR", "alpha", 0, None), "1.0.0-a0"), - (("1.0.0a0", None, "alpha", 0, None), "1.0.0-a1"), - (("1.0.0a1", None, "alpha", 0, None), "1.0.0-a2"), - (("1.0.0a1", None, "alpha", 0, 1), "1.0.0-a2-dev1"), - (("1.0.0a2.dev0", None, "alpha", 0, 1), "1.0.0-a3-dev1"), - (("1.0.0a2.dev0", None, "alpha", 0, 0), "1.0.0-a3-dev0"), - (("1.0.0a1", None, "beta", 0, None), "1.0.0-b0"), - (("1.0.0b0", None, "beta", 0, None), "1.0.0-b1"), - (("1.0.0b1", None, "rc", 0, None), "1.0.0-rc0"), - (("1.0.0rc0", None, "rc", 0, None), "1.0.0-rc1"), - (("1.0.0rc0", None, "rc", 0, 1), "1.0.0-rc1-dev1"), - (("1.0.0rc0", "PATCH", None, 0, None), "1.0.0"), - (("1.0.0a3.dev0", None, "beta", 0, None), "1.0.0-b0"), - (("1.0.0", "PATCH", None, 0, None), "1.0.1"), - (("1.0.1", "PATCH", None, 0, None), "1.0.2"), - (("1.0.2", "MINOR", None, 0, None), "1.1.0"), - (("1.1.0", "MINOR", None, 0, None), "1.2.0"), - (("1.2.0", "PATCH", None, 0, None), "1.2.1"), - (("1.2.1", "MAJOR", None, 0, None), "2.0.0"), -] - -local_versions = [ - (("4.5.0+0.1.0", "PATCH", None, 0, None), "4.5.0+0.1.1"), - (("4.5.0+0.1.1", "MINOR", None, 0, None), "4.5.0+0.2.0"), - (("4.5.0+0.2.0", "MAJOR", None, 0, None), "4.5.0+1.0.0"), -] - -# never bump backwards on pre-releases -linear_prerelease_cases = [ - (("0.1.1b1", None, "alpha", 0, None), "0.1.1-b2"), - (("0.1.1rc0", None, "alpha", 0, None), "0.1.1-rc1"), - (("0.1.1rc0", None, "beta", 0, None), "0.1.1-rc1"), -] - -weird_cases = [ - (("1.1", "PATCH", None, 0, None), "1.1.1"), - (("1", "MINOR", None, 0, None), "1.1.0"), - (("1", "MAJOR", None, 0, None), "2.0.0"), - (("1a0", None, "alpha", 0, None), "1.0.0-a1"), - (("1a0", None, "alpha", 1, None), "1.0.0-a1"), - (("1", None, "beta", 0, None), "1.0.0-b0"), - (("1", None, "beta", 1, None), "1.0.0-b1"), - (("1beta", None, "beta", 0, None), "1.0.0-b1"), - (("1.0.0alpha1", None, "alpha", 0, None), "1.0.0-a2"), - (("1", None, "rc", 0, None), "1.0.0-rc0"), - (("1.0.0rc1+e20d7b57f3eb", "PATCH", None, 0, None), "1.0.0"), -] - -# test driven development -tdd_cases = [ - (("0.1.1", "PATCH", None, 0, None), "0.1.2"), - (("0.1.1", "MINOR", None, 0, None), "0.2.0"), - (("2.1.1", "MAJOR", None, 0, None), "3.0.0"), - (("0.9.0", "PATCH", "alpha", 0, None), "0.9.1-a0"), - (("0.9.0", "MINOR", "alpha", 0, None), "0.10.0-a0"), - (("0.9.0", "MAJOR", "alpha", 0, None), "1.0.0-a0"), - (("0.9.0", "MAJOR", "alpha", 1, None), "1.0.0-a1"), - (("1.0.0a2", None, "beta", 0, None), "1.0.0-b0"), - (("1.0.0a2", None, "beta", 1, None), "1.0.0-b1"), - (("1.0.0beta1", None, "rc", 0, None), "1.0.0-rc0"), - (("1.0.0rc1", None, "rc", 0, None), "1.0.0-rc2"), - (("1.0.0-a0", None, "rc", 0, None), "1.0.0-rc0"), - (("1.0.0-alpha1", None, "alpha", 0, None), "1.0.0-a2"), -] - -exact_cases = [ - (("1.0.0", "PATCH", None, 0, None), "1.0.1"), - (("1.0.0", "MINOR", None, 0, None), "1.1.0"), - # with exact_increment=False: "1.0.0-b0" - (("1.0.0a1", "PATCH", "beta", 0, None), "1.0.1-b0"), - # with exact_increment=False: "1.0.0-b1" - (("1.0.0b0", "PATCH", "beta", 0, None), "1.0.1-b0"), - # with exact_increment=False: "1.0.0-rc0" - (("1.0.0b1", "PATCH", "rc", 0, None), "1.0.1-rc0"), - # with exact_increment=False: "1.0.0-rc1" - (("1.0.0rc0", "PATCH", "rc", 0, None), "1.0.1-rc0"), - # with exact_increment=False: "1.0.0-rc1-dev1" - (("1.0.0rc0", "PATCH", "rc", 0, 1), "1.0.1-rc0-dev1"), - # with exact_increment=False: "1.0.0-b0" - (("1.0.0a1", "MINOR", "beta", 0, None), "1.1.0-b0"), - # with exact_increment=False: "1.0.0-b1" - (("1.0.0b0", "MINOR", "beta", 0, None), "1.1.0-b0"), - # with exact_increment=False: "1.0.0-rc0" - (("1.0.0b1", "MINOR", "rc", 0, None), "1.1.0-rc0"), - # with exact_increment=False: "1.0.0-rc1" - (("1.0.0rc0", "MINOR", "rc", 0, None), "1.1.0-rc0"), - # with exact_increment=False: "1.0.0-rc1-dev1" - (("1.0.0rc0", "MINOR", "rc", 0, 1), "1.1.0-rc0-dev1"), - # with exact_increment=False: "2.0.0" - (("2.0.0b0", "MAJOR", None, 0, None), "3.0.0"), - # with exact_increment=False: "2.0.0" - (("2.0.0b0", "MINOR", None, 0, None), "2.1.0"), - # with exact_increment=False: "2.0.0" - (("2.0.0b0", "PATCH", None, 0, None), "2.0.1"), - # same with exact_increment=False - (("2.0.0b0", "MAJOR", "alpha", 0, None), "3.0.0-a0"), - # with exact_increment=False: "2.0.0b1" - (("2.0.0b0", "MINOR", "alpha", 0, None), "2.1.0-a0"), - # with exact_increment=False: "2.0.0b1" - (("2.0.0b0", "PATCH", "alpha", 0, None), "2.0.1-a0"), -] +from tests.utils import VersionSchemeTestArgs @pytest.mark.parametrize( - "test_input, expected", - itertools.chain(tdd_cases, weird_cases, simple_flow, linear_prerelease_cases), + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.1.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="2.1.1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.9.1-a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.10.0-a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-b0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2", + increment=None, + prerelease="beta", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-b1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0beta1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-a0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a2", + ), + # weird cases + ( + VersionSchemeTestArgs( + current_version="1.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="1a0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a1", + ), + ( + VersionSchemeTestArgs( + current_version="1a0", + increment=None, + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-a1", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-b0", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="beta", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-b1", + ), + ( + VersionSchemeTestArgs( + current_version="1beta", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-b1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0alpha1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a2", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc1+e20d7b57f3eb", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.0", + ), + # simple flow + ( + VersionSchemeTestArgs( + current_version="0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=1, + ), + "0.1.1-dev1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.2.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.2.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=1, + ), + "0.3.0-dev1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.3.1-a0", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1a0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.3.1-a1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "0.3.1-a1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1a0", + increment=None, + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "0.3.1-a1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1a0", + increment=None, + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.4.2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-a2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0-a2-dev1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2.dev0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0-a3-dev1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a2.dev0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=0, + ), + "1.0.0-a3-dev0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-b0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-b1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0b1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0-rc1-dev1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0a3.dev0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-b0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.2", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.2.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.2.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.2.1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + # linear prerelease cases (never bump backwards on pre-releases) + ( + VersionSchemeTestArgs( + current_version="0.1.1b1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1-b2", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1rc0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1-rc1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1rc0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1-rc1", + ), + ], ) -def test_bump_semver_version(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] +def test_bump_semver_version( + version_args: VersionSchemeTestArgs, expected_version: str +): assert ( str( - SemVer(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, + SemVer(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, ) ) - == expected + == expected_version ) -@pytest.mark.parametrize("test_input, expected", exact_cases) -def test_bump_semver_version_force(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] +@pytest.mark.parametrize( + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + # with exact_increment=False: "1.0.0-b0" + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment="PATCH", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1-b0", + ), + # with exact_increment=False: "1.0.0-b1" + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment="PATCH", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1-b0", + ), + # with exact_increment=False: "1.0.0-rc0" + ( + VersionSchemeTestArgs( + current_version="1.0.0b1", + increment="PATCH", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1-rc0", + ), + # with exact_increment=False: "1.0.0-rc1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="PATCH", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.1-rc0", + ), + # with exact_increment=False: "1.0.0-rc1-dev1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="PATCH", + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.0.1-rc0-dev1", + ), + # with exact_increment=False: "1.0.0-b0" + ( + VersionSchemeTestArgs( + current_version="1.0.0a1", + increment="MINOR", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0-b0", + ), + # with exact_increment=False: "1.0.0-b1" + ( + VersionSchemeTestArgs( + current_version="1.0.0b0", + increment="MINOR", + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0-b0", + ), + # with exact_increment=False: "1.0.0-rc0" + ( + VersionSchemeTestArgs( + current_version="1.0.0b1", + increment="MINOR", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0-rc0", + ), + # with exact_increment=False: "1.0.0-rc1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="MINOR", + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.1.0-rc0", + ), + # with exact_increment=False: "1.0.0-rc1-dev1" + ( + VersionSchemeTestArgs( + current_version="1.0.0rc0", + increment="MINOR", + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.1.0-rc0-dev1", + ), + # with exact_increment=False: "2.0.0" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + # with exact_increment=False: "2.0.0" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.1.0", + ), + # with exact_increment=False: "2.0.0" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.1", + ), + # same with exact_increment=False + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "3.0.0-a0", + ), + # with exact_increment=False: "2.0.0b1" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.1.0-a0", + ), + # with exact_increment=False: "2.0.0b1" + ( + VersionSchemeTestArgs( + current_version="2.0.0b0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "2.0.1-a0", + ), + ], +) +def test_bump_semver_version_force( + version_args: VersionSchemeTestArgs, expected_version: str +): assert ( str( - SemVer(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, + SemVer(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, exact_increment=True, ) ) - == expected + == expected_version ) -@pytest.mark.parametrize("test_input,expected", local_versions) -def test_bump_semver_version_local(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] - is_local_version = True +@pytest.mark.parametrize( + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+0.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.2.0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+1.0.0", + ), + ], +) +def test_bump_semver_version_local( + version_args: VersionSchemeTestArgs, expected_version: str +): assert ( str( - SemVer(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, - is_local_version=is_local_version, + SemVer(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, + is_local_version=True, ) ) - == expected + == expected_version ) @@ -194,76 +887,3 @@ def test_semver_scheme_property(): def test_semver_implement_version_protocol(): assert isinstance(SemVer("0.0.1"), VersionProtocol) - - -def test_semver_sortable(): - test_input = [x[0][0] for x in simple_flow] - test_input.extend([x[1] for x in simple_flow]) - # randomize - random_input = [SemVer(x) for x in random.sample(test_input, len(test_input))] - assert len(random_input) == len(test_input) - sorted_result = [str(x) for x in sorted(random_input)] - assert sorted_result == [ - "0.1.0", - "0.1.0", - "0.1.1-dev1", - "0.1.1", - "0.1.1", - "0.2.0", - "0.2.0", - "0.2.0", - "0.3.0-dev1", - "0.3.0", - "0.3.0", - "0.3.0", - "0.3.0", - "0.3.1-a0", - "0.3.1-a0", - "0.3.1-a0", - "0.3.1-a0", - "0.3.1-a1", - "0.3.1-a1", - "0.3.1-a1", - "0.3.1", - "0.3.1", - "0.3.1", - "0.3.2", - "0.4.2", - "1.0.0-a0", - "1.0.0-a0", - "1.0.0-a1", - "1.0.0-a1", - "1.0.0-a1", - "1.0.0-a1", - "1.0.0-a2-dev0", - "1.0.0-a2-dev0", - "1.0.0-a2-dev1", - "1.0.0-a2", - "1.0.0-a3-dev0", - "1.0.0-a3-dev0", - "1.0.0-a3-dev1", - "1.0.0-b0", - "1.0.0-b0", - "1.0.0-b0", - "1.0.0-b1", - "1.0.0-b1", - "1.0.0-rc0", - "1.0.0-rc0", - "1.0.0-rc0", - "1.0.0-rc0", - "1.0.0-rc1-dev1", - "1.0.0-rc1", - "1.0.0", - "1.0.0", - "1.0.1", - "1.0.1", - "1.0.2", - "1.0.2", - "1.1.0", - "1.1.0", - "1.2.0", - "1.2.0", - "1.2.1", - "1.2.1", - "2.0.0", - ] diff --git a/tests/test_version_scheme_semver2.py b/tests/test_version_scheme_semver2.py index d18a058a7c..4a35e6470a 100644 --- a/tests/test_version_scheme_semver2.py +++ b/tests/test_version_scheme_semver2.py @@ -1,131 +1,664 @@ -import itertools -import random +from __future__ import annotations import pytest from commitizen.version_schemes import SemVer2, VersionProtocol - -simple_flow = [ - (("0.1.0", "PATCH", None, 0, None), "0.1.1"), - (("0.1.0", "PATCH", None, 0, 1), "0.1.1-dev.1"), - (("0.1.1", "MINOR", None, 0, None), "0.2.0"), - (("0.2.0", "MINOR", None, 0, None), "0.3.0"), - (("0.2.0", "MINOR", None, 0, 1), "0.3.0-dev.1"), - (("0.3.0", "PATCH", None, 0, None), "0.3.1"), - (("0.3.0", "PATCH", "alpha", 0, None), "0.3.1-alpha.0"), - (("0.3.1-alpha.0", None, "alpha", 0, None), "0.3.1-alpha.1"), - (("0.3.0", "PATCH", "alpha", 1, None), "0.3.1-alpha.1"), - (("0.3.1-alpha.0", None, "alpha", 1, None), "0.3.1-alpha.1"), - (("0.3.1-alpha.0", None, None, 0, None), "0.3.1"), - (("0.3.1", "PATCH", None, 0, None), "0.3.2"), - (("0.4.2", "MAJOR", "alpha", 0, None), "1.0.0-alpha.0"), - (("1.0.0-alpha.0", None, "alpha", 0, None), "1.0.0-alpha.1"), - (("1.0.0-alpha.1", None, "alpha", 0, None), "1.0.0-alpha.2"), - (("1.0.0-alpha.1", None, "alpha", 0, 1), "1.0.0-alpha.2.dev.1"), - (("1.0.0-alpha.2.dev.0", None, "alpha", 0, 1), "1.0.0-alpha.3.dev.1"), - (("1.0.0-alpha.2.dev.0", None, "alpha", 0, 0), "1.0.0-alpha.3.dev.0"), - (("1.0.0-alpha.1", None, "beta", 0, None), "1.0.0-beta.0"), - (("1.0.0-beta.0", None, "beta", 0, None), "1.0.0-beta.1"), - (("1.0.0-beta.1", None, "rc", 0, None), "1.0.0-rc.0"), - (("1.0.0-rc.0", None, "rc", 0, None), "1.0.0-rc.1"), - (("1.0.0-rc.0", None, "rc", 0, 1), "1.0.0-rc.1.dev.1"), - (("1.0.0-rc.0", "PATCH", None, 0, None), "1.0.0"), - (("1.0.0-alpha.3.dev.0", None, "beta", 0, None), "1.0.0-beta.0"), - (("1.0.0", "PATCH", None, 0, None), "1.0.1"), - (("1.0.1", "PATCH", None, 0, None), "1.0.2"), - (("1.0.2", "MINOR", None, 0, None), "1.1.0"), - (("1.1.0", "MINOR", None, 0, None), "1.2.0"), - (("1.2.0", "PATCH", None, 0, None), "1.2.1"), - (("1.2.1", "MAJOR", None, 0, None), "2.0.0"), -] - -local_versions = [ - (("4.5.0+0.1.0", "PATCH", None, 0, None), "4.5.0+0.1.1"), - (("4.5.0+0.1.1", "MINOR", None, 0, None), "4.5.0+0.2.0"), - (("4.5.0+0.2.0", "MAJOR", None, 0, None), "4.5.0+1.0.0"), -] - -# never bump backwards on pre-releases -linear_prerelease_cases = [ - (("0.1.1-beta.1", None, "alpha", 0, None), "0.1.1-beta.2"), - (("0.1.1-rc.0", None, "alpha", 0, None), "0.1.1-rc.1"), - (("0.1.1-rc.0", None, "beta", 0, None), "0.1.1-rc.1"), -] - -weird_cases = [ - (("1.1", "PATCH", None, 0, None), "1.1.1"), - (("1", "MINOR", None, 0, None), "1.1.0"), - (("1", "MAJOR", None, 0, None), "2.0.0"), - (("1-alpha.0", None, "alpha", 0, None), "1.0.0-alpha.1"), - (("1-alpha.0", None, "alpha", 1, None), "1.0.0-alpha.1"), - (("1", None, "beta", 0, None), "1.0.0-beta.0"), - (("1", None, "beta", 1, None), "1.0.0-beta.1"), - (("1-beta", None, "beta", 0, None), "1.0.0-beta.1"), - (("1.0.0-alpha.1", None, "alpha", 0, None), "1.0.0-alpha.2"), - (("1", None, "rc", 0, None), "1.0.0-rc.0"), - (("1.0.0-rc.1+e20d7b57f3eb", "PATCH", None, 0, None), "1.0.0"), -] - -# test driven development -tdd_cases = [ - (("0.1.1", "PATCH", None, 0, None), "0.1.2"), - (("0.1.1", "MINOR", None, 0, None), "0.2.0"), - (("2.1.1", "MAJOR", None, 0, None), "3.0.0"), - (("0.9.0", "PATCH", "alpha", 0, None), "0.9.1-alpha.0"), - (("0.9.0", "MINOR", "alpha", 0, None), "0.10.0-alpha.0"), - (("0.9.0", "MAJOR", "alpha", 0, None), "1.0.0-alpha.0"), - (("0.9.0", "MAJOR", "alpha", 1, None), "1.0.0-alpha.1"), - (("1.0.0-alpha.2", None, "beta", 0, None), "1.0.0-beta.0"), - (("1.0.0-alpha.2", None, "beta", 1, None), "1.0.0-beta.1"), - (("1.0.0-beta.1", None, "rc", 0, None), "1.0.0-rc.0"), - (("1.0.0-rc.1", None, "rc", 0, None), "1.0.0-rc.2"), - (("1.0.0-alpha.0", None, "rc", 0, None), "1.0.0-rc.0"), - (("1.0.0-alpha.1", None, "alpha", 0, None), "1.0.0-alpha.2"), -] +from tests.utils import VersionSchemeTestArgs @pytest.mark.parametrize( - "test_input, expected", - itertools.chain(tdd_cases, weird_cases, simple_flow, linear_prerelease_cases), + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.1.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="2.1.1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "3.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.9.1-alpha.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MINOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.10.0-alpha.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.9.0", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.2", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-beta.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.2", + increment=None, + prerelease="beta", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-beta.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-beta.1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-rc.1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc.2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.2", + ), + # weird_cases + ( + VersionSchemeTestArgs( + current_version="1.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="1-alpha.0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="1-alpha.0", + increment=None, + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-beta.0", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="beta", + prerelease_offset=1, + devrelease=None, + ), + "1.0.0-beta.1", + ), + ( + VersionSchemeTestArgs( + current_version="1-beta", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-beta.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.2", + ), + ( + VersionSchemeTestArgs( + current_version="1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-rc.1+e20d7b57f3eb", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.0", + ), + # simple_flow + ( + VersionSchemeTestArgs( + current_version="0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=1, + ), + "0.1.1-dev.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.2.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.2.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=1, + ), + "0.3.0-dev.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.3.1-alpha.0", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1-alpha.0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.3.1-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.0", + increment="PATCH", + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "0.3.1-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1-alpha.0", + increment=None, + prerelease="alpha", + prerelease_offset=1, + devrelease=None, + ), + "0.3.1-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1-alpha.0", + increment=None, + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.3.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "0.3.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.4.2", + increment="MAJOR", + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-alpha.2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0-alpha.2.dev.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.2.dev.0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0-alpha.3.dev.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.2.dev.0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=0, + ), + "1.0.0-alpha.3.dev.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.1", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-beta.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-beta.0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-beta.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-beta.1", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-rc.0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-rc.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-rc.0", + increment=None, + prerelease="rc", + prerelease_offset=0, + devrelease=1, + ), + "1.0.0-rc.1.dev.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-rc.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0-alpha.3.dev.0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "1.0.0-beta.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.1", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.0.2", + ), + ( + VersionSchemeTestArgs( + current_version="1.0.2", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.1.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.1.0", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="1.2.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "1.2.1", + ), + ( + VersionSchemeTestArgs( + current_version="1.2.1", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "2.0.0", + ), + # linear prerelease cases (never bump backwards on pre-releases) + ( + VersionSchemeTestArgs( + current_version="0.1.1-beta.1", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1-beta.2", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1-rc.0", + increment=None, + prerelease="alpha", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1-rc.1", + ), + ( + VersionSchemeTestArgs( + current_version="0.1.1-rc.0", + increment=None, + prerelease="beta", + prerelease_offset=0, + devrelease=None, + ), + "0.1.1-rc.1", + ), + ], ) -def test_bump_semver_version(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] +def test_bump_semver_version( + version_args: VersionSchemeTestArgs, expected_version: str +): assert ( str( - SemVer2(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, + SemVer2(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, ) ) - == expected + == expected_version ) -@pytest.mark.parametrize("test_input,expected", local_versions) -def test_bump_semver_version_local(test_input, expected): - current_version = test_input[0] - increment = test_input[1] - prerelease = test_input[2] - prerelease_offset = test_input[3] - devrelease = test_input[4] - is_local_version = True +@pytest.mark.parametrize( + "version_args, expected_version", + [ + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.1.0", + increment="PATCH", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+0.1.1", + ), + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.1.1", + increment="MINOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+0.2.0", + ), + ( + VersionSchemeTestArgs( + current_version="4.5.0+0.2.0", + increment="MAJOR", + prerelease=None, + prerelease_offset=0, + devrelease=None, + ), + "4.5.0+1.0.0", + ), + ], +) +def test_bump_semver_version_local( + version_args: VersionSchemeTestArgs, expected_version: str +): assert ( str( - SemVer2(current_version).bump( - increment=increment, - prerelease=prerelease, - prerelease_offset=prerelease_offset, - devrelease=devrelease, - is_local_version=is_local_version, + SemVer2(version_args.current_version).bump( + increment=version_args.increment, + prerelease=version_args.prerelease, + prerelease_offset=version_args.prerelease_offset, + devrelease=version_args.devrelease, + is_local_version=True, ) ) - == expected + == expected_version ) @@ -136,76 +669,3 @@ def test_semver_scheme_property(): def test_semver_implement_version_protocol(): assert isinstance(SemVer2("0.0.1"), VersionProtocol) - - -def test_semver_sortable(): - test_input = [x[0][0] for x in simple_flow] - test_input.extend([x[1] for x in simple_flow]) - # randomize - random_input = [SemVer2(x) for x in random.sample(test_input, len(test_input))] - assert len(random_input) == len(test_input) - sorted_result = [str(x) for x in sorted(random_input)] - assert sorted_result == [ - "0.1.0", - "0.1.0", - "0.1.1-dev.1", - "0.1.1", - "0.1.1", - "0.2.0", - "0.2.0", - "0.2.0", - "0.3.0-dev.1", - "0.3.0", - "0.3.0", - "0.3.0", - "0.3.0", - "0.3.1-alpha.0", - "0.3.1-alpha.0", - "0.3.1-alpha.0", - "0.3.1-alpha.0", - "0.3.1-alpha.1", - "0.3.1-alpha.1", - "0.3.1-alpha.1", - "0.3.1", - "0.3.1", - "0.3.1", - "0.3.2", - "0.4.2", - "1.0.0-alpha.0", - "1.0.0-alpha.0", - "1.0.0-alpha.1", - "1.0.0-alpha.1", - "1.0.0-alpha.1", - "1.0.0-alpha.1", - "1.0.0-alpha.2.dev.0", - "1.0.0-alpha.2.dev.0", - "1.0.0-alpha.2.dev.1", - "1.0.0-alpha.2", - "1.0.0-alpha.3.dev.0", - "1.0.0-alpha.3.dev.0", - "1.0.0-alpha.3.dev.1", - "1.0.0-beta.0", - "1.0.0-beta.0", - "1.0.0-beta.0", - "1.0.0-beta.1", - "1.0.0-beta.1", - "1.0.0-rc.0", - "1.0.0-rc.0", - "1.0.0-rc.0", - "1.0.0-rc.0", - "1.0.0-rc.1.dev.1", - "1.0.0-rc.1", - "1.0.0", - "1.0.0", - "1.0.1", - "1.0.1", - "1.0.2", - "1.0.2", - "1.1.0", - "1.1.0", - "1.2.0", - "1.2.0", - "1.2.1", - "1.2.1", - "2.0.0", - ] diff --git a/tests/utils.py b/tests/utils.py index 5e26b2d70a..43e0cf79a0 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,11 +4,13 @@ import time import uuid from pathlib import Path +from typing import NamedTuple import pytest from deprecated import deprecated from commitizen import cmd, exceptions, git +from commitizen.version_schemes import Increment, Prerelease skip_below_py_3_10 = pytest.mark.skipif( sys.version_info < (3, 10), @@ -21,6 +23,14 @@ ) +class VersionSchemeTestArgs(NamedTuple): + current_version: str + increment: Increment | None + prerelease: Prerelease | None + prerelease_offset: int + devrelease: int | None + + class FakeCommand: def __init__(self, out=None, err=None, return_code=0): self.out = out From cbb309d8573ffcb659284b584f0dad328731b5a8 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sat, 20 Sep 2025 01:29:52 +0800 Subject: [PATCH 066/221] refactor: remove self.encoding for better maintainability --- commitizen/changelog_formats/base.py | 5 +++-- commitizen/commands/bump.py | 3 +-- commitizen/commands/changelog.py | 9 ++++++--- commitizen/commands/check.py | 5 +++-- commitizen/commands/commit.py | 13 +++++++++---- commitizen/commands/init.py | 9 ++++++--- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/commitizen/changelog_formats/base.py b/commitizen/changelog_formats/base.py index 0a76ad68f9..64a795207a 100644 --- a/commitizen/changelog_formats/base.py +++ b/commitizen/changelog_formats/base.py @@ -24,7 +24,6 @@ def __init__(self, config: BaseConfig) -> None: # Constructor needs to be redefined because `Protocol` prevent instantiation by default # See: https://bugs.python.org/issue44807 self.config = config - self.encoding = self.config.settings["encoding"] self.tag_rules = TagRules( scheme=get_version_scheme(self.config.settings), tag_format=self.config.settings["tag_format"], @@ -36,7 +35,9 @@ def get_metadata(self, filepath: str) -> Metadata: if not os.path.isfile(filepath): return Metadata() - with open(filepath, encoding=self.encoding) as changelog_file: + with open( + filepath, encoding=self.config.settings["encoding"] + ) as changelog_file: return self.get_metadata_from_file(changelog_file) def get_metadata_from_file(self, file: IO[Any]) -> Metadata: diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index fc9649c6c5..3dc678920e 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -67,7 +67,6 @@ def __init__(self, config: BaseConfig, arguments: BumpArgs) -> None: raise NotAGitProjectError() self.config: BaseConfig = config - self.encoding = config.settings["encoding"] self.arguments = arguments self.bump_settings = cast( BumpArgs, @@ -335,7 +334,7 @@ def __call__(self) -> None: str(new_version), self.bump_settings["version_files"], check_consistency=self.check_consistency, - encoding=self.encoding, + encoding=self.config.settings["encoding"], ) ) diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index c739419b8d..27b8ccb258 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -67,7 +67,6 @@ def __init__(self, config: BaseConfig, arguments: ChangelogArgs) -> None: else changelog_file_name ) - self.encoding = self.config.settings["encoding"] self.cz = factory.committer_factory(self.config) self.start_rev = arguments.get("start_rev") or self.config.settings.get( @@ -157,7 +156,9 @@ def _find_incremental_rev(self, latest_version: str, tags: Iterable[GitTag]) -> def _write_changelog( self, changelog_out: str, lines: list[str], changelog_meta: changelog.Metadata ) -> None: - with smart_open(self.file_name, "w", encoding=self.encoding) as changelog_file: + with smart_open( + self.file_name, "w", encoding=self.config.settings["encoding"] + ) as changelog_file: partial_changelog: str | None = None if self.incremental: new_lines = changelog.incremental_build( @@ -259,7 +260,9 @@ def __call__(self) -> None: lines = [] if self.incremental and os.path.isfile(self.file_name): - with open(self.file_name, encoding=self.encoding) as changelog_file: + with open( + self.file_name, encoding=self.config.settings["encoding"] + ) as changelog_file: lines = changelog_file.readlines() self._write_changelog(changelog_out, lines, changelog_meta) diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index b79e6609e0..d45e388f9d 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -71,7 +71,6 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N self.commit_msg = sys.stdin.read() self.config: BaseConfig = config - self.encoding = config.settings["encoding"] self.cz = factory.committer_factory(self.config) def __call__(self) -> None: @@ -106,7 +105,9 @@ def _get_commit_message(self) -> str | None: # Get commit message from command line (--message) return self.commit_msg - with open(self.commit_msg_file, encoding=self.encoding) as commit_file: + with open( + self.commit_msg_file, encoding=self.config.settings["encoding"] + ) as commit_file: # Get commit message from file (--commit-msg-file) return commit_file.read() diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 0a6349303c..8ab8d2cac9 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -48,7 +48,6 @@ def __init__(self, config: BaseConfig, arguments: CommitArgs) -> None: raise NotAGitProjectError() self.config: BaseConfig = config - self.encoding = config.settings["encoding"] self.cz = factory.committer_factory(self.config) self.arguments = arguments self.backup_file_path = get_backup_file_path() @@ -59,7 +58,9 @@ def _read_backup_message(self) -> str | None: return None # Read commit message from backup - with open(self.backup_file_path, encoding=self.encoding) as f: + with open( + self.backup_file_path, encoding=self.config.settings["encoding"] + ) as f: return f.read().strip() def _prompt_commit_questions(self) -> str: @@ -146,7 +147,9 @@ def __call__(self) -> None: out.info(f"\n{commit_message}\n") if write_message_to_file: - with smart_open(write_message_to_file, "w", encoding=self.encoding) as file: + with smart_open( + write_message_to_file, "w", encoding=self.config.settings["encoding"] + ) as file: file.write(commit_message) if dry_run: @@ -160,7 +163,9 @@ def __call__(self) -> None: out.error(c.err) # Create commit backup - with smart_open(self.backup_file_path, "w", encoding=self.encoding) as f: + with smart_open( + self.backup_file_path, "w", encoding=self.config.settings["encoding"] + ) as f: f.write(commit_message) raise CommitError() diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 92e7d06d7d..35e9c20415 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -121,7 +121,6 @@ class Init: def __init__(self, config: BaseConfig, *args: object) -> None: self.config: BaseConfig = config - self.encoding = config.settings["encoding"] self.cz = factory.committer_factory(self.config) self.project_info = ProjectInfo() @@ -163,7 +162,9 @@ def __call__(self) -> None: if hook_types: config_data = self._get_config_data() with smart_open( - self._PRE_COMMIT_CONFIG_PATH, "w", encoding=self.encoding + self._PRE_COMMIT_CONFIG_PATH, + "w", + encoding=self.config.settings["encoding"], ) as config_file: yaml.safe_dump(config_data, stream=config_file) @@ -355,7 +356,9 @@ def _get_config_data(self) -> dict[str, Any]: # .pre-commit-config.yaml does not exist return {"repos": [CZ_HOOK_CONFIG]} - with open(self._PRE_COMMIT_CONFIG_PATH, encoding=self.encoding) as config_file: + with open( + self._PRE_COMMIT_CONFIG_PATH, encoding=self.config.settings["encoding"] + ) as config_file: config_data: dict[str, Any] = yaml.safe_load(config_file) or {} if not isinstance(repos := config_data.get("repos"), list): From 9f36d5ebfa72616b3caf765efde16787509ed085 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 14 Sep 2025 23:38:03 +0800 Subject: [PATCH 067/221] refactor(BaseConfig): update docstring, extract factory method and remove unnecessary variable assignment --- commitizen/commands/init.py | 71 ++++++++++++++++++----------- commitizen/config/__init__.py | 58 ++++++++++------------- commitizen/config/base_config.py | 8 +++- commitizen/config/factory.py | 22 +++++++++ commitizen/config/json_config.py | 9 ++-- commitizen/config/toml_config.py | 9 ++-- commitizen/config/yaml_config.py | 11 +++-- tests/commands/conftest.py | 3 +- tests/commands/test_init_command.py | 3 +- tests/test_conf.py | 21 +++++---- tests/test_cz_customize.py | 27 ++++++----- tests/test_cz_search_filter.py | 2 +- 12 files changed, 146 insertions(+), 98 deletions(-) create mode 100644 commitizen/config/factory.py diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 35e9c20415..637caa2841 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -2,6 +2,7 @@ import os import shutil +from pathlib import Path from typing import Any, NamedTuple import questionary @@ -9,7 +10,10 @@ from commitizen import cmd, factory, out from commitizen.__version__ import __version__ -from commitizen.config import BaseConfig, JsonConfig, TomlConfig, YAMLConfig +from commitizen.config import ( + BaseConfig, +) +from commitizen.config.factory import create_config from commitizen.cz import registry from commitizen.defaults import CONFIG_FILES, DEFAULT_SETTINGS from commitizen.exceptions import InitFailedError, NoAnswersError @@ -188,45 +192,33 @@ def __call__(self) -> None: ) out.write("commitizen pre-commit hook is now installed in your '.git'\n") - # Initialize configuration - if "toml" in config_path: - self.config = TomlConfig(data="", path=config_path) - elif "json" in config_path: - self.config = JsonConfig(data="{}", path=config_path) - elif "yaml" in config_path: - self.config = YAMLConfig(data="", path=config_path) - - # Create and initialize config - self.config.init_empty_config_content() - - self.config.set_key("name", cz_name) - self.config.set_key("tag_format", tag_format) - self.config.set_key("version_scheme", version_scheme) - if version_provider == "commitizen": - self.config.set_key("version", version.public) - else: - self.config.set_key("version_provider", version_provider) - if update_changelog_on_bump: - self.config.set_key("update_changelog_on_bump", update_changelog_on_bump) - if major_version_zero: - self.config.set_key("major_version_zero", major_version_zero) + _write_config_to_file( + path=config_path, + cz_name=cz_name, + version_provider=version_provider, + version_scheme=version_scheme, + version=version, + tag_format=tag_format, + update_changelog_on_bump=update_changelog_on_bump, + major_version_zero=major_version_zero, + ) out.write("\nYou can bump the version running:\n") out.info("\tcz bump\n") out.success("Configuration complete 🚀") - def _ask_config_path(self) -> str: + def _ask_config_path(self) -> Path: default_path = ( "pyproject.toml" if self.project_info.has_pyproject else ".cz.toml" ) - name: str = questionary.select( + filename: str = questionary.select( "Please choose a supported config file: ", choices=CONFIG_FILES, default=default_path, style=self.cz.style, ).unsafe_ask() - return name + return Path(filename) def _ask_name(self) -> str: name: str = questionary.select( @@ -372,3 +364,30 @@ def _get_config_data(self) -> dict[str, Any]: else: repos.append(CZ_HOOK_CONFIG) return config_data + + +def _write_config_to_file( + *, + path: Path, + cz_name: str, + version_provider: str, + version_scheme: str, + version: Version, + tag_format: str, + update_changelog_on_bump: bool, + major_version_zero: bool, +) -> None: + out_config = create_config(path=path) + out_config.init_empty_config_content() + + out_config.set_key("name", cz_name) + out_config.set_key("tag_format", tag_format) + out_config.set_key("version_scheme", version_scheme) + if version_provider == "commitizen": + out_config.set_key("version", version.public) + else: + out_config.set_key("version_provider", version_provider) + if update_changelog_on_bump: + out_config.set_key("update_changelog_on_bump", update_changelog_on_bump) + if major_version_zero: + out_config.set_key("major_version_zero", major_version_zero) diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index 9dfd591c40..6cf8b840d8 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -1,58 +1,46 @@ from __future__ import annotations +from collections.abc import Generator from pathlib import Path from commitizen import defaults, git +from commitizen.config.factory import create_config from commitizen.exceptions import ConfigFileIsEmpty, ConfigFileNotFound from .base_config import BaseConfig -from .json_config import JsonConfig -from .toml_config import TomlConfig -from .yaml_config import YAMLConfig -def read_cfg(filepath: str | None = None) -> BaseConfig: - conf = BaseConfig() - +def _resolve_config_paths(filepath: str | None = None) -> Generator[Path, None, None]: if filepath is not None: - if not Path(filepath).exists(): + out_path = Path(filepath) + if not out_path.exists(): raise ConfigFileNotFound() - cfg_paths = (path for path in (Path(filepath),)) - else: - git_project_root = git.find_git_project_root() - cfg_search_paths = [Path(".")] - if git_project_root: - cfg_search_paths.append(git_project_root) + yield out_path + return - cfg_paths = ( - path / Path(filename) - for path in cfg_search_paths - for filename in defaults.CONFIG_FILES - ) + git_project_root = git.find_git_project_root() + cfg_search_paths = [Path(".")] + if git_project_root: + cfg_search_paths.append(git_project_root) - for filename in cfg_paths: - if not filename.exists(): - continue + for path in cfg_search_paths: + for filename in defaults.CONFIG_FILES: + out_path = path / Path(filename) + if out_path.exists(): + yield out_path - _conf: TomlConfig | JsonConfig | YAMLConfig +def read_cfg(filepath: str | None = None) -> BaseConfig: + for filename in _resolve_config_paths(filepath): with open(filename, "rb") as f: data: bytes = f.read() - if "toml" in filename.suffix: - _conf = TomlConfig(data=data, path=filename) - elif "json" in filename.suffix: - _conf = JsonConfig(data=data, path=filename) - elif "yaml" in filename.suffix: - _conf = YAMLConfig(data=data, path=filename) + conf = create_config(data=data, path=filename) + if not conf.is_empty_config: + return conf - if filepath is not None and _conf.is_empty_config: + if filepath is not None: raise ConfigFileIsEmpty() - elif _conf.is_empty_config: - continue - else: - conf = _conf - break - return conf + return BaseConfig() diff --git a/commitizen/config/base_config.py b/commitizen/config/base_config.py index 4b8f5f05fc..f7a6f3b8e8 100644 --- a/commitizen/config/base_config.py +++ b/commitizen/config/base_config.py @@ -17,8 +17,8 @@ class BaseConfig: def __init__(self) -> None: + self.is_empty_config = False self._settings: Settings = DEFAULT_SETTINGS.copy() - self.encoding = self.settings["encoding"] self._path: Path | None = None @property @@ -30,7 +30,7 @@ def path(self) -> Path: return self._path # type: ignore[return-value] @path.setter - def path(self, path: str | Path) -> None: + def path(self, path: Path) -> None: self._path = Path(path) def set_key(self, key: str, value: Any) -> Self: @@ -48,4 +48,8 @@ def _parse_setting(self, data: bytes | str) -> None: raise NotImplementedError() def init_empty_config_content(self) -> None: + """Create a config file with the empty config content. + + The implementation is different for each config file type. + """ raise NotImplementedError() diff --git a/commitizen/config/factory.py b/commitizen/config/factory.py new file mode 100644 index 0000000000..b77aea5f32 --- /dev/null +++ b/commitizen/config/factory.py @@ -0,0 +1,22 @@ +from __future__ import annotations + +from pathlib import Path + +from commitizen.config.base_config import BaseConfig +from commitizen.config.json_config import JsonConfig +from commitizen.config.toml_config import TomlConfig +from commitizen.config.yaml_config import YAMLConfig + + +def create_config(*, data: bytes | str | None = None, path: Path) -> BaseConfig: + if "toml" in path.suffix: + return TomlConfig(data=data or "", path=path) + if "json" in path.suffix: + return JsonConfig(data=data or "{}", path=path) + if "yaml" in path.suffix: + return YAMLConfig(data=data or "", path=path) + + # Should be unreachable. See the constant CONFIG_FILES. + raise ValueError( + f"Unsupported config file: {path.name} due to unknown file extension" + ) diff --git a/commitizen/config/json_config.py b/commitizen/config/json_config.py index be1f1c36b0..4655f48d5e 100644 --- a/commitizen/config/json_config.py +++ b/commitizen/config/json_config.py @@ -20,14 +20,15 @@ class JsonConfig(BaseConfig): - def __init__(self, *, data: bytes | str, path: Path | str) -> None: + def __init__(self, *, data: bytes | str, path: Path) -> None: super().__init__() - self.is_empty_config = False self.path = path self._parse_setting(data) def init_empty_config_content(self) -> None: - with smart_open(self.path, "a", encoding=self.encoding) as json_file: + with smart_open( + self.path, "a", encoding=self._settings["encoding"] + ) as json_file: json.dump({"commitizen": {}}, json_file) def set_key(self, key: str, value: Any) -> Self: @@ -40,7 +41,7 @@ def set_key(self, key: str, value: Any) -> Self: parser = json.load(f) parser["commitizen"][key] = value - with smart_open(self.path, "w", encoding=self.encoding) as f: + with smart_open(self.path, "w", encoding=self._settings["encoding"]) as f: json.dump(parser, f, indent=2) return self diff --git a/commitizen/config/toml_config.py b/commitizen/config/toml_config.py index 2164d3f992..8fa3d97828 100644 --- a/commitizen/config/toml_config.py +++ b/commitizen/config/toml_config.py @@ -21,9 +21,8 @@ class TomlConfig(BaseConfig): - def __init__(self, *, data: bytes | str, path: Path | str) -> None: + def __init__(self, *, data: bytes | str, path: Path) -> None: super().__init__() - self.is_empty_config = False self.path = path self._parse_setting(data) @@ -38,7 +37,9 @@ def init_empty_config_content(self) -> None: if parser.get("tool") is None: parser["tool"] = table() parser["tool"]["commitizen"] = table() # type: ignore[index] - output_toml_file.write(parser.as_string().encode(self.encoding)) + output_toml_file.write( + parser.as_string().encode(self._settings["encoding"]) + ) def set_key(self, key: str, value: Any) -> Self: """Set or update a key in the conf. @@ -51,7 +52,7 @@ def set_key(self, key: str, value: Any) -> Self: parser["tool"]["commitizen"][key] = value # type: ignore[index] with open(self.path, "wb") as f: - f.write(parser.as_string().encode(self.encoding)) + f.write(parser.as_string().encode(self._settings["encoding"])) return self def _parse_setting(self, data: bytes | str) -> None: diff --git a/commitizen/config/yaml_config.py b/commitizen/config/yaml_config.py index f2a79e6937..d2924ef023 100644 --- a/commitizen/config/yaml_config.py +++ b/commitizen/config/yaml_config.py @@ -21,14 +21,15 @@ class YAMLConfig(BaseConfig): - def __init__(self, *, data: bytes | str, path: Path | str) -> None: + def __init__(self, *, data: bytes | str, path: Path) -> None: super().__init__() - self.is_empty_config = False self.path = path self._parse_setting(data) def init_empty_config_content(self) -> None: - with smart_open(self.path, "a", encoding=self.encoding) as json_file: + with smart_open( + self.path, "a", encoding=self._settings["encoding"] + ) as json_file: yaml.dump({"commitizen": {}}, json_file, explicit_start=True) def _parse_setting(self, data: bytes | str) -> None: @@ -61,7 +62,9 @@ def set_key(self, key: str, value: Any) -> Self: parser = yaml.load(yaml_file, Loader=yaml.FullLoader) parser["commitizen"][key] = value - with smart_open(self.path, "w", encoding=self.encoding) as yaml_file: + with smart_open( + self.path, "w", encoding=self._settings["encoding"] + ) as yaml_file: yaml.dump(parser, yaml_file, explicit_start=True) return self diff --git a/tests/commands/conftest.py b/tests/commands/conftest.py index 91931849b2..4f9b5de3c6 100644 --- a/tests/commands/conftest.py +++ b/tests/commands/conftest.py @@ -3,7 +3,8 @@ import pytest from commitizen import defaults -from commitizen.config import BaseConfig, JsonConfig +from commitizen.config import BaseConfig +from commitizen.config.json_config import JsonConfig @pytest.fixture() diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 8c632a2b67..4d8492ac3b 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -3,6 +3,7 @@ import json import os import sys +from pathlib import Path from typing import Any import pytest @@ -87,7 +88,7 @@ def test_init_without_setup_pre_commit_hook( def test_init_when_config_already_exists(config: BaseConfig, capsys): # Set config path - path = os.sep.join(["tests", "pyproject.toml"]) + path = Path(os.sep.join(["tests", "pyproject.toml"])) config.path = path commands.Init(config)() diff --git a/tests/test_conf.py b/tests/test_conf.py index cc38bf4b05..0953401ea7 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -9,6 +9,9 @@ import yaml from commitizen import config, defaults, git +from commitizen.config.json_config import JsonConfig +from commitizen.config.toml_config import TomlConfig +from commitizen.config.yaml_config import YAMLConfig from commitizen.exceptions import ConfigFileIsEmpty, InvalidConfigurationError PYPROJECT = """ @@ -211,7 +214,7 @@ def test_load_cz_json_not_from_config_argument(_, tmpdir): _not_root_path.write(JSON_STR) cfg = config.read_cfg(filepath="./not_in_root/.cz.json") - json_cfg_by_class = config.JsonConfig(data=JSON_STR, path=_not_root_path) + json_cfg_by_class = JsonConfig(data=JSON_STR, path=_not_root_path) assert cfg.settings == json_cfg_by_class.settings def test_load_cz_yaml_not_from_config_argument(_, tmpdir): @@ -220,7 +223,7 @@ def test_load_cz_yaml_not_from_config_argument(_, tmpdir): _not_root_path.write(YAML_STR) cfg = config.read_cfg(filepath="./not_in_root/.cz.yaml") - yaml_cfg_by_class = config.YAMLConfig(data=YAML_STR, path=_not_root_path) + yaml_cfg_by_class = YAMLConfig(data=YAML_STR, path=_not_root_path) assert cfg.settings == yaml_cfg_by_class._settings def test_load_empty_pyproject_toml_from_config_argument(_, tmpdir): @@ -244,7 +247,7 @@ def test_load_empty_pyproject_toml_from_config_argument(_, tmpdir): class TestTomlConfig: def test_init_empty_config_content(self, tmpdir, config_file, exception_string): path = tmpdir.mkdir("commitizen").join(config_file) - toml_config = config.TomlConfig(data="", path=path) + toml_config = TomlConfig(data="", path=path) toml_config.init_empty_config_content() with open(path, encoding="utf-8") as toml_file: @@ -257,7 +260,7 @@ def test_init_empty_config_content_with_existing_content( path = tmpdir.mkdir("commitizen").join(config_file) path.write(existing_content) - toml_config = config.TomlConfig(data="", path=path) + toml_config = TomlConfig(data="", path=path) toml_config.init_empty_config_content() with open(path, encoding="utf-8") as toml_file: @@ -270,7 +273,7 @@ def test_init_with_invalid_config_content( path = tmpdir.mkdir("commitizen").join(config_file) with pytest.raises(InvalidConfigurationError, match=exception_string): - config.TomlConfig(data=existing_content, path=path) + TomlConfig(data=existing_content, path=path) @pytest.mark.parametrize( @@ -284,7 +287,7 @@ def test_init_with_invalid_config_content( class TestJsonConfig: def test_init_empty_config_content(self, tmpdir, config_file, exception_string): path = tmpdir.mkdir("commitizen").join(config_file) - json_config = config.JsonConfig(data="{}", path=path) + json_config = JsonConfig(data="{}", path=path) json_config.init_empty_config_content() with open(path, encoding="utf-8") as json_file: @@ -297,7 +300,7 @@ def test_init_with_invalid_config_content( path = tmpdir.mkdir("commitizen").join(config_file) with pytest.raises(InvalidConfigurationError, match=exception_string): - config.JsonConfig(data=existing_content, path=path) + JsonConfig(data=existing_content, path=path) @pytest.mark.parametrize( @@ -311,7 +314,7 @@ def test_init_with_invalid_config_content( class TestYamlConfig: def test_init_empty_config_content(self, tmpdir, config_file, exception_string): path = tmpdir.mkdir("commitizen").join(config_file) - yaml_config = config.YAMLConfig(data="{}", path=path) + yaml_config = YAMLConfig(data="{}", path=path) yaml_config.init_empty_config_content() with open(path) as yaml_file: @@ -322,4 +325,4 @@ def test_init_with_invalid_content(self, tmpdir, config_file, exception_string): path = tmpdir.mkdir("commitizen").join(config_file) with pytest.raises(InvalidConfigurationError, match=exception_string): - config.YAMLConfig(data=existing_content, path=path) + YAMLConfig(data=existing_content, path=path) diff --git a/tests/test_cz_customize.py b/tests/test_cz_customize.py index 933b1aa065..76341828d4 100644 --- a/tests/test_cz_customize.py +++ b/tests/test_cz_customize.py @@ -1,6 +1,11 @@ +from pathlib import Path + import pytest -from commitizen.config import BaseConfig, JsonConfig, TomlConfig, YAMLConfig +from commitizen.config import BaseConfig +from commitizen.config.json_config import JsonConfig +from commitizen.config.toml_config import TomlConfig +from commitizen.config.yaml_config import YAMLConfig from commitizen.cz.customize import CustomizeCommitsCz from commitizen.exceptions import MissingCzCustomizeConfigError @@ -319,8 +324,8 @@ @pytest.fixture( params=[ - TomlConfig(data=TOML_STR, path="not_exist.toml"), - JsonConfig(data=JSON_STR, path="not_exist.json"), + TomlConfig(data=TOML_STR, path=Path("not_exist.toml")), + JsonConfig(data=JSON_STR, path=Path("not_exist.json")), ] ) def config(request): @@ -334,9 +339,9 @@ def config(request): @pytest.fixture( params=[ - TomlConfig(data=TOML_STR_INFO_PATH, path="not_exist.toml"), - JsonConfig(data=JSON_STR_INFO_PATH, path="not_exist.json"), - YAMLConfig(data=YAML_STR_INFO_PATH, path="not_exist.yaml"), + TomlConfig(data=TOML_STR_INFO_PATH, path=Path("not_exist.toml")), + JsonConfig(data=JSON_STR_INFO_PATH, path=Path("not_exist.json")), + YAMLConfig(data=YAML_STR_INFO_PATH, path=Path("not_exist.yaml")), ] ) def config_info(request): @@ -345,9 +350,9 @@ def config_info(request): @pytest.fixture( params=[ - TomlConfig(data=TOML_STR_WITHOUT_INFO, path="not_exist.toml"), - JsonConfig(data=JSON_STR_WITHOUT_PATH, path="not_exist.json"), - YAMLConfig(data=YAML_STR_WITHOUT_PATH, path="not_exist.yaml"), + TomlConfig(data=TOML_STR_WITHOUT_INFO, path=Path("not_exist.toml")), + JsonConfig(data=JSON_STR_WITHOUT_PATH, path=Path("not_exist.json")), + YAMLConfig(data=YAML_STR_WITHOUT_PATH, path=Path("not_exist.yaml")), ] ) def config_without_info(request): @@ -356,8 +361,8 @@ def config_without_info(request): @pytest.fixture( params=[ - TomlConfig(data=TOML_WITH_UNICODE, path="not_exist.toml"), - JsonConfig(data=JSON_WITH_UNICODE, path="not_exist.json"), + TomlConfig(data=TOML_WITH_UNICODE, path=Path("not_exist.toml")), + JsonConfig(data=JSON_WITH_UNICODE, path=Path("not_exist.json")), ] ) def config_with_unicode(request): diff --git a/tests/test_cz_search_filter.py b/tests/test_cz_search_filter.py index 0e70e3104a..cbceb8b887 100644 --- a/tests/test_cz_search_filter.py +++ b/tests/test_cz_search_filter.py @@ -1,6 +1,6 @@ import pytest -from commitizen.config import TomlConfig +from commitizen.config.toml_config import TomlConfig from commitizen.cz.customize import CustomizeCommitsCz TOML_WITH_SEARCH_FILTER = r""" From e758e9929b5d103756d9bdbad5c8c91b1dbc3ea9 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 15 Sep 2025 14:05:23 +0800 Subject: [PATCH 068/221] refactor(Init): make project_info a module and remove self.project_info --- commitizen/commands/init.py | 91 ++--------------------------- commitizen/project_info.py | 47 +++++++++++++++ tests/commands/test_init_command.py | 4 +- tests/test_project_info.py | 90 ++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 87 deletions(-) create mode 100644 commitizen/project_info.py create mode 100644 tests/test_project_info.py diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 637caa2841..4a8a69d9e9 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -1,14 +1,12 @@ from __future__ import annotations -import os -import shutil from pathlib import Path from typing import Any, NamedTuple import questionary import yaml -from commitizen import cmd, factory, out +from commitizen import cmd, factory, out, project_info from commitizen.__version__ import __version__ from commitizen.config import ( BaseConfig, @@ -69,64 +67,12 @@ def title(self) -> str: ) -class ProjectInfo: - """Discover information about the current folder.""" - - @property - def has_pyproject(self) -> bool: - return os.path.isfile("pyproject.toml") - - @property - def has_uv_lock(self) -> bool: - return os.path.isfile("uv.lock") - - @property - def has_setup(self) -> bool: - return os.path.isfile("setup.py") - - @property - def has_pre_commit_config(self) -> bool: - return os.path.isfile(".pre-commit-config.yaml") - - @property - def is_python_uv(self) -> bool: - return self.has_pyproject and self.has_uv_lock - - @property - def is_python_poetry(self) -> bool: - if not self.has_pyproject: - return False - with open("pyproject.toml") as f: - return "[tool.poetry]" in f.read() - - @property - def is_python(self) -> bool: - return self.has_pyproject or self.has_setup - - @property - def is_rust_cargo(self) -> bool: - return os.path.isfile("Cargo.toml") - - @property - def is_npm_package(self) -> bool: - return os.path.isfile("package.json") - - @property - def is_php_composer(self) -> bool: - return os.path.isfile("composer.json") - - @property - def is_pre_commit_installed(self) -> bool: - return bool(shutil.which("pre-commit")) - - class Init: _PRE_COMMIT_CONFIG_PATH = ".pre-commit-config.yaml" def __init__(self, config: BaseConfig, *args: object) -> None: self.config: BaseConfig = config self.cz = factory.committer_factory(self.config) - self.project_info = ProjectInfo() def __call__(self) -> None: if self.config.path: @@ -172,7 +118,7 @@ def __call__(self) -> None: ) as config_file: yaml.safe_dump(config_data, stream=config_file) - if not self.project_info.is_pre_commit_installed: + if not project_info.is_pre_commit_installed(): raise InitFailedError( "Failed to install pre-commit hook.\n" "pre-commit is not installed in current environment." @@ -208,14 +154,10 @@ def __call__(self) -> None: out.success("Configuration complete 🚀") def _ask_config_path(self) -> Path: - default_path = ( - "pyproject.toml" if self.project_info.has_pyproject else ".cz.toml" - ) - filename: str = questionary.select( "Please choose a supported config file: ", choices=CONFIG_FILES, - default=default_path, + default=project_info.get_default_config_filename(), style=self.cz.style, ).unsafe_ask() return Path(filename) @@ -280,37 +222,17 @@ def _ask_version_provider(self) -> str: "Choose the source of the version:", choices=_VERSION_PROVIDER_CHOICES, style=self.cz.style, - default=self._default_version_provider, + default=project_info.get_default_version_provider(), ).unsafe_ask() return version_provider - @property - def _default_version_provider(self) -> str: - if self.project_info.is_python: - if self.project_info.is_python_poetry: - return "poetry" - if self.project_info.is_python_uv: - return "uv" - return "pep621" - - if self.project_info.is_rust_cargo: - return "cargo" - if self.project_info.is_npm_package: - return "npm" - if self.project_info.is_php_composer: - return "composer" - - return "commitizen" - def _ask_version_scheme(self) -> str: """Ask for setting: version_scheme""" - default_scheme = "pep440" if self.project_info.is_python else "semver" - scheme: str = questionary.select( "Choose version scheme: ", choices=KNOWN_SCHEMES, style=self.cz.style, - default=default_scheme, + default=project_info.get_default_version_scheme(), ).unsafe_ask() return scheme @@ -344,8 +266,7 @@ def _get_config_data(self) -> dict[str, Any]: ], } - if not self.project_info.has_pre_commit_config: - # .pre-commit-config.yaml does not exist + if not Path(".pre-commit-config.yaml").is_file(): return {"repos": [CZ_HOOK_CONFIG]} with open( diff --git a/commitizen/project_info.py b/commitizen/project_info.py new file mode 100644 index 0000000000..a754388008 --- /dev/null +++ b/commitizen/project_info.py @@ -0,0 +1,47 @@ +"""Resolves project information about the current working directory.""" + +import shutil +from pathlib import Path +from typing import Literal + + +def is_pre_commit_installed() -> bool: + return bool(shutil.which("pre-commit")) + + +def get_default_version_provider() -> Literal[ + "commitizen", "cargo", "composer", "npm", "pep621", "poetry", "uv" +]: + pyproject_path = Path("pyproject.toml") + if pyproject_path.is_file(): + if "[tool.poetry]" in pyproject_path.read_text(): + return "poetry" + if Path("uv.lock").is_file(): + return "uv" + return "pep621" + + if Path("setup.py").is_file(): + return "pep621" + + if Path("Cargo.toml").is_file(): + return "cargo" + + if Path("package.json").is_file(): + return "npm" + + if Path("composer.json").is_file(): + return "composer" + + return "commitizen" + + +def get_default_config_filename() -> Literal["pyproject.toml", ".cz.toml"]: + return "pyproject.toml" if Path("pyproject.toml").is_file() else ".cz.toml" + + +def get_default_version_scheme() -> Literal["pep440", "semver"]: + return ( + "pep440" + if Path("pyproject.toml").is_file() or Path("setup.py").is_file() + else "semver" + ) diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 4d8492ac3b..cfecfebeb1 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -122,7 +122,7 @@ def test_init_without_choosing_tag(config: BaseConfig, mocker: MockFixture, tmpd def pre_commit_installed(mocker: MockFixture): # Assume the `pre-commit` is installed mocker.patch( - "commitizen.commands.init.ProjectInfo.is_pre_commit_installed", + "commitizen.project_info.is_pre_commit_installed", return_value=True, ) # And installation success (i.e. no exception raised) @@ -232,7 +232,7 @@ def test_pre_commit_not_installed( ): # Assume `pre-commit` is not installed mocker.patch( - "commitizen.commands.init.ProjectInfo.is_pre_commit_installed", + "commitizen.project_info.is_pre_commit_installed", return_value=False, ) with tmpdir.as_cwd(): diff --git a/tests/test_project_info.py b/tests/test_project_info.py new file mode 100644 index 0000000000..d30a743e58 --- /dev/null +++ b/tests/test_project_info.py @@ -0,0 +1,90 @@ +"""Tests for project_info module.""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from commitizen import project_info + + +def _create_project_files(files: dict[str, str | None]) -> None: + for file_path, content in files.items(): + path = Path(file_path) + if content is None: + path.touch() + else: + path.write_text(content) + + +@pytest.mark.parametrize( + "which_return, expected", + [ + ("/usr/local/bin/pre-commit", True), + (None, False), + ("", False), + ], +) +def test_is_pre_commit_installed(mocker, which_return, expected): + mocker.patch("shutil.which", return_value=which_return) + assert project_info.is_pre_commit_installed() is expected + + +@pytest.mark.parametrize( + "files, expected", + [ + ( + {"pyproject.toml": '[tool.poetry]\nname = "test"\nversion = "0.1.0"'}, + "poetry", + ), + ({"pyproject.toml": "", "uv.lock": ""}, "uv"), + ( + {"pyproject.toml": '[tool.commitizen]\nversion = "0.1.0"'}, + "pep621", + ), + ({"setup.py": ""}, "pep621"), + ({"Cargo.toml": ""}, "cargo"), + ({"package.json": ""}, "npm"), + ({"composer.json": ""}, "composer"), + ({}, "commitizen"), + ( + { + "pyproject.toml": "", + "Cargo.toml": "", + "package.json": "", + "composer.json": "", + }, + "pep621", + ), + ], +) +def test_get_default_version_provider(chdir, files, expected): + _create_project_files(files) + assert project_info.get_default_version_provider() == expected + + +@pytest.mark.parametrize( + "files, expected", + [ + ({"pyproject.toml": ""}, "pyproject.toml"), + ({}, ".cz.toml"), + ], +) +def test_get_default_config_filename(chdir, files, expected): + _create_project_files(files) + assert project_info.get_default_config_filename() == expected + + +@pytest.mark.parametrize( + "files, expected", + [ + ({"pyproject.toml": ""}, "pep440"), + ({"setup.py": ""}, "pep440"), + ({"package.json": ""}, "semver"), + ({}, "semver"), + ], +) +def test_get_default_version_scheme(chdir, files, expected): + _create_project_files(files) + assert project_info.get_default_version_scheme() == expected From 8ab25ab530b1090267dd2ee1846e13995a922729 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 29 Sep 2025 11:15:54 +0800 Subject: [PATCH 069/221] refactor(hooks): refactor to improve readability --- hooks/prepare-commit-msg.py | 60 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/hooks/prepare-commit-msg.py b/hooks/prepare-commit-msg.py index a100f13afa..017ecc28ea 100755 --- a/hooks/prepare-commit-msg.py +++ b/hooks/prepare-commit-msg.py @@ -2,7 +2,7 @@ import shutil import subprocess import sys -from subprocess import CalledProcessError +from pathlib import Path try: from commitizen.cz.utils import get_backup_file_path @@ -23,33 +23,34 @@ def prepare_commit_msg(commit_msg_file: str) -> int: ], capture_output=True, ).returncode - if exit_code != 0: - backup_file_path = get_backup_file_path() - if backup_file_path.is_file(): - # confirm if commit message from backup file should be reused - answer = input("retry with previous message? [y/N]: ") - if answer.lower() == "y": - shutil.copyfile(backup_file_path, commit_msg_file) - return 0 - - # use commitizen to generate the commit message - try: - subprocess.run( - [ - "cz", - "commit", - "--dry-run", - "--write-message-to-file", - commit_msg_file, - ], - stdin=sys.stdin, - stdout=sys.stdout, - ).check_returncode() - except CalledProcessError as error: - return error.returncode - - # write message to backup file - shutil.copyfile(commit_msg_file, backup_file_path) + if exit_code == 0: + return 0 + + backup_file = Path(get_backup_file_path()) + if backup_file.is_file(): + # confirm if commit message from backup file should be reused + answer = input("retry with previous message? [y/N]: ") + if answer.lower() == "y": + shutil.copyfile(backup_file, commit_msg_file) + return 0 + + # use commitizen to generate the commit message + exit_code = subprocess.run( + [ + "cz", + "commit", + "--dry-run", + "--write-message-to-file", + commit_msg_file, + ], + stdin=sys.stdin, + stdout=sys.stdout, + ).returncode + if exit_code: + return exit_code + + # write message to backup file + shutil.copyfile(commit_msg_file, backup_file) return 0 @@ -57,4 +58,5 @@ def prepare_commit_msg(commit_msg_file: str) -> int: # make hook interactive by attaching /dev/tty to stdin with open("/dev/tty") as tty: sys.stdin = tty - exit(prepare_commit_msg(sys.argv[1])) + exit_code = prepare_commit_msg(sys.argv[1]) + exit(exit_code) From 33213d8df86a25dcf0fcea491569a5dfb810a3a2 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 29 Sep 2025 02:25:08 +0800 Subject: [PATCH 070/221] refactor(Commit): refactor _prompt_commit_questions and fix some type hint --- commitizen/commands/commit.py | 38 ++++++++++++++++++++--------------- commitizen/cz/base.py | 2 +- tests/conftest.py | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 8ab8d2cac9..5a37d4d7c9 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -63,33 +63,37 @@ def _read_backup_message(self) -> str | None: ) as f: return f.read().strip() - def _prompt_commit_questions(self) -> str: + def _get_message_by_prompt_commit_questions(self) -> str: # Prompt user for the commit message - cz = self.cz - questions = cz.questions() + questions = self.cz.questions() for question in (q for q in questions if q["type"] == "list"): question["use_shortcuts"] = self.config.settings["use_shortcuts"] try: - answers = questionary.prompt(questions, style=cz.style) + answers = questionary.prompt(questions, style=self.cz.style) except ValueError as err: root_err = err.__context__ if isinstance(root_err, CzException): - raise CustomError(root_err.__str__()) + raise CustomError(str(root_err)) raise err if not answers: raise NoAnswersError() - message = cz.message(answers) - message_len = len(message.partition("\n")[0].strip()) - message_length_limit = self.arguments.get("message_length_limit", 0) - if 0 < message_length_limit < message_len: + message = self.cz.message(answers) + self._validate_subject_length(message) + return message + + def _validate_subject_length(self, message: str) -> None: + # By the contract, message_length_limit is set to 0 for no limit + subject = message.partition("\n")[0].strip() + limit = self.arguments.get("message_length_limit", 0) + if limit == 0: + return + if len(subject) > limit: raise CommitMessageLengthExceededError( - f"Length of commit message exceeds limit ({message_len}/{message_length_limit})" + f"Length of commit message exceeds limit ({len(subject)}/{limit}), subject: '{subject}'" ) - return message - def manual_edit(self, message: str) -> str: editor = git.get_core_editor() if editor is None: @@ -114,11 +118,13 @@ def _get_message(self) -> str: raise NoCommitBackupError() return commit_message - if self.config.settings.get("retry_after_failure") and not self.arguments.get( - "no_retry" + if ( + self.config.settings.get("retry_after_failure") + and not self.arguments.get("no_retry") + and (backup_message := self._read_backup_message()) ): - return self._read_backup_message() or self._prompt_commit_questions() - return self._prompt_commit_questions() + return backup_message + return self._get_message_by_prompt_commit_questions() def __call__(self) -> None: extra_args = self.arguments.get("extra_cli_args", "") diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index ecb1a21962..8466b58bba 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -68,7 +68,7 @@ def __init__(self, config: BaseConfig) -> None: self.config.settings.update({"style": BaseCommitizen.default_style_config}) @abstractmethod - def questions(self) -> Iterable[CzQuestion]: + def questions(self) -> list[CzQuestion]: """Questions regarding the commit message.""" @abstractmethod diff --git a/tests/conftest.py b/tests/conftest.py index 61b64ae8d2..04a448d99a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -177,7 +177,7 @@ class SemverCommitizen(BaseCommitizen): "patch": "Bugs", } - def questions(self) -> list: + def questions(self) -> list[CzQuestion]: return [ { "type": "list", From fa8d227aefb7f28beac984fb31e3c6819503f086 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sat, 8 Nov 2025 16:36:39 +0800 Subject: [PATCH 071/221] fixup! refactor(Commit): refactor _prompt_commit_questions and fix some type hint --- commitizen/commands/commit.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 5a37d4d7c9..d16b4d8d88 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -80,18 +80,16 @@ def _get_message_by_prompt_commit_questions(self) -> str: raise NoAnswersError() message = self.cz.message(answers) - self._validate_subject_length(message) + if limit := self.arguments.get("message_length_limit", 0): + self._validate_subject_length(message=message, length_limit=limit) return message - def _validate_subject_length(self, message: str) -> None: + def _validate_subject_length(self, *, message: str, length_limit: int) -> None: # By the contract, message_length_limit is set to 0 for no limit subject = message.partition("\n")[0].strip() - limit = self.arguments.get("message_length_limit", 0) - if limit == 0: - return - if len(subject) > limit: + if len(subject) > length_limit: raise CommitMessageLengthExceededError( - f"Length of commit message exceeds limit ({len(subject)}/{limit}), subject: '{subject}'" + f"Length of commit message exceeds limit ({len(subject)}/{length_limit}), subject: '{subject}'" ) def manual_edit(self, message: str) -> str: From 596446e9ad8a53188b04df556b92be630d967520 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sat, 13 Sep 2025 21:38:24 +0800 Subject: [PATCH 072/221] refactor(TomlConfig): minor cleanups for DX --- commitizen/config/toml_config.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/commitizen/config/toml_config.py b/commitizen/config/toml_config.py index 8fa3d97828..0aadad8c1f 100644 --- a/commitizen/config/toml_config.py +++ b/commitizen/config/toml_config.py @@ -2,9 +2,9 @@ import os from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING -from tomlkit import exceptions, parse, table +from tomlkit import TOMLDocument, exceptions, parse, table from commitizen.exceptions import InvalidConfigurationError @@ -27,32 +27,33 @@ def __init__(self, *, data: bytes | str, path: Path) -> None: self._parse_setting(data) def init_empty_config_content(self) -> None: + config_doc = TOMLDocument() if os.path.isfile(self.path): with open(self.path, "rb") as input_toml_file: - parser = parse(input_toml_file.read()) - else: - parser = parse("") + config_doc = parse(input_toml_file.read()) + + if config_doc.get("tool") is None: + config_doc["tool"] = table() + config_doc["tool"]["commitizen"] = table() # type: ignore[index] with open(self.path, "wb") as output_toml_file: - if parser.get("tool") is None: - parser["tool"] = table() - parser["tool"]["commitizen"] = table() # type: ignore[index] output_toml_file.write( - parser.as_string().encode(self._settings["encoding"]) + config_doc.as_string().encode(self._settings["encoding"]) ) - def set_key(self, key: str, value: Any) -> Self: + def set_key(self, key: str, value: object) -> Self: """Set or update a key in the conf. For now only strings are supported. We use to update the version number. """ with open(self.path, "rb") as f: - parser = parse(f.read()) + config_doc = parse(f.read()) - parser["tool"]["commitizen"][key] = value # type: ignore[index] + config_doc["tool"]["commitizen"][key] = value # type: ignore[index] with open(self.path, "wb") as f: - f.write(parser.as_string().encode(self._settings["encoding"])) + f.write(config_doc.as_string().encode(self._settings["encoding"])) + return self def _parse_setting(self, data: bytes | str) -> None: From d77da0930c18c7636f9f387ea6cf427a57e8bfee Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sun, 14 Sep 2025 22:15:36 +0800 Subject: [PATCH 073/221] style(BaseConfig): update set_key comments and type annotation, remove duplicated docstring --- commitizen/config/base_config.py | 9 ++++----- commitizen/config/json_config.py | 15 +++++---------- commitizen/config/toml_config.py | 5 ----- commitizen/config/yaml_config.py | 15 +++++---------- 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/commitizen/config/base_config.py b/commitizen/config/base_config.py index f7a6f3b8e8..98270915d8 100644 --- a/commitizen/config/base_config.py +++ b/commitizen/config/base_config.py @@ -1,7 +1,7 @@ from __future__ import annotations from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING from commitizen.defaults import DEFAULT_SETTINGS, Settings @@ -33,11 +33,10 @@ def path(self) -> Path: def path(self, path: Path) -> None: self._path = Path(path) - def set_key(self, key: str, value: Any) -> Self: - """Set or update a key in the conf. + def set_key(self, key: str, value: object) -> Self: + """Set or update a key in the config file. - For now only strings are supported. - We use to update the version number. + Currently, only strings are supported for the parameter key. """ raise NotImplementedError() diff --git a/commitizen/config/json_config.py b/commitizen/config/json_config.py index 4655f48d5e..4e7097aa1a 100644 --- a/commitizen/config/json_config.py +++ b/commitizen/config/json_config.py @@ -2,7 +2,7 @@ import json from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING from commitizen.exceptions import InvalidConfigurationError from commitizen.git import smart_open @@ -31,18 +31,13 @@ def init_empty_config_content(self) -> None: ) as json_file: json.dump({"commitizen": {}}, json_file) - def set_key(self, key: str, value: Any) -> Self: - """Set or update a key in the conf. - - For now only strings are supported. - We use to update the version number. - """ + def set_key(self, key: str, value: object) -> Self: with open(self.path, "rb") as f: - parser = json.load(f) + config_doc = json.load(f) - parser["commitizen"][key] = value + config_doc["commitizen"][key] = value with smart_open(self.path, "w", encoding=self._settings["encoding"]) as f: - json.dump(parser, f, indent=2) + json.dump(config_doc, f, indent=2) return self def _parse_setting(self, data: bytes | str) -> None: diff --git a/commitizen/config/toml_config.py b/commitizen/config/toml_config.py index 0aadad8c1f..4ea1dca7d4 100644 --- a/commitizen/config/toml_config.py +++ b/commitizen/config/toml_config.py @@ -42,11 +42,6 @@ def init_empty_config_content(self) -> None: ) def set_key(self, key: str, value: object) -> Self: - """Set or update a key in the conf. - - For now only strings are supported. - We use to update the version number. - """ with open(self.path, "rb") as f: config_doc = parse(f.read()) diff --git a/commitizen/config/yaml_config.py b/commitizen/config/yaml_config.py index d2924ef023..c048ab272a 100644 --- a/commitizen/config/yaml_config.py +++ b/commitizen/config/yaml_config.py @@ -1,7 +1,7 @@ from __future__ import annotations from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING import yaml @@ -52,19 +52,14 @@ def _parse_setting(self, data: bytes | str) -> None: except (KeyError, TypeError): self.is_empty_config = True - def set_key(self, key: str, value: Any) -> Self: - """Set or update a key in the conf. - - For now only strings are supported. - We use to update the version number. - """ + def set_key(self, key: str, value: object) -> Self: with open(self.path, "rb") as yaml_file: - parser = yaml.load(yaml_file, Loader=yaml.FullLoader) + config_doc = yaml.load(yaml_file, Loader=yaml.FullLoader) - parser["commitizen"][key] = value + config_doc["commitizen"][key] = value with smart_open( self.path, "w", encoding=self._settings["encoding"] ) as yaml_file: - yaml.dump(parser, yaml_file, explicit_start=True) + yaml.dump(config_doc, yaml_file, explicit_start=True) return self From 79a420cdaf6254fd3e379c5607c44cb4777f0833 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 15 Sep 2025 20:58:05 +0800 Subject: [PATCH 074/221] refactor(RestructuredTest): rename variable, fix typo and remove unnecessary string copy --- .../changelog_formats/restructuredtext.py | 118 +++++++++--------- .../test_changelog_format_restructuredtext.py | 14 ++- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/commitizen/changelog_formats/restructuredtext.py b/commitizen/changelog_formats/restructuredtext.py index b7e4e105a1..e8ce411e80 100644 --- a/commitizen/changelog_formats/restructuredtext.py +++ b/commitizen/changelog_formats/restructuredtext.py @@ -1,92 +1,88 @@ from __future__ import annotations -import sys from itertools import zip_longest -from typing import IO, TYPE_CHECKING, Any, Union +from typing import IO from commitizen.changelog import Metadata from .base import BaseFormat -if TYPE_CHECKING: - # TypeAlias is Python 3.10+ but backported in typing-extensions - if sys.version_info >= (3, 10): - from typing import TypeAlias - else: - from typing_extensions import TypeAlias - - -# Can't use `|` operator and native type because of https://bugs.python.org/issue42233 only fixed in 3.10 -TitleKind: TypeAlias = Union[str, tuple[str, str]] - class RestructuredText(BaseFormat): extension = "rst" - def get_metadata_from_file(self, file: IO[Any]) -> Metadata: + def get_metadata_from_file(self, file: IO[str]) -> Metadata: """ RestructuredText section titles are not one-line-based, they spread on 2 or 3 lines and levels are not predefined - but determined byt their occurrence order. + but determined by their occurrence order. It requires its own algorithm. For a more generic approach, you need to rely on `docutils`. """ - meta = Metadata() - unreleased_title_kind: TitleKind | None = None - in_overlined_title = False - lines = file.readlines() + out_metadata = Metadata() + unreleased_title_kind: str | tuple[str, str] | None = None + is_overlined_title = False + lines = [line.strip().lower() for line in file.readlines()] + for index, (first, second, third) in enumerate( zip_longest(lines, lines[1:], lines[2:], fillvalue="") ): - first = first.strip().lower() - second = second.strip().lower() - third = third.strip().lower() title: str | None = None - kind: TitleKind | None = None - if self.is_overlined_title(first, second, third): + kind: str | tuple[str, str] | None = None + if _is_overlined_title(first, second, third): title = second kind = (first[0], third[0]) - in_overlined_title = True - elif not in_overlined_title and self.is_underlined_title(first, second): + is_overlined_title = True + elif not is_overlined_title and _is_underlined_title(first, second): title = first kind = second[0] else: - in_overlined_title = False - - if title: - if "unreleased" in title: - unreleased_title_kind = kind - meta.unreleased_start = index - continue - elif unreleased_title_kind and unreleased_title_kind == kind: - meta.unreleased_end = index - # Try to find the latest release done - if version := self.tag_rules.search_version(title): - meta.latest_version = version[0] - meta.latest_version_tag = version[1] - meta.latest_version_position = index - break - if meta.unreleased_start is not None and meta.unreleased_end is None: - meta.unreleased_end = ( - meta.latest_version_position if meta.latest_version else index + 1 + is_overlined_title = False + + if not title: + continue + + if "unreleased" in title: + unreleased_title_kind = kind + out_metadata.unreleased_start = index + continue + + if unreleased_title_kind and unreleased_title_kind == kind: + out_metadata.unreleased_end = index + # Try to find the latest release done + if version := self.tag_rules.search_version(title): + out_metadata.latest_version = version[0] + out_metadata.latest_version_tag = version[1] + out_metadata.latest_version_position = index + break + + if ( + out_metadata.unreleased_start is not None + and out_metadata.unreleased_end is None + ): + out_metadata.unreleased_end = ( + out_metadata.latest_version_position + if out_metadata.latest_version + else len(lines) ) - return meta - - def is_overlined_title(self, first: str, second: str, third: str) -> bool: - return ( - len(first) >= len(second) - and len(first) == len(third) - and all(char == first[0] for char in first[1:]) - and first[0] == third[0] - and self.is_underlined_title(second, third) - ) - - def is_underlined_title(self, first: str, second: str) -> bool: - return ( - len(second) >= len(first) - and not second.isalnum() - and all(char == second[0] for char in second[1:]) - ) + return out_metadata + + +def _is_overlined_title(first: str, second: str, third: str) -> bool: + return ( + len(first) == len(third) >= len(second) + and first[0] == third[0] + and all(char == first[0] for char in first) + and _is_underlined_title(second, third) + ) + + +def _is_underlined_title(first: str, second: str) -> bool: + return ( + len(second) >= len(first) + and not second.isalnum() + and all(char == second[0] for char in second) + ) diff --git a/tests/test_changelog_format_restructuredtext.py b/tests/test_changelog_format_restructuredtext.py index 14bc15ec09..ca79620ad3 100644 --- a/tests/test_changelog_format_restructuredtext.py +++ b/tests/test_changelog_format_restructuredtext.py @@ -7,7 +7,11 @@ import pytest from commitizen.changelog import Metadata -from commitizen.changelog_formats.restructuredtext import RestructuredText +from commitizen.changelog_formats.restructuredtext import ( + RestructuredText, + _is_overlined_title, + _is_underlined_title, +) from commitizen.config.base_config import BaseConfig if TYPE_CHECKING: @@ -325,9 +329,9 @@ def test_get_metadata( [(text, True) for text in UNDERLINED_TITLES] + [(text, False) for text in NOT_UNDERLINED_TITLES], ) -def test_is_underlined_title(format: RestructuredText, text: str, expected: bool): +def test_is_underlined_title(text: str, expected: bool): _, first, second = dedent(text).splitlines() - assert format.is_underlined_title(first, second) is expected + assert _is_underlined_title(first, second) is expected @pytest.mark.parametrize( @@ -335,10 +339,10 @@ def test_is_underlined_title(format: RestructuredText, text: str, expected: bool [(text, True) for text in OVERLINED_TITLES] + [(text, False) for text in NOT_OVERLINED_TITLES], ) -def test_is_overlined_title(format: RestructuredText, text: str, expected: bool): +def test_is_overlined_title(text: str, expected: bool): _, first, second, third = dedent(text).splitlines() - assert format.is_overlined_title(first, second, third) is expected + assert _is_overlined_title(first, second, third) is expected @pytest.mark.parametrize( From d895b47b319b71e5ed071b48ed31561a4f469c9e Mon Sep 17 00:00:00 2001 From: Sebastien Fusilier Date: Mon, 1 Sep 2025 14:11:38 +0000 Subject: [PATCH 075/221] feat(conventional_commits): allow exclamation in title on BC Add a configuration (disable by default) to allow exclamation in commit title to ease identify BC simple git log parsing. Signed-off-by: Sebastien Fusilier --- .../conventional_commits.py | 14 +++--- commitizen/defaults.py | 2 + docs/config.md | 10 ++++ docs/tutorials/writing_commits.md | 5 ++ tests/test_conf.py | 2 + tests/test_cz_conventional_commits.py | 49 +++++++++++++++++++ 6 files changed, 74 insertions(+), 8 deletions(-) diff --git a/commitizen/cz/conventional_commits/conventional_commits.py b/commitizen/cz/conventional_commits/conventional_commits.py index c827cebb78..acb0dfe094 100644 --- a/commitizen/cz/conventional_commits/conventional_commits.py +++ b/commitizen/cz/conventional_commits/conventional_commits.py @@ -154,17 +154,15 @@ def message(self, answers: ConventionalCommitsAnswers) -> str: # type: ignore[o footer = answers["footer"] is_breaking_change = answers["is_breaking_change"] - if scope: - # example: "fix(users): email pattern corrected" - first_line = f"{prefix}({scope}): {subject}" - else: - # example: "fix: email pattern corrected" - first_line = f"{prefix}: {subject}" - + scope = f"({scope})" if scope else "" + body = f"\n\n{body}" if body else "" + title = f"{prefix}{scope}" if is_breaking_change: + if self.config.settings.get("breaking_change_exclamation_in_title", False): + title = f"{title}!" footer = f"BREAKING CHANGE: {footer}" - return "\n\n".join(s for s in (first_line, body, footer) if s) + return f"{title}: {subject}{body}{footer}" def example(self) -> str: return ( diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 4840a69b6a..68e580f52b 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -61,6 +61,7 @@ class Settings(TypedDict, total=False): version_scheme: str | None version_type: str | None version: str | None + breaking_change_exclamation_in_title: bool CONFIG_FILES: list[str] = [ @@ -109,6 +110,7 @@ class Settings(TypedDict, total=False): "always_signoff": False, "template": None, # default provided by plugin "extras": {}, + "breaking_change_exclamation_in_title": False, } MAJOR = "MAJOR" diff --git a/docs/config.md b/docs/config.md index 05f45a1a80..c00a6f72a8 100644 --- a/docs/config.md +++ b/docs/config.md @@ -96,6 +96,15 @@ Use annotated tags instead of lightweight tags. [See difference][annotated-tags- Create custom commit message. Useful to skip CI. [Read more][bump_message] +### `breaking_change_exclamation_in_title` + +Type: `bool` + +Default: `False` + +When true, breaking changes will be also indicated by an exclamation mark in the commit title (e.g., `feat!: breaking change`). +When false, breaking changes will be only indicated by `BREAKING CHANGE:` in the footer. [Read more][writing_commits] + ### `retry_after_failure` - Type: `bool` @@ -401,3 +410,4 @@ setup( [template-customization]: customization.md#customizing-the-changelog-template [annotated-tags-vs-lightweight]: https://stackoverflow.com/a/11514139/2047185 [encoding]: tutorials/writing_commits.md#writing-commits +[writing_commits]: tutorials/writing_commits.md#conventional-commits diff --git a/docs/tutorials/writing_commits.md b/docs/tutorials/writing_commits.md index 7d9139929c..a64480874a 100644 --- a/docs/tutorials/writing_commits.md +++ b/docs/tutorials/writing_commits.md @@ -13,6 +13,10 @@ add to your commit body the following `BREAKING CHANGE`. Using these three keywords will allow the proper identification of the semantic version. Of course, there are other keywords, but I'll leave it to the reader to explore them. +Note: You can also indicate breaking changes by adding an exclamation mark in the commit title +(e.g., `feat!: breaking change`) by setting the `breaking_change_exclamation_in_title` +configuration option to `true`. [Read more][breaking-change-config] + ## Writing commits Now to the important part: when writing commits, it's important to think about: @@ -44,3 +48,4 @@ Emojis may be added as well (e.g., see [cz-emoji][cz_emoji]), which requires the [conventional_commits]: https://www.conventionalcommits.org [cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-commitizen/#cz-emoji [configuration]: ../config.md#encoding +[breaking-change-config]: ../config.md#breaking_change_exclamation_in_title diff --git a/tests/test_conf.py b/tests/test_conf.py index 0953401ea7..47633c7e01 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -105,6 +105,7 @@ "always_signoff": False, "template": None, "extras": {}, + "breaking_change_exclamation_in_title": False, } _new_settings: dict[str, Any] = { @@ -143,6 +144,7 @@ "always_signoff": False, "template": None, "extras": {}, + "breaking_change_exclamation_in_title": False, } diff --git a/tests/test_cz_conventional_commits.py b/tests/test_cz_conventional_commits.py index c96e036707..1742b0f3b7 100644 --- a/tests/test_cz_conventional_commits.py +++ b/tests/test_cz_conventional_commits.py @@ -105,6 +105,55 @@ def test_breaking_change_in_footer(config): ) +@pytest.mark.parametrize( + "scope,breaking_change_exclamation_in_title,expected_message", + [ + # Test with scope and breaking_change_exclamation_in_title enabled + ( + "users", + True, + "feat(users)!: email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users", + ), + # Test without scope and breaking_change_exclamation_in_title enabled + ( + "", + True, + "feat!: email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users", + ), + # Test with scope and breaking_change_exclamation_in_title disabled + ( + "users", + False, + "feat(users): email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users", + ), + # Test without scope and breaking_change_exclamation_in_title disabled + ( + "", + False, + "feat: email pattern corrected\n\ncomplete content\n\nBREAKING CHANGE: migrate by renaming user to users", + ), + ], +) +def test_breaking_change_message_formats( + config, scope, breaking_change_exclamation_in_title, expected_message +): + # Set the breaking_change_exclamation_in_title setting + config.settings["breaking_change_exclamation_in_title"] = ( + breaking_change_exclamation_in_title + ) + conventional_commits = ConventionalCommitsCz(config) + answers = { + "prefix": "feat", + "scope": scope, + "subject": "email pattern corrected", + "is_breaking_change": True, + "body": "complete content", + "footer": "migrate by renaming user to users", + } + message = conventional_commits.message(answers) + assert message == expected_message + + def test_example(config): """just testing a string is returned. not the content""" conventional_commits = ConventionalCommitsCz(config) From 327677abc0833ee5dc9aa748c90730b106d1b7a7 Mon Sep 17 00:00:00 2001 From: Sebastien Fusilier Date: Tue, 9 Sep 2025 13:43:06 +0000 Subject: [PATCH 076/221] fix(test): set terminal width for cli tests Force consistent terminal width for tests to avoid wrapping differences between single and multi-worker pytest modes Signed-off-by: Sebastien Fusilier --- .../conventional_commits.py | 10 ++++--- tests/commands/test_version_command.py | 27 ++++++++++++++----- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/commitizen/cz/conventional_commits/conventional_commits.py b/commitizen/cz/conventional_commits/conventional_commits.py index acb0dfe094..f0b254eb10 100644 --- a/commitizen/cz/conventional_commits/conventional_commits.py +++ b/commitizen/cz/conventional_commits/conventional_commits.py @@ -154,15 +154,17 @@ def message(self, answers: ConventionalCommitsAnswers) -> str: # type: ignore[o footer = answers["footer"] is_breaking_change = answers["is_breaking_change"] - scope = f"({scope})" if scope else "" - body = f"\n\n{body}" if body else "" - title = f"{prefix}{scope}" + formatted_scope = f"({scope})" if scope else "" + title = f"{prefix}{formatted_scope}" if is_breaking_change: if self.config.settings.get("breaking_change_exclamation_in_title", False): title = f"{title}!" footer = f"BREAKING CHANGE: {footer}" - return f"{title}: {subject}{body}{footer}" + formatted_body = f"\n\n{body}" if body else "" + formatted_footter = f"\n\n{footer}" if footer else "" + + return f"{title}: {subject}{formatted_body}{formatted_footter}" def example(self) -> str: return ( diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index cd2e7f77e0..7b5b13a7e1 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -1,3 +1,4 @@ +import os import platform import sys @@ -112,13 +113,25 @@ def test_version_use_version_provider( def test_version_command_shows_description_when_use_help_option( mocker: MockerFixture, capsys, file_regression ): - testargs = ["cz", "version", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") + # Force consistent terminal width for tests to avoid wrapping differences + # between single and multi-worker pytest modes + original_columns = os.environ.get("COLUMNS") + os.environ["COLUMNS"] = "80" + + try: + testargs = ["cz", "version", "--help"] + mocker.patch.object(sys, "argv", testargs) + with pytest.raises(SystemExit): + cli.main() + + out, _ = capsys.readouterr() + file_regression.check(out, extension=".txt") + finally: + # Restore original COLUMNS + if original_columns is not None: + os.environ["COLUMNS"] = original_columns + else: + os.environ.pop("COLUMNS", None) @pytest.mark.parametrize( From 0e9497050b9e04a5c045ea872ec4239aeb7dfb0b Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 10 Sep 2025 23:23:33 +0800 Subject: [PATCH 077/221] refactor(bump): cleanup related to update_version_file --- commitizen/bump.py | 81 ++++----- tests/test_bump_update_version_in_files.py | 182 ++++++++++++++++++++- 2 files changed, 207 insertions(+), 56 deletions(-) diff --git a/commitizen/bump.py b/commitizen/bump.py index 6d6b6dc069..6672c5f509 100644 --- a/commitizen/bump.py +++ b/commitizen/bump.py @@ -3,13 +3,13 @@ import os import re from collections import OrderedDict -from collections.abc import Iterable +from collections.abc import Generator, Iterable from glob import iglob from logging import getLogger from string import Template from typing import cast -from commitizen.defaults import BUMP_MESSAGE, ENCODING, MAJOR, MINOR, PATCH +from commitizen.defaults import BUMP_MESSAGE, MAJOR, MINOR, PATCH from commitizen.exceptions import CurrentVersionNotFoundError from commitizen.git import GitCommit, smart_open from commitizen.version_schemes import Increment, Version @@ -64,8 +64,8 @@ def update_version_in_files( new_version: str, files: Iterable[str], *, - check_consistency: bool = False, - encoding: str = ENCODING, + check_consistency: bool, + encoding: str, ) -> list[str]: """Change old version to the new one in every file given. @@ -75,16 +75,22 @@ def update_version_in_files( Returns the list of updated files. """ - # TODO: separate check step and write step - updated = [] - for path, regex in _files_and_regexes(files, current_version): - current_version_found, version_file = _bump_with_regex( - path, - current_version, - new_version, - regex, - encoding=encoding, - ) + updated_files = [] + + for path, pattern in _resolve_files_and_regexes(files, current_version): + current_version_found = False + bumped_lines = [] + + with open(path, encoding=encoding) as version_file: + for line in version_file: + bumped_line = ( + line.replace(current_version, new_version) + if pattern.search(line) + else line + ) + + current_version_found = current_version_found or bumped_line != line + bumped_lines.append(bumped_line) if check_consistency and not current_version_found: raise CurrentVersionNotFoundError( @@ -93,53 +99,32 @@ def update_version_in_files( "version_files are possibly inconsistent." ) + bumped_version_file_content = "".join(bumped_lines) + # Write the file out again with smart_open(path, "w", encoding=encoding) as file: - file.write(version_file) - updated.append(path) - return updated + file.write(bumped_version_file_content) + updated_files.append(path) + + return updated_files -def _files_and_regexes(patterns: Iterable[str], version: str) -> list[tuple[str, str]]: +def _resolve_files_and_regexes( + patterns: Iterable[str], version: str +) -> Generator[tuple[str, re.Pattern], None, None]: """ Resolve all distinct files with their regexp from a list of glob patterns with optional regexp """ - out: set[tuple[str, str]] = set() + filepath_set: set[tuple[str, str]] = set() for pattern in patterns: drive, tail = os.path.splitdrive(pattern) path, _, regex = tail.partition(":") filepath = drive + path - if not regex: - regex = re.escape(version) + regex = regex or re.escape(version) - for file in iglob(filepath): - out.add((file, regex)) + filepath_set.update((path, regex) for path in iglob(filepath)) - return sorted(out) - - -def _bump_with_regex( - version_filepath: str, - current_version: str, - new_version: str, - regex: str, - encoding: str = ENCODING, -) -> tuple[bool, str]: - current_version_found = False - lines = [] - pattern = re.compile(regex) - with open(version_filepath, encoding=encoding) as f: - for line in f: - if not pattern.search(line): - lines.append(line) - continue - - bumped_line = line.replace(current_version, new_version) - if bumped_line != line: - current_version_found = True - lines.append(bumped_line) - - return current_version_found, "".join(lines) + return ((path, re.compile(regex)) for path, regex in sorted(filepath_set)) def create_commit_message( diff --git a/tests/test_bump_update_version_in_files.py b/tests/test_bump_update_version_in_files.py index c14e4ad1cb..5a74c1c456 100644 --- a/tests/test_bump_update_version_in_files.py +++ b/tests/test_bump_update_version_in_files.py @@ -103,7 +103,11 @@ def test_update_version_in_files(version_files, file_regression): old_version = "1.2.3" new_version = "2.0.0" bump.update_version_in_files( - old_version, new_version, version_files, encoding="utf-8" + old_version, + new_version, + version_files, + check_consistency=False, + encoding="utf-8", ) file_contents = "" @@ -119,7 +123,9 @@ def test_partial_update_of_file(version_repeated_file, file_regression): regex = "version" location = f"{version_repeated_file}:{regex}" - bump.update_version_in_files(old_version, new_version, [location], encoding="utf-8") + bump.update_version_in_files( + old_version, new_version, [location], check_consistency=False, encoding="utf-8" + ) with open(version_repeated_file, encoding="utf-8") as f: file_regression.check(f.read(), extension=".json") @@ -129,7 +135,9 @@ def test_random_location(random_location_version_file, file_regression): new_version = "2.0.0" location = f"{random_location_version_file}:version.+Commitizen" - bump.update_version_in_files(old_version, new_version, [location], encoding="utf-8") + bump.update_version_in_files( + old_version, new_version, [location], check_consistency=False, encoding="utf-8" + ) with open(random_location_version_file, encoding="utf-8") as f: file_regression.check(f.read(), extension=".lock") @@ -141,7 +149,9 @@ def test_duplicates_are_change_with_no_regex( new_version = "2.0.0" location = f"{random_location_version_file}:version" - bump.update_version_in_files(old_version, new_version, [location], encoding="utf-8") + bump.update_version_in_files( + old_version, new_version, [location], check_consistency=False, encoding="utf-8" + ) with open(random_location_version_file, encoding="utf-8") as f: file_regression.check(f.read(), extension=".lock") @@ -153,7 +163,9 @@ def test_version_bump_increase_string_length( new_version = "1.2.10" location = f"{multiple_versions_increase_string}:version" - bump.update_version_in_files(old_version, new_version, [location], encoding="utf-8") + bump.update_version_in_files( + old_version, new_version, [location], check_consistency=False, encoding="utf-8" + ) with open(multiple_versions_increase_string, encoding="utf-8") as f: file_regression.check(f.read(), extension=".txt") @@ -165,7 +177,9 @@ def test_version_bump_reduce_string_length( new_version = "2.0.0" location = f"{multiple_versions_reduce_string}:version" - bump.update_version_in_files(old_version, new_version, [location], encoding="utf-8") + bump.update_version_in_files( + old_version, new_version, [location], check_consistency=False, encoding="utf-8" + ) with open(multiple_versions_reduce_string, encoding="utf-8") as f: file_regression.check(f.read(), extension=".txt") @@ -204,7 +218,9 @@ def test_multiple_versions_to_bump( new_version = "1.2.10" location = f"{multiple_versions_to_update_poetry_lock}:version" - bump.update_version_in_files(old_version, new_version, [location], encoding="utf-8") + bump.update_version_in_files( + old_version, new_version, [location], check_consistency=False, encoding="utf-8" + ) with open(multiple_versions_to_update_poetry_lock, encoding="utf-8") as f: file_regression.check(f.read(), extension=".toml") @@ -220,8 +236,158 @@ def test_update_version_in_globbed_files(commitizen_config_file, file_regression version_files = [commitizen_config_file.dirpath("*.toml")] bump.update_version_in_files( - old_version, new_version, version_files, encoding="utf-8" + old_version, + new_version, + version_files, + check_consistency=False, + encoding="utf-8", ) for file in commitizen_config_file, other: file_regression.check(file.read_text("utf-8"), extension=".toml") + + +def test_update_version_in_files_with_check_consistency_true(version_files): + """Test update_version_in_files with check_consistency=True (success case).""" + old_version = "1.2.3" + new_version = "2.0.0" + + # This should succeed because all files contain the current version + updated_files = bump.update_version_in_files( + old_version, + new_version, + version_files, + check_consistency=True, + encoding="utf-8", + ) + + # Verify that all files were updated + assert len(updated_files) == len(version_files) + for file_path in updated_files: + assert file_path in version_files + + +def test_update_version_in_files_with_check_consistency_true_failure( + commitizen_config_file, inconsistent_python_version_file +): + """Test update_version_in_files with check_consistency=True (failure case).""" + old_version = "1.2.3" + new_version = "2.0.0" + version_files = [commitizen_config_file, inconsistent_python_version_file] + + # This should fail because inconsistent_python_version_file doesn't contain the current version + with pytest.raises(CurrentVersionNotFoundError) as excinfo: + bump.update_version_in_files( + old_version, + new_version, + version_files, + check_consistency=True, + encoding="utf-8", + ) + + expected_msg = ( + f"Current version {old_version} is not found in {inconsistent_python_version_file}.\n" + "The version defined in commitizen configuration and the ones in " + "version_files are possibly inconsistent." + ) + assert expected_msg in str(excinfo.value) + + +@pytest.mark.parametrize( + "encoding,filename", + [ + ("latin-1", "test_latin1.txt"), + ("utf-16", "test_utf16.txt"), + ], + ids=["latin-1", "utf-16"], +) +def test_update_version_in_files_with_different_encodings(tmp_path, encoding, filename): + """Test update_version_in_files with different encodings.""" + # Create a test file with the specified encoding + test_file = tmp_path / filename + content = f'version = "1.2.3"\n# This is a test file with {encoding} encoding\n' + test_file.write_text(content, encoding=encoding) + + old_version = "1.2.3" + new_version = "2.0.0" + + updated_files = bump.update_version_in_files( + old_version, + new_version, + [str(test_file)], + check_consistency=True, + encoding=encoding, + ) + + # Verify the file was updated + assert len(updated_files) == 1 + assert str(test_file) in updated_files + + # Verify the content was updated correctly + updated_content = test_file.read_text(encoding=encoding) + assert f'version = "{new_version}"' in updated_content + assert f'version = "{old_version}"' not in updated_content + + +def test_update_version_in_files_return_value(version_files): + """Test that update_version_in_files returns the correct list of updated files.""" + old_version = "1.2.3" + new_version = "2.0.0" + + updated_files = bump.update_version_in_files( + old_version, + new_version, + version_files, + check_consistency=False, + encoding="utf-8", + ) + + # Verify return value is a list + assert isinstance(updated_files, list) + + # Verify all files in the input are in the returned list + assert len(updated_files) == len(version_files) + for file_path in version_files: + assert file_path in updated_files + + # Verify the returned paths are strings + for file_path in updated_files: + assert isinstance(file_path, str) + + +def test_update_version_in_files_return_value_partial_update(tmp_path): + """Test return value when only some files are updated.""" + # Create two test files + file1 = tmp_path / "file1.txt" + file2 = tmp_path / "file2.txt" + + # File1 contains the version to update + file1.write_text('version = "1.2.3"\n') + + # File2 doesn't contain the version + file2.write_text("some other content\n") + + old_version = "1.2.3" + new_version = "2.0.0" + + updated_files = bump.update_version_in_files( + old_version, + new_version, + [str(file1), str(file2)], + check_consistency=False, + encoding="utf-8", + ) + + # Verify return value + assert isinstance(updated_files, list) + assert len(updated_files) == 2 # Both files should be in the list + assert str(file1) in updated_files + assert str(file2) in updated_files + + # Verify file1 was actually updated + content1 = file1.read_text(encoding="utf-8") + assert f'version = "{new_version}"' in content1 + + # Verify file2 was not changed + content2 = file2.read_text(encoding="utf-8") + assert content2 == "some other content\n" From a31df00f77ed28ba8cb65cde5f93830cbdcf6e98 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sat, 8 Nov 2025 17:08:06 +0800 Subject: [PATCH 078/221] test: simplify assertion --- tests/test_bump_update_version_in_files.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/test_bump_update_version_in_files.py b/tests/test_bump_update_version_in_files.py index 5a74c1c456..a1df2f34b4 100644 --- a/tests/test_bump_update_version_in_files.py +++ b/tests/test_bump_update_version_in_files.py @@ -346,13 +346,10 @@ def test_update_version_in_files_return_value(version_files): assert isinstance(updated_files, list) # Verify all files in the input are in the returned list - assert len(updated_files) == len(version_files) - for file_path in version_files: - assert file_path in updated_files + assert set(version_files) == set(updated_files) # Verify the returned paths are strings - for file_path in updated_files: - assert isinstance(file_path, str) + assert all(isinstance(file_path, str) for file_path in updated_files) def test_update_version_in_files_return_value_partial_update(tmp_path): From 31b1309ae298361eeae13f9324ca572821bc0ea7 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sat, 8 Nov 2025 17:59:37 +0800 Subject: [PATCH 079/221] test: replace tmpdir with tmppath --- tests/test_bump_update_version_in_files.py | 79 ++++++++++++---------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/tests/test_bump_update_version_in_files.py b/tests/test_bump_update_version_in_files.py index a1df2f34b4..9d53a3e81d 100644 --- a/tests/test_bump_update_version_in_files.py +++ b/tests/test_bump_update_version_in_files.py @@ -2,6 +2,7 @@ from shutil import copyfile import pytest +from _pytest.fixtures import FixtureRequest from commitizen import bump from commitizen.exceptions import CurrentVersionNotFoundError @@ -21,40 +22,40 @@ def _copy_sample_file_to_tmpdir( @pytest.fixture(scope="function") -def commitizen_config_file(tmpdir): +def commitizen_config_file(tmp_path: Path) -> Path: return _copy_sample_file_to_tmpdir( - tmpdir, "sample_pyproject.toml", "pyproject.toml" + tmp_path, "sample_pyproject.toml", "pyproject.toml" ) @pytest.fixture(scope="function") -def python_version_file(tmpdir, request): - return _copy_sample_file_to_tmpdir(tmpdir, "sample_version.py", "__version__.py") +def python_version_file(tmp_path: Path, request: FixtureRequest) -> Path: + return _copy_sample_file_to_tmpdir(tmp_path, "sample_version.py", "__version__.py") @pytest.fixture(scope="function") -def inconsistent_python_version_file(tmpdir): +def inconsistent_python_version_file(tmp_path: Path) -> Path: return _copy_sample_file_to_tmpdir( - tmpdir, "inconsistent_version.py", "__version__.py" + tmp_path, "inconsistent_version.py", "__version__.py" ) @pytest.fixture(scope="function") -def random_location_version_file(tmpdir): - return _copy_sample_file_to_tmpdir(tmpdir, "sample_cargo.lock", "Cargo.lock") +def random_location_version_file(tmp_path: Path) -> Path: + return _copy_sample_file_to_tmpdir(tmp_path, "sample_cargo.lock", "Cargo.lock") @pytest.fixture(scope="function") -def version_repeated_file(tmpdir): +def version_repeated_file(tmp_path: Path) -> Path: return _copy_sample_file_to_tmpdir( - tmpdir, "repeated_version_number.json", "package.json" + tmp_path, "repeated_version_number.json", "package.json" ) @pytest.fixture(scope="function") -def docker_compose_file(tmpdir): +def docker_compose_file(tmp_path: Path) -> Path: return _copy_sample_file_to_tmpdir( - tmpdir, "sample_docker_compose.yaml", "docker-compose.yaml" + tmp_path, "sample_docker_compose.yaml", "docker-compose.yaml" ) @@ -66,36 +67,38 @@ def docker_compose_file(tmpdir): ), ids=("with_eol", "without_eol"), ) -def multiple_versions_to_update_poetry_lock(tmpdir, request): - return _copy_sample_file_to_tmpdir(tmpdir, request.param, "pyproject.toml") +def multiple_versions_to_update_poetry_lock( + tmp_path: Path, request: FixtureRequest +) -> Path: + return _copy_sample_file_to_tmpdir(tmp_path, request.param, "pyproject.toml") @pytest.fixture(scope="function") -def multiple_versions_increase_string(tmpdir): - tmp_file = tmpdir.join("anyfile") - tmp_file.write(MULTIPLE_VERSIONS_INCREASE_STRING) +def multiple_versions_increase_string(tmp_path: Path) -> str: + tmp_file = tmp_path / "anyfile" + tmp_file.write_text(MULTIPLE_VERSIONS_INCREASE_STRING) return str(tmp_file) @pytest.fixture(scope="function") -def multiple_versions_reduce_string(tmpdir): - tmp_file = tmpdir.join("anyfile") - tmp_file.write(MULTIPLE_VERSIONS_REDUCE_STRING) +def multiple_versions_reduce_string(tmp_path: Path) -> str: + tmp_file = tmp_path / "anyfile" + tmp_file.write_text(MULTIPLE_VERSIONS_REDUCE_STRING) return str(tmp_file) @pytest.fixture(scope="function") def version_files( - commitizen_config_file, - python_version_file, - version_repeated_file, - docker_compose_file, -): + commitizen_config_file: Path, + python_version_file: Path, + version_repeated_file: Path, + docker_compose_file: Path, +) -> tuple[str, ...]: return ( - commitizen_config_file, - python_version_file, - version_repeated_file, - docker_compose_file, + str(commitizen_config_file), + str(python_version_file), + str(version_repeated_file), + str(docker_compose_file), ) @@ -228,12 +231,14 @@ def test_multiple_versions_to_bump( def test_update_version_in_globbed_files(commitizen_config_file, file_regression): old_version = "1.2.3" new_version = "2.0.0" - other = commitizen_config_file.dirpath("other.toml") - print(commitizen_config_file, other) + other = commitizen_config_file.parent / "other.toml" + copyfile(commitizen_config_file, other) # Prepend full path as test assume absolute paths or cwd-relative - version_files = [commitizen_config_file.dirpath("*.toml")] + version_files = [ + str(file_path) for file_path in commitizen_config_file.parent.glob("*.toml") + ] bump.update_version_in_files( old_version, @@ -247,13 +252,15 @@ def test_update_version_in_globbed_files(commitizen_config_file, file_regression file_regression.check(file.read_text("utf-8"), extension=".toml") -def test_update_version_in_files_with_check_consistency_true(version_files): +def test_update_version_in_files_with_check_consistency_true( + version_files: tuple[str, ...], +): """Test update_version_in_files with check_consistency=True (success case).""" old_version = "1.2.3" new_version = "2.0.0" # This should succeed because all files contain the current version - updated_files = bump.update_version_in_files( + updated_files: list[str] = bump.update_version_in_files( old_version, new_version, version_files, @@ -262,9 +269,7 @@ def test_update_version_in_files_with_check_consistency_true(version_files): ) # Verify that all files were updated - assert len(updated_files) == len(version_files) - for file_path in updated_files: - assert file_path in version_files + assert set(updated_files) == set(version_files) def test_update_version_in_files_with_check_consistency_true_failure( From e6bcb1a81acd9d424c60c8002949409514a197f3 Mon Sep 17 00:00:00 2001 From: catfish Date: Mon, 11 Aug 2025 23:54:31 +0800 Subject: [PATCH 080/221] feat: add config option for line length warning --- commitizen/cli.py | 2 - commitizen/commands/check.py | 21 +++++++--- commitizen/commands/commit.py | 7 +++- commitizen/defaults.py | 2 + poetry.lock | 2 +- pyproject.toml | 2 +- tests/commands/test_check_command.py | 59 ++++++++++++++++++++++++++- tests/commands/test_commit_command.py | 59 +++++++++++++++++++++++++++ tests/test_conf.py | 2 + 9 files changed, 143 insertions(+), 13 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index e9689d75f3..c11e9078dc 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -160,7 +160,6 @@ def __call__( { "name": ["-l", "--message-length-limit"], "type": int, - "default": 0, "help": "length limit of the commit message; 0 for no limit", }, { @@ -499,7 +498,6 @@ def __call__( { "name": ["-l", "--message-length-limit"], "type": int, - "default": 0, "help": "length limit of the commit message; 0 for no limit", }, ], diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index d45e388f9d..a6101f7df7 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -7,6 +7,7 @@ from commitizen import factory, git, out from commitizen.config import BaseConfig from commitizen.exceptions import ( + CommitMessageLengthExceededError, InvalidCommandArgumentError, InvalidCommitMessageError, NoCommitsFoundError, @@ -18,7 +19,7 @@ class CheckArgs(TypedDict, total=False): commit_msg: str rev_range: str allow_abort: bool - message_length_limit: int + message_length_limit: int | None allowed_prefixes: list[str] message: str use_default_range: bool @@ -41,8 +42,11 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N self.allow_abort = bool( arguments.get("allow_abort", config.settings["allow_abort"]) ) + self.use_default_range = bool(arguments.get("use_default_range")) - self.max_msg_length = arguments.get("message_length_limit", 0) + self.max_msg_length = arguments.get( + "message_length_limit", config.settings.get("message_length_limit", None) + ) # we need to distinguish between None and [], which is a valid value allowed_prefixes = arguments.get("allowed_prefixes") @@ -88,7 +92,7 @@ def __call__(self) -> None: invalid_msgs_content = "\n".join( f'commit "{commit.rev}": "{commit.message}"' for commit in commits - if not self._validate_commit_message(commit.message, pattern) + if not self._validate_commit_message(commit.message, pattern, commit.rev) ) if invalid_msgs_content: # TODO: capitalize the first letter of the error message for consistency in v5 @@ -153,7 +157,7 @@ def _filter_comments(msg: str) -> str: return "\n".join(lines) def _validate_commit_message( - self, commit_msg: str, pattern: re.Pattern[str] + self, commit_msg: str, pattern: re.Pattern[str], commit_hash: str ) -> bool: if not commit_msg: return self.allow_abort @@ -161,9 +165,14 @@ def _validate_commit_message( if any(map(commit_msg.startswith, self.allowed_prefixes)): return True - if self.max_msg_length: + if self.max_msg_length is not None: msg_len = len(commit_msg.partition("\n")[0].strip()) if msg_len > self.max_msg_length: - return False + raise CommitMessageLengthExceededError( + f"commit validation: failed!\n" + f"commit message length exceeds the limit.\n" + f'commit "{commit_hash}": "{commit_msg}"\n' + f"message length limit: {self.max_msg_length} (actual: {msg_len})" + ) return bool(pattern.match(commit_msg)) diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index d16b4d8d88..7144bced87 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -33,7 +33,7 @@ class CommitArgs(TypedDict, total=False): dry_run: bool edit: bool extra_cli_args: str - message_length_limit: int + message_length_limit: int | None no_retry: bool signoff: bool write_message_to_file: Path | None @@ -80,8 +80,11 @@ def _get_message_by_prompt_commit_questions(self) -> str: raise NoAnswersError() message = self.cz.message(answers) - if limit := self.arguments.get("message_length_limit", 0): + if limit := self.arguments.get( + "message_length_limit", self.config.settings.get("message_length_limit", 0) + ): self._validate_subject_length(message=message, length_limit=limit) + return message def _validate_subject_length(self, *, message: str, length_limit: int) -> None: diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 68e580f52b..9b3b76a686 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -46,6 +46,7 @@ class Settings(TypedDict, total=False): ignored_tag_formats: Sequence[str] legacy_tag_formats: Sequence[str] major_version_zero: bool + message_length_limit: int | None name: str post_bump_hooks: list[str] | None pre_bump_hooks: list[str] | None @@ -111,6 +112,7 @@ class Settings(TypedDict, total=False): "template": None, # default provided by plugin "extras": {}, "breaking_change_exclamation_in_title": False, + "message_length_limit": None, # None for no limit } MAJOR = "MAJOR" diff --git a/poetry.lock b/poetry.lock index 1a731e4f06..49df9dcd52 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1955,4 +1955,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "bdc8773ed978a4265a2a099265db7e116d2f65c467c4980d984e546716cea244" +content-hash = "cd5648d8aad7b58913b1c0e4cd4f04c98d5bcfa7e4ef8e7bb994a59492d7d4a2" diff --git a/pyproject.toml b/pyproject.toml index f16ad596bb..4ff252ebf5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "colorama (>=0.4.1,<1.0)", "termcolor (>=1.1.0,<4.0.0)", "packaging>=19", - "tomlkit (>=0.5.3,<1.0.0)", + "tomlkit (>=0.8.0,<1.0.0)", "jinja2>=2.10.3", "pyyaml>=3.08", "argcomplete >=1.12.1,<3.7", diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index 365a556dda..d2a82a903a 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -8,6 +8,7 @@ from commitizen import cli, commands, git from commitizen.exceptions import ( + CommitMessageLengthExceededError, InvalidCommandArgumentError, InvalidCommitMessageError, NoCommitsFoundError, @@ -449,7 +450,7 @@ def test_check_command_with_message_length_limit_exceeded(config, mocker: MockFi arguments={"message": message, "message_length_limit": len(message) - 1}, ) - with pytest.raises(InvalidCommitMessageError): + with pytest.raises(CommitMessageLengthExceededError): check_cmd() error_mock.assert_called_once() @@ -460,3 +461,59 @@ def test_check_command_with_amend_prefix_default(config, mocker: MockFixture): check_cmd() success_mock.assert_called_once() + + +def test_check_command_with_config_message_length_limit(config, mocker: MockFixture): + success_mock = mocker.patch("commitizen.out.success") + message = "fix(scope): some commit message" + + config.settings["message_length_limit"] = len(message) + 1 + + check_cmd = commands.Check( + config=config, + arguments={"message": message}, + ) + + check_cmd() + success_mock.assert_called_once() + + +def test_check_command_with_config_message_length_limit_exceeded( + config, mocker: MockFixture +): + error_mock = mocker.patch("commitizen.out.error") + message = "fix(scope): some commit message" + + config.settings["message_length_limit"] = len(message) - 1 + + check_cmd = commands.Check( + config=config, + arguments={"message": message}, + ) + + with pytest.raises(CommitMessageLengthExceededError): + check_cmd() + error_mock.assert_called_once() + + +def test_check_command_cli_overrides_config_message_length_limit( + config, mocker: MockFixture +): + success_mock = mocker.patch("commitizen.out.success") + message = "fix(scope): some commit message" + + config.settings["message_length_limit"] = len(message) - 1 + + check_cmd = commands.Check( + config=config, + arguments={"message": message, "message_length_limit": len(message) + 1}, + ) + + check_cmd() + success_mock.assert_called_once() + + success_mock.reset_mock() + check_cmd = commands.Check( + config=config, + arguments={"message": message, "message_length_limit": None}, + ) diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index 8d0181f3e0..3e408576fe 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -554,3 +554,62 @@ def test_commit_when_nothing_added_to_commit(config, mocker: MockFixture, out): commit_mock.assert_called_once() error_mock.assert_called_once_with(out) + + +@pytest.mark.usefixtures("staging_is_clean") +def test_commit_command_with_config_message_length_limit(config, mocker: MockFixture): + prompt_mock = mocker.patch("questionary.prompt") + prefix = "feat" + subject = "random subject" + message_length = len(prefix) + len(": ") + len(subject) + prompt_mock.return_value = { + "prefix": prefix, + "subject": subject, + "scope": "", + "is_breaking_change": False, + "body": "random body", + "footer": "random footer", + } + + commit_mock = mocker.patch("commitizen.git.commit") + commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) + success_mock = mocker.patch("commitizen.out.success") + + config.settings["message_length_limit"] = message_length + commands.Commit(config, {})() + success_mock.assert_called_once() + + config.settings["message_length_limit"] = message_length - 1 + with pytest.raises(CommitMessageLengthExceededError): + commands.Commit(config, {})() + + +@pytest.mark.usefixtures("staging_is_clean") +def test_commit_command_cli_overrides_config_message_length_limit( + config, mocker: MockFixture +): + prompt_mock = mocker.patch("questionary.prompt") + prefix = "feat" + subject = "random subject" + message_length = len(prefix) + len(": ") + len(subject) + prompt_mock.return_value = { + "prefix": prefix, + "subject": subject, + "scope": "", + "is_breaking_change": False, + "body": "random body", + "footer": "random footer", + } + + commit_mock = mocker.patch("commitizen.git.commit") + commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) + success_mock = mocker.patch("commitizen.out.success") + + config.settings["message_length_limit"] = message_length - 1 + + commands.Commit(config, {"message_length_limit": message_length})() + success_mock.assert_called_once() + + success_mock.reset_mock() + commands.Commit(config, {"message_length_limit": None})() + success_mock.assert_called_once() diff --git a/tests/test_conf.py b/tests/test_conf.py index 47633c7e01..bbbed41e08 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -106,6 +106,7 @@ "template": None, "extras": {}, "breaking_change_exclamation_in_title": False, + "message_length_limit": None, } _new_settings: dict[str, Any] = { @@ -145,6 +146,7 @@ "template": None, "extras": {}, "breaking_change_exclamation_in_title": False, + "message_length_limit": None, } From f31db0d8764842c19684fd9a813110798b91741e Mon Sep 17 00:00:00 2001 From: catfish Date: Tue, 12 Aug 2025 13:06:27 +0800 Subject: [PATCH 081/221] docs(config): add message length limit configuration option --- docs/config.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/config.md b/docs/config.md index c00a6f72a8..94aa2076b4 100644 --- a/docs/config.md +++ b/docs/config.md @@ -119,6 +119,14 @@ Automatically retry failed commit when running `cz commit`. [Read more][retry_af Disallow empty commit messages. Useful in CI. [Read more][allow_abort] +### `message_length_limit` + +Type: `int` + +Default: `0` + +Maximum length of the commit message. Setting it to `0` disables the length limit. It can be overridden by the `-l/--message-length-limit` command line argument. + ### `allowed_prefixes` - Type: `list` From a85ab5e72426272872dc58590aeffb2bd38b01cd Mon Sep 17 00:00:00 2001 From: Adrian DC Date: Tue, 13 Aug 2024 17:35:37 +0200 Subject: [PATCH 082/221] style: unify YAML quotes style Signed-off-by: Adrian DC --- docs/customization.md | 14 +++++++------- tests/test_cz_customize.py | 16 +++++++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/docs/customization.md b/docs/customization.md index df77171077..99ffd39ba7 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -110,13 +110,13 @@ And the correspondent example for a yaml file: commitizen: name: cz_customize customize: - message_template: "{{change_type}}:{% if show_message %} {{message}}{% endif %}" + message_template: '{{change_type}}:{% if show_message %} {{message}}{% endif %}' example: 'feature: this feature enable customize through config file' - schema: ": " - schema_pattern: "(feature|bug fix):(\\s.*)" - bump_pattern: "^(break|new|fix|hotfix)" - commit_parser: "^(?Pfeature|bug fix):\\s(?P.*)?" - changelog_pattern: "^(feature|bug fix)?(!)?" + schema: ': ' + schema_pattern: '(feature|bug fix):(\\s.*)' + bump_pattern: '^(break|new|fix|hotfix)' + commit_parser: '^(?Pfeature|bug fix):\\s(?P.*)?' + changelog_pattern: '^(feature|bug fix)?(!)?' change_type_map: feature: Feat bug fix: Fix @@ -125,7 +125,7 @@ commitizen: new: MINOR fix: PATCH hotfix: PATCH - change_type_order: ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"] + change_type_order: ['BREAKING CHANGE', 'feat', 'fix', 'refactor', 'perf'] info_path: cz_customize_info.txt info: This is customized info questions: diff --git a/tests/test_cz_customize.py b/tests/test_cz_customize.py index 76341828d4..dd354d65ea 100644 --- a/tests/test_cz_customize.py +++ b/tests/test_cz_customize.py @@ -110,17 +110,22 @@ - commitizen/__version__.py - pyproject.toml customize: - message_template: "{{change_type}}:{% if show_message %} {{message}}{% endif %}" + message_template: '{{change_type}}:{% if show_message %} {{message}}{% endif %}' example: 'feature: this feature enables customization through a config file' - schema: ": " - schema_pattern: "(feature|bug fix):(\\s.*)" - bump_pattern: "^(break|new|fix|hotfix)" + schema: ': ' + schema_pattern: '(feature|bug fix):(\\s.*)' + bump_pattern: '^(break|new|fix|hotfix)' + commit_parser: '^(?Pfeature|bug fix):\\s(?P.*)?' + changelog_pattern: '^(feature|bug fix)?(!)?' + change_type_map: + feature: Feat + bug fix: Fix bump_map: break: MAJOR new: MINOR fix: PATCH hotfix: PATCH - change_type_order: ["perf", "BREAKING CHANGE", "feat", "fix", "refactor"] + change_type_order: ['perf', 'BREAKING CHANGE', 'feat', 'fix', 'refactor'] info: This is a customized cz. questions: - type: list @@ -326,6 +331,7 @@ params=[ TomlConfig(data=TOML_STR, path=Path("not_exist.toml")), JsonConfig(data=JSON_STR, path=Path("not_exist.json")), + YAMLConfig(data=YAML_STR, path=Path("not_exist.yaml")), ] ) def config(request): From 7018c78d03b0fe2691f01464a4a533fea60b5c56 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sun, 9 Nov 2025 09:59:15 +0800 Subject: [PATCH 083/221] fix(commands/version): add missing return --- commitizen/commands/version.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 04fa664f25..7ccadb5135 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -48,6 +48,8 @@ def __call__(self) -> None: version_scheme = get_version_scheme(self.config.settings) except VersionSchemeUnknown: out.error("Unknown version scheme.") + return + _version = version_scheme(version) if self.parameter.get("major"): From 9f3ec868c0429155a46b4819b625d47a8522a3d5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 10 Nov 2025 14:08:24 +0000 Subject: [PATCH 084/221] =?UTF-8?q?bump:=20version=204.9.1=20=E2=86=92=204?= =?UTF-8?q?.10.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4af318e4eb..bf207ea60b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.9.1 # automatically updated by Commitizen + rev: v4.10.0 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index a72dc0fda0..f8bca478b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +## v4.10.0 (2025-11-10) + +### Feat + +- add config option for line length warning +- **conventional_commits**: allow exclamation in title on BC +- **version**: add the ability to just print major or minor version +- allow `amend!` prefix as created by `git --fixup=reword:` + +### Fix + +- **commands/version**: add missing return +- **test**: set terminal width for cli tests +- **Init**: raise InitFailedError on keyboard interrupt on pre-commit hook question, simplify logic, remove unreachable code path + +### Refactor + +- **bump**: cleanup related to update_version_file +- **RestructuredTest**: rename variable, fix typo and remove unnecessary string copy +- **TomlConfig**: minor cleanups for DX +- **Commit**: refactor _prompt_commit_questions and fix some type hint +- **hooks**: refactor to improve readability +- **Init**: make project_info a module and remove self.project_info +- **BaseConfig**: update docstring, extract factory method and remove unnecessary variable assignment +- remove self.encoding for better maintainability +- **utils**: make get_backup_file_path to return a path for semantic correctness +- remove unnecessary class member tag_format +- **Bump**: remove use of getattr +- **ConventionalCommitsCz**: rewrite message method to make the pattern more clear +- **cmd**: unnest try except +- **BaseCommitizen**: remove NotImplementedError and make them abstract method +- **BaseCommitizen**: construct Style object directly to get rid of potential type error + ## v4.9.1 (2025-09-10) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 0139b2ebd5..897e6be2ff 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.9.1" +__version__ = "4.10.0" diff --git a/pyproject.toml b/pyproject.toml index 4ff252ebf5..8211b969d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.9.1" +version = "4.10.0" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -90,7 +90,7 @@ build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "4.9.1" +version = "4.10.0" tag_format = "v$version" version_files = [ "pyproject.toml:version", From f4e8fcb863b21a3796218dc7fd210cacb85a3bf4 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 12 Sep 2025 18:13:26 +0800 Subject: [PATCH 085/221] test(changelog): cover incremental_build --- tests/test_incremental_build.py | 606 ++++++++++++++++++++++++++++++++ 1 file changed, 606 insertions(+) create mode 100644 tests/test_incremental_build.py diff --git a/tests/test_incremental_build.py b/tests/test_incremental_build.py new file mode 100644 index 0000000000..13f123a651 --- /dev/null +++ b/tests/test_incremental_build.py @@ -0,0 +1,606 @@ +"""Tests for the incremental_build function in commitizen.changelog module.""" + +from commitizen.changelog import Metadata, incremental_build + + +class TestIncrementalBuild: + """Test cases for the incremental_build function.""" + + def test_basic_replacement_of_unreleased_section(self): + """Test basic functionality of replacing unreleased section with new content.""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=6, + latest_version="1.0.0", + latest_version_position=7, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- Another new feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + assert result == expected + + def test_replacement_when_latest_version_position_is_none(self): + """Test replacement when latest_version_position is None (append to end).""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=5, + latest_version=None, + latest_version_position=None, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- Another new feature", + ] + + assert result == expected + + def test_replacement_when_latest_version_position_after_unreleased_end(self): + """Test replacement when latest_version_position is after unreleased_end.""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=5, + latest_version="1.0.0", + latest_version_position=7, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "", + "## Unreleased\n\n### Added\n- Another new feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + assert result == expected + + def test_replacement_when_latest_version_position_before_unreleased_end(self): + """Test replacement when latest_version_position is before unreleased_end.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + ] + + metadata = Metadata( + unreleased_start=7, + unreleased_end=10, + latest_version="1.0.0", + latest_version_position=2, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- Another new feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "", + "- New feature", + ] + + assert result == expected + + def test_no_unreleased_section_append_to_end(self): + """Test appending new content when no unreleased section exists.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + metadata = Metadata( + unreleased_start=None, + unreleased_end=None, + latest_version=None, + latest_version_position=None, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "\n", + "## Unreleased\n\n### Added\n- New feature", + ] + + assert result == expected + + def test_no_unreleased_section_with_latest_version_position(self): + """Test inserting new content at latest_version_position when no unreleased section.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + metadata = Metadata( + unreleased_start=None, + unreleased_end=None, + latest_version="1.0.0", + latest_version_position=2, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- New feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + assert result == expected + + def test_empty_lines_list(self): + """Test behavior with empty lines list.""" + lines = [] + + metadata = Metadata( + unreleased_start=None, + unreleased_end=None, + latest_version=None, + latest_version_position=None, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "## Unreleased\n\n### Added\n- New feature", + ] + + assert result == expected + + def test_single_line_unreleased_section(self): + """Test replacement of single line unreleased section.""" + lines = [ + "# Changelog", + "## Unreleased", + "## 1.0.0 (2023-01-01)", + ] + + metadata = Metadata( + unreleased_start=1, + unreleased_end=1, + latest_version="1.0.0", + latest_version_position=2, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + ] + + assert result == expected + + def test_unreleased_section_at_end_of_file(self): + """Test replacement when unreleased section is at the end of file.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + ] + + metadata = Metadata( + unreleased_start=7, + unreleased_end=10, + latest_version="1.0.0", + latest_version_position=2, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- Another new feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "", + "- New feature", + ] + + assert result == expected + + def test_blank_line_handling_when_appending(self): + """Test that blank line is added when appending to non-empty content.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + ] + + metadata = Metadata( + unreleased_start=None, + unreleased_end=None, + latest_version=None, + latest_version_position=None, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "\n", + "## Unreleased\n\n### Added\n- New feature", + ] + + assert result == expected + + def test_no_blank_line_when_content_ends_with_blank_line(self): + """Test that no extra blank line is added when content already ends with blank line.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + ] + + metadata = Metadata( + unreleased_start=None, + unreleased_end=None, + latest_version=None, + latest_version_position=None, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "## Unreleased\n\n### Added\n- New feature", + ] + + assert result == expected + + def test_empty_new_content(self): + """Test behavior with empty new content.""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + "", + "## 1.0.0 (2023-01-01)", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=5, + latest_version="1.0.0", + latest_version_position=7, + ) + + new_content = "" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "", + "", + "\n", + "## 1.0.0 (2023-01-01)", + ] + + assert result == expected + + def test_multiline_new_content(self): + """Test behavior with multiline new content.""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + "", + "## 1.0.0 (2023-01-01)", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=5, + latest_version="1.0.0", + latest_version_position=7, + ) + + new_content = "## Unreleased\n\n### Added\n- Feature 1\n- Feature 2\n\n### Fixed\n- Bug fix" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "", + "## Unreleased\n\n### Added\n- Feature 1\n- Feature 2\n\n### Fixed\n- Bug fix", + "\n", + "## 1.0.0 (2023-01-01)", + ] + + assert result == expected + + def test_metadata_with_none_values(self): + """Test behavior when metadata has None values for unreleased positions.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + metadata = Metadata( + unreleased_start=None, + unreleased_end=None, + latest_version="1.0.0", + latest_version_position=2, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- New feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + assert result == expected + + def test_skip_behavior_during_unreleased_section(self): + """Test that lines are properly skipped during unreleased section processing.""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- Old feature 1", + "- Old feature 2", + "", + "### Fixed", + "- Old bug fix", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=9, + latest_version="1.0.0", + latest_version_position=11, + ) + + new_content = "## Unreleased\n\n### Added\n- New feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "", + "## Unreleased\n\n### Added\n- New feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + ] + + assert result == expected + + def test_latest_version_position_at_unreleased_end(self): + """Test behavior when latest_version_position equals unreleased_end.""" + lines = [ + "# Changelog", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + "", + "## 1.0.0 (2023-01-01)", + ] + + metadata = Metadata( + unreleased_start=2, + unreleased_end=5, + latest_version="1.0.0", + latest_version_position=5, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- Another new feature", + "\n", + "- New feature", + "", + "## 1.0.0 (2023-01-01)", + ] + + assert result == expected + + def test_latest_version_position_before_unreleased_start(self): + """Test behavior when latest_version_position is before unreleased_start.""" + lines = [ + "# Changelog", + "", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "", + "## Unreleased", + "", + "### Added", + "- New feature", + ] + + metadata = Metadata( + unreleased_start=7, + unreleased_end=9, + latest_version="1.0.0", + latest_version_position=2, + ) + + new_content = "## Unreleased\n\n### Added\n- Another new feature" + + result = incremental_build(new_content, lines, metadata) + + expected = [ + "# Changelog", + "", + "## Unreleased\n\n### Added\n- Another new feature", + "\n", + "## 1.0.0 (2023-01-01)", + "", + "### Fixed", + "- Bug fix", + "", + "### Added", + "- New feature", + ] + + assert result == expected From 90e5ee7139174def05a3ccdf2dc6fb93a3ba4c41 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 17 Nov 2025 22:42:56 +0800 Subject: [PATCH 086/221] docs(Bump): wording consistency --- docs/commands/bump.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index 47e64dfc6e..510fb4619c 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -9,7 +9,7 @@ - **Automatic Version Detection**: Analyzes commit history to determine the appropriate version bump - **Manual Version Control**: Supports manual version specification when needed - **Pre-release Support**: Handles alpha, beta, and release candidate versions -- **Multiple Version Schemes**: Supports both [PEP 0440][pep440] and [semantic versioning][semver] formats +- **Multiple Version Schemes**: Supports both [PEP 440][pep440] and [semantic versioning][semver] formats ### Version Increment Rules @@ -23,7 +23,7 @@ The version follows the `MAJOR.MINOR.PATCH` format, with increments determined b ### Version Schemes -By default, Commitizen uses [PEP 0440][pep440] for version formatting. You can switch to semantic versioning using either: +By default, Commitizen uses [PEP 440][pep440] for version formatting. You can switch to semantic versioning using either: 1. Command line: ```sh From f32bec0e86def0d6beb60dd0bb04b2a3ecb5f662 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Mon, 17 Nov 2025 23:27:50 +0800 Subject: [PATCH 087/221] docs(bump): add example to version file --- docs/commands/bump.md | 47 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index 510fb4619c..cee6c6db26 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -470,36 +470,65 @@ Supported variables: --- -### `version_files` \* +### `version_files` It is used to identify the files or glob patterns which should be updated with the new version. -It is also possible to provide a pattern for each file, separated by colons (`:`). Commitizen will update its configuration file automatically (`pyproject.toml`, `.cz`) when bumping, regarding if the file is present or not in `version_files`. -\* Renamed from `files` to `version_files`. +You may specify the `version_files` in your `pyproject.toml`, `.cz.toml` or `cz.toml` configuration file. -Some examples +It is also possible to provide a pattern for each file, separated by a colon (e.g. `file:pattern`). See the below example for more details. -`pyproject.toml`, `.cz.toml` or `cz.toml` +#### Example Configuration ```toml title="pyproject.toml" [tool.commitizen] version_files = [ "src/__version__.py", "packages/*/pyproject.toml:version", - "setup.py:version", + "setup.json:version", ] ``` -In the example above, we can see the reference `"setup.py:version"`. -This means that it will find a file `setup.py` and will only make a change -in a line containing the `version` substring. +In the example configuration above, we can see the reference `"setup.json:version"`. + +This means that it will find a file `setup.json` and will only change the lines that contain the substring `"version"`. + +For example, if we have a file `setup.json` with the following content: + + + +```json title="setup.json" +{ + "name": "magictool", + "version": "1.2.3", + "dependencies": { + "lodash": "1.2.3" + } +} +``` + +After running `cz bump 2.0.0`, the file will be updated to: + +```diff title="setup.json" +{ + "name": "magictool", +- "version": "1.2.3", ++ "version": "2.0.0", + "dependencies": { + "lodash": "1.2.3" + } +} +``` !!! note Files can be specified using relative (to the execution) paths, absolute paths, or glob patterns. +!!! note + (Historical note) This option was renamed from `files` to `version_files`. + --- ### `bump_message` From cbbf6150ea32c7758a0aa97f965e19c8cb754268 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 19 Nov 2025 01:02:32 +0800 Subject: [PATCH 088/221] docs(bump): general documentation update --- docs/commands/bump.md | 477 +++++++++++++++++++++++------------------- docs/config.md | 2 +- 2 files changed, 268 insertions(+), 211 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index cee6c6db26..eb807f841c 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -2,9 +2,18 @@ ## About -`cz bump` is a powerful command that **automatically** determines and increases your project's version number based on your commit history. It analyzes your commits to determine the appropriate version increment according to semantic versioning principles. +`cz bump` is a powerful command that **automatically** determines and increases your project's version number based on your commit history. -### Key Features +It analyzes your commits to determine the appropriate version increment according to semantic versioning principles. + +!!! note + In the following documentation, the term "configuration file" refers to `pyproject.toml`, `.cz.toml` or other configuration files. + + We will use `pyproject.toml` as the configuration file throughout the documentation. + + See [Configuration file](../config.md#configuration-file) for more details. + +## Key Features - **Automatic Version Detection**: Analyzes commit history to determine the appropriate version bump - **Manual Version Control**: Supports manual version specification when needed @@ -21,7 +30,7 @@ The version follows the `MAJOR.MINOR.PATCH` format, with increments determined b | `MINOR` | New features | `feat` | | `PATCH` | Fixes and improvements | `fix`, `perf`, `refactor`| -### Version Schemes +### Version Schemes (`--version-scheme`) By default, Commitizen uses [PEP 440][pep440] for version formatting. You can switch to semantic versioning using either: @@ -36,6 +45,26 @@ cz bump --version-scheme semver version_scheme = "semver" ``` +Available options are: + +- `pep440`: [PEP 440][pep440] (**default** and recommended for Python projects) +- `semver`: [Semantic Versioning][semver] (recommended for non-Python projects) + +You can also set this in the [configuration](#version_scheme) with `version_scheme = "semver"`. + +!!! note + [pep440][pep440] and [semver][semver] are quite similar, although their difference lies in + how the prereleases look. For example, `0.3.1a0` in pep440 is equivalent to `0.3.1-a0` in semver. + + The following table illustrates the difference between the two schemes: + + | Version Type | pep440 | semver | + |--------------|----------------|-----------------| + | Non-prerelease | `0.1.0` | `0.1.0` | + | Prerelease | `0.3.1a0` | `0.3.1-a0` | + | Devrelease | `0.1.1.dev1` | `0.1.1-dev1` | + | Dev and pre | `1.0.0a3.dev1` | `1.0.0-a3-dev1` | + ### PEP440 Version Examples Commitizen supports the [PEP 440][pep440] version format, which includes several version types. Here are examples of each: @@ -76,13 +105,13 @@ Commitizen supports the [PEP 440][pep440] version format, which includes several > **Note**: `post` releases (e.g., `1.0.0.post1`) are not currently supported. -## Usage +## Command line options ![cz bump --help](../images/cli_help/cz_bump___help.svg) ### `--files-only` -Bumps the version in the files defined in `version_files` without creating a commit and tag on the git repository, +Bumps the version in the files defined in [`version_files`](#version_files) without creating a commit and tag on the git repository, ```bash cz bump --files-only @@ -90,7 +119,7 @@ cz bump --files-only ### `--changelog` -Generate a **changelog** along with the new version and tag when bumping. +Generate a **changelog** along with the new version and tag when bumping. See [changelog](./changelog.md) for more details. ```bash cz bump --changelog @@ -122,16 +151,21 @@ by their precedence and showcase how a release might flow through a development ### `--increment-mode` -By default, `--increment-mode` is set to `linear`, which ensures that bumping pre-releases _maintains linearity_: -bumping of a pre-release with lower precedence than the current pre-release phase maintains the current phase of -higher precedence. For example, if the current version is `1.0.0b1` then bumping with `--prerelease alpha` will -continue to bump the "beta" phase. +#### `--increment-mode=linear` (default) + +Ensures that bumping pre-releases **maintains linearity**. -Setting `--increment-mode` to `exact` instructs `cz bump` to instead apply the -exact changes that have been specified with `--increment` or determined from the commit log. For example, -`--prerelease beta` will always result in a `b` tag, and `--increment PATCH` will always increase the patch component. +Bumping a pre-release with lower precedence than the current pre-release phase maintains the current phase of higher precedence. +For example, if the current version is `1.0.0b1` then bumping with `--prerelease alpha` will continue to bump the *beta* phase. -Below are some examples that illustrate the difference in behavior: +#### `--increment-mode=exact` + +Applies the exact changes that have been specified with `--increment` or determined from the commit log. +For example, `--prerelease beta` will always result in a `b` tag, and `--increment PATCH` will always increase the patch component. + +#### Examples + +The following table illustrates the difference in behavior between the two modes: | Increment | Pre-release | Start Version | `--increment-mode=linear` | `--increment-mode=exact` | |-----------|-------------|---------------|---------------------------|--------------------------| @@ -144,14 +178,13 @@ Below are some examples that illustrate the difference in behavior: ### `--check-consistency` -Check whether the versions defined in `version_files` and the version in Commitizen -configuration are consistent before bumping version. +Check whether the versions defined in [`version_files`](#version_files) and the version in Commitizen configuration are consistent before bumping version. ```bash cz bump --check-consistency ``` -For example, if we have `pyproject.toml` +For example, if we have the following configuration file `pyproject.toml`: ```toml title="pyproject.toml" [tool.commitizen] @@ -162,67 +195,94 @@ version_files = [ ] ``` -`src/__version__.py` - +and the following version files `src/__version__.py` and `setup.py`: ```python title="src/__version__.py" __version__ = "1.21.0" ``` -and `setup.py` - ```python title="setup.py" from setuptools import setup setup(..., version="1.0.5", ...) ``` -If `--check-consistency` is used, Commitizen will check whether the current version in `pyproject.toml` -exists in all version_files and find out it does not exist in `setup.py` and fails. -However, it will still update `pyproject.toml` and `src/__version__.py`. +When you run `cz bump --check-consistency`, Commitizen will verify that the current version in `pyproject.toml` (`1.21.0`) exists in all files listed in [`version_files`](#version_files). +In this example, it will detect that `setup.py` contains `1.0.5` instead of `1.21.0`, causing the bump to fail. + +!!! warning "Partial updates on failure" + If the consistency check fails, Commitizen may have already updated some files (like `pyproject.toml` and `src/__version__.py`) before detecting the inconsistency. + In this case, you'll need to restore the files to their previous state. + + To resolve this issue: -To fix it, you'll first `git checkout .` to reset to the status before trying to bump and update -the version in `setup.py` to `1.21.0` + 1. Restore the modified files to their previous state: + ```bash + git checkout . + ``` + + 2. Manually update the version in `setup.py` to match the version in `pyproject.toml`: + ```python title="setup.py" + from setuptools import setup + + setup(..., version="1.21.0", ...) + ``` + + 3. Run the bump command again: + ```bash + cz bump --check-consistency + ``` ### `--local-version` Bump the local portion of the version. -```bash -cz bump --local-version -``` - -For example, if we have `pyproject.toml` +For example, if we have the following configuration file `pyproject.toml`: ```toml title="pyproject.toml" [tool.commitizen] version = "5.3.5+0.1.0" ``` -If `--local-version` is used, it will bump only the local version `0.1.0` and keep the public version `5.3.5` intact, bumping to the version `5.3.5+0.2.0`. +When you run `cz bump --local-version`, it will bump only the local version `0.1.0` and keep the public version `5.3.5` intact, bumping to the version `5.3.5+0.2.0`. ### `--annotated-tag` -If `--annotated-tag` is used, Commitizen will create annotated tags. It is also available via configuration, in `pyproject.toml` or `.cz.toml`. +Create annotated tags. + +It is also available via configuration files. + +For example, in `pyproject.toml`: + +```toml title="pyproject.toml" +[tool.commitizen] +annotated_tag = true +``` ### `--annotated-tag-message` -If `--annotated-tag-message` is used, Commitizen will create annotated tags with the given message. +Create annotated tags with the given message. + +It is also available via configuration files. + +For example, in `pyproject.toml`: + +```toml title="pyproject.toml" +[tool.commitizen] +annotated_tag_message = "Annotated tag message" +``` ### `--changelog-to-stdout` -If `--changelog-to-stdout` is used, the incremental changelog generated by the bump -will be sent to the stdout, and any other message generated by the bump will be -sent to stderr. +Send the incremental changelog generated by `cz bump` to `stdout`. +Any other messages generated by `cz bump` will be sent to `stderr`. -If `--changelog` is not used with this command, it is still smart enough to -understand that the user wants to create a changelog. It is recommended to be -explicit and use `--changelog` (or the setting `update_changelog_on_bump`). +When this flag is used, `--changelog` is implied. +However, it is recommended to set `--changelog` (or the setting `update_changelog_on_bump`) explicitly when the option `--changelog-to-stdout` is used. -This command is useful to "transport" the newly created changelog. -It can be sent to an auditing system, or to create a GitHub Release. +#### Useful scenarios -Example: +This is useful to pipe the newly created changelog to another tool. For example, it can be sent to an auditing system, or to create a GitHub Release, etc. ```bash cz bump --changelog --changelog-to-stdout > body.md @@ -230,55 +290,64 @@ cz bump --changelog --changelog-to-stdout > body.md ### `--git-output-to-stderr` -If `--git-output-to-stderr` is used, git commands output is redirected to stderr. +If `--git-output-to-stderr` is used, git commands output is redirected to `stderr`. + +Useful when used with `--changelog-to-stdout` and piping the output to a file, -This command is useful when used with `--changelog-to-stdout` and piping the output to a file, -and you don't want the `git commit` output polluting the stdout. +For example, `git commit` output may pollute `stdout`, so it is recommended to use this flag when piping the output to a file. ### `--retry` -If you use tools like [pre-commit](https://pre-commit.com/), add this flag. -It will retry the commit if it fails the 1st time. +If you use tools like [pre-commit](https://pre-commit.com/), you can add this flag. +It will retry the commit if it fails the first time. Useful to combine with code formatters, like [Prettier](https://prettier.io/). ### `--major-version-zero` -A project in its initial development should have a major version zero, and even breaking changes -should not bump that major version from zero. This command ensures that behavior. +Breaking changes does not bump the major version number. -If `--major-version-zero` is used for projects that have a version number greater than zero it fails. -If used together with a manual version the command also fails. +Say you have a project with the version `0.1.x` and you commit a breaking change like this: -We recommend setting `major_version_zero = true` in your configuration file while a project -is in its initial development. Remove that configuration using a breaking-change commit to bump -your project's major version to `v1.0.0` once your project has reached maturity. +```text +fix(magic)!: fully deprecate whatever +``` -### `--version-scheme` +and you run -Choose the version format, options: `pep440`, `semver`. +```bash +cz bump --major-version-zero +``` -Default: `pep440` +Then the version of your project will be bumped to `0.2.0` instead of `1.0.0`. -Recommended for python: `pep440` +!!! note + A project in its initial development should have a major version zero, + and even breaking changes should not bump that major version from zero. This command ensures that behavior. -Recommended for other: `semver` + We recommend setting `major_version_zero = true` in your configuration file while a project + is in its initial development. Remove that configuration using a breaking-change commit to bump + your project's major version to `v1.0.0` once your project has reached maturity. -You can also set this in the [configuration](#version_scheme) with `version_scheme = "semver"`. +!!! warning + This option is only compatible with projects that have major version number zero, `0.x.x` for example. -[pep440][pep440] and [semver][semver] are quite similar, their difference lies in -how the prereleases look. + It fails when used with projects that have a version number greater than zero like `1.x.x`. -| schemes | pep440 | semver | -| -------------- | -------------- | --------------- | -| non-prerelease | `0.1.0` | `0.1.0` | -| prerelease | `0.3.1a0` | `0.3.1-a0` | -| devrelease | `0.1.1.dev1` | `0.1.1-dev1` | -| dev and pre | `1.0.0a3.dev1` | `1.0.0-a3-dev1` | + If used together with a manual version, the command also fails. -Can I transition from one to the other? + ```bash + # This fails + cz bump 0.1.0 --major-version-zero + ``` -Yes, you shouldn't have any issues. +### `--gpg-sign` + +Create gpg signed tags. + +```bash +cz bump --gpg-sign +``` ### `--template` @@ -304,15 +373,23 @@ cz bump --build-metadata yourmetadata ``` Will create a version like `1.1.2+yourmetadata`. + This can be useful for multiple things + - Git hash in version - Labeling the version with additional metadata. -Note that Commitizen ignores everything after `+` when it bumps the version. It is therefore safe to write different build-metadata between versions. +!!! note + Commitizen ignores everything after `+` when it bumps the version. + + It is therefore safe to write different build-metadata between versions. + + +!!! warning + Normally, you should not use this functionality, but if you decide to do so, keep in mind that: -You should normally not use this functionality, but if you decide to do, keep in mind that -- Version `1.2.3+a`, and `1.2.3+b` are the same version! Tools should not use the string after `+` for version calculation. This is probably not a guarantee (example in helm) even tho it is in the spec. -- It might be problematic having the metadata in place when doing upgrades depending on what tool you use. + - Version `1.2.3+a`, and `1.2.3+b` are the same version! Tools should not use the string after `+` for version calculation. This is probably not a guarantee (example in helm) even tho it is in the spec. + - It might be problematic having the metadata in place when doing upgrades depending on what tool you use. ### `--get-next` @@ -323,33 +400,33 @@ and `manual version`. cz bump --get-next ``` -Will output the next version, e.g., `1.2.3`. This can be useful for determining the next version based on CI for non -production environments/builds. +Will only output the next version, e.g., `1.2.3`. This can be useful for determining the next version based on CI for non-production environments/builds. -This behavior differs from the `--dry-run` flag. The `--dry-run` flag provides a more detailed output and can also show -the changes as they would appear in the changelog file. +!!! note "Compare with `--dry-run`" + `--dry-run` provides a more detailed output including the changes as they would appear in the changelog file, while `--get-next` only outputs the next version. -The following output is the result of `cz bump --dry-run`: + The following is the output of `cz bump --dry-run`: -``` -bump: version 3.28.0 → 3.29.0 -tag to create: v3.29.0 -increment detected: MINOR -``` + ```text + bump: version 3.28.0 → 3.29.0 + tag to create: v3.29.0 + increment detected: MINOR + ``` -The following output is the result of `cz bump --get-next`: + The following is the output of `cz bump --get-next`: -``` -3.29.0 -``` + ```text + 3.29.0 + ``` -The `--get-next` flag will raise a `NoneIncrementExit` if the found commits are not eligible for a version bump. +!!! warning + The `--get-next` flag will raise a `NoneIncrementExit` if the found commits are not eligible for a version bump. -For information on how to suppress this exit, see [avoid raising errors](#avoid-raising-errors). + For information on how to suppress this exit, see [avoid raising errors](#avoid-raising-errors). ### `--allow-no-commit` -Allow the project version to be bumped even when there's no eligible version. This is most useful when used with `--increment {MAJOR,MINOR,PATCH}` or `[MANUL_VERSION]` +Allow the project version to be bumped even when there's no eligible version. This is most useful when used with `--increment {MAJOR,MINOR,PATCH}` or `[MANUAL_VERSION]` ```sh # bump a minor version even when there's only bug fixes, documentation changes or even no commits @@ -359,74 +436,15 @@ cz bump --incremental MINOR --allow-no-commit cz bump --allow-no-commit 2.0.0 ``` -## Avoid raising errors - -Some situations from Commitizen raise an exit code different from 0. -If the error code is different from 0, any CI or script running Commitizen might be interrupted. - -If you have a special use case, where you don't want to raise one of this error codes, you can -tell Commitizen to not raise them. - -### Recommended use case - -At the moment, we've identified that the most common error code to skip is - -| Error name | Exit code | -| ----------------- | --------- | -| NoneIncrementExit | 21 | - -There are some situations where you don't want to get an error code when some -commits do not match your rules, you just want those commits to be skipped. - -```sh -cz -nr 21 bump -``` - -### Easy way - -Check which error code was raised by Commitizen by running in the terminal - -```sh -echo $? -``` - -The output should be an integer like this - -```sh -3 -``` - -And then you can tell Commitizen to ignore it: - -```sh -cz --no-raise 3 -``` - -You can tell Commitizen to skip more than one if needed: - -```sh -cz --no-raise 3,4,5 -``` - -### Longer way - -Check the list of [exit_codes](../exit_codes.md) and understand which one you have -to skip and why. +### `--version-scheme` -Remember to document somewhere this, because you'll forget. +See [Version Schemes](#version-schemes-version-scheme). -For example if the system raises a `NoneIncrementExit` error, you look it up -on the list, and then you can use the exit code: - -```sh -cz -nr 21 bump -``` - -## Configuration +## Configuration file options ### `tag_format` -`tag_format` and `version_scheme` are combined to make Git tag names from versions. +`tag_format` and [`version_scheme`](#version-schemes-version-scheme) are combined to make Git tag names from versions. These are used in: @@ -438,7 +456,7 @@ These are used in: - If `tag_format` is set to `$version` (default): `VersionProtocol.parser` (allows `v` prefix) - If `tag_format` is set: Custom regex similar to SemVer (not as lenient as PEP440 e.g. on dev-releases) -Commitizen supports 2 types of formats, a simple and a more complex. +Commitizen supports two types of formats, a simple and a more complex. ```bash cz bump --tag-format="v$version" @@ -448,7 +466,7 @@ cz bump --tag-format="v$version" cz bump --tag-format="v$minor.$major.$patch$prerelease.$devrelease" ``` -In your `pyproject.toml` or `.cz.toml` +In your configuration file: ```toml [tool.commitizen] @@ -461,27 +479,42 @@ Supported variables: | Variable | Description | |--------------------------------|---------------------------------------------| -| `$version`, `${version}` | full generated version | +| `$version`, `${version}` | fully generated version | | `$major`, `${major}` | MAJOR increment | | `$minor`, `${minor}` | MINOR increment | | `$patch`, `${patch}` | PATCH increment | | `$prerelease`, `${prerelease}` | Prerelease (alpha, beta, release candidate) | | `$devrelease`, ${devrelease}` | Development release | ---- - ### `version_files` -It is used to identify the files or glob patterns which should be updated with the new version. +Identify the files or glob patterns which should be updated with the new version. -Commitizen will update its configuration file automatically (`pyproject.toml`, `.cz`) when bumping, +Commitizen will update its configuration file automatically when bumping, regarding if the file is present or not in `version_files`. -You may specify the `version_files` in your `pyproject.toml`, `.cz.toml` or `cz.toml` configuration file. +You may specify the `version_files` in your configuration file. + +```toml title="pyproject.toml" +[tool.commitizen] +version_files = [ + "src/__version__.py", +] +``` It is also possible to provide a pattern for each file, separated by a colon (e.g. `file:pattern`). See the below example for more details. -#### Example Configuration +```toml title="pyproject.toml" +[tool.commitizen] +version_files = [ + "packages/*/pyproject.toml:version", + "setup.json:version", +] +``` + +#### Example scenario + +We have a project with the following configuration file `pyproject.toml`: ```toml title="pyproject.toml" [tool.commitizen] @@ -492,11 +525,9 @@ version_files = [ ] ``` -In the example configuration above, we can see the reference `"setup.json:version"`. +For the reference `"setup.json:version"`, it means that it will look for a file `setup.json` and will only change the lines that contain the substring `"version"`. -This means that it will find a file `setup.json` and will only change the lines that contain the substring `"version"`. - -For example, if we have a file `setup.json` with the following content: +For example, if the content of `setup.json` is: @@ -510,7 +541,7 @@ For example, if we have a file `setup.json` with the following content: } ``` -After running `cz bump 2.0.0`, the file will be updated to: +After running `cz bump 2.0.0`, its content will be updated to: ```diff title="setup.json" { @@ -526,10 +557,8 @@ After running `cz bump 2.0.0`, the file will be updated to: !!! note Files can be specified using relative (to the execution) paths, absolute paths, or glob patterns. -!!! note - (Historical note) This option was renamed from `files` to `version_files`. - ---- +!!! note "Historical note" + This option was renamed from `files` to `version_files`. ### `bump_message` @@ -542,69 +571,52 @@ Defaults to: `bump: version $current_version → $new_version` | `$current_version` | the version existing before bumping | | `$new_version` | version generated after bumping | -Some examples - -`pyproject.toml`, `.cz.toml` or `cz.toml` +#### Example configuration ```toml title="pyproject.toml" [tool.commitizen] bump_message = "release $current_version → $new_version [skip-ci]" ``` ---- - ### `update_changelog_on_bump` -When set to `true` the changelog is always updated incrementally when running `cz bump`, so the user does not have to provide the `--changelog` flag every time. - -Defaults to: `false` +When set to `true`, `cz bump` is equivalent to `cz bump --changelog`. ```toml title="pyproject.toml" [tool.commitizen] update_changelog_on_bump = true ``` ---- - ### `annotated_tag` -When set to `true`, Commitizen will create annotated tags. +When set to `true`, `cz bump` is equivalent to `cz bump --annotated-tag`. ```toml title="pyproject.toml" [tool.commitizen] annotated_tag = true ``` ---- - ### `gpg_sign` -When set to `true`, Commitizen will create gpg signed tags. +When set to `true`, `cz bump` is equivalent to `cz bump --gpg-sign`. See [--gpg-sign](#-gpg-sign). ```toml title="pyproject.toml" [tool.commitizen] gpg_sign = true ``` ---- - ### `major_version_zero` -When set to `true`, Commitizen will keep the major version at zero. -Useful during the initial development stage of your project. - -Defaults to: `false` +When set to `true`, `cz bump` is equivalent to `cz bump --major-version-zero`. See [--major-version-zero](#-major-version-zero). ```toml title="pyproject.toml" [tool.commitizen] major_version_zero = true ``` ---- - ### `pre_bump_hooks` -A list of optional commands that will run right _after_ updating `version_files` +A list of optional commands that will run right _after_ updating [`version_files`](#version_files) and _before_ actual committing and tagging the release. Useful when you need to generate documentation based on the new version. During @@ -628,8 +640,6 @@ pre_bump_hooks = [ ] ``` ---- - ### `post_bump_hooks` A list of optional commands that will run right _after_ committing and tagging the release. @@ -668,22 +678,69 @@ prerelease_offset = 1 ### `version_scheme` -Choose version scheme +See [Version Schemes](#version-schemes-version-scheme). -| schemes | pep440 | semver | semver2 | -| -------------- | -------------- | --------------- | --------------------- | -| non-prerelease | `0.1.0` | `0.1.0` | `0.1.0` | -| prerelease | `0.3.1a0` | `0.3.1-a0` | `0.3.1-alpha.0` | -| devrelease | `0.1.1.dev1` | `0.1.1-dev1` | `0.1.1-dev.1` | -| dev and pre | `1.0.0a3.dev1` | `1.0.0-a3-dev1` | `1.0.0-alpha.3.dev.1` | +## Avoid raising errors -Options: `pep440`, `semver`, `semver2` +Some situations from Commitizen raise an exit code different from 0. +If the error code is different from 0, any CI or script running Commitizen might be interrupted. -Defaults to: `pep440` +If you have a special use case, where you don't want to raise one of this error codes, you can +tell Commitizen to not raise them. -```toml title="pyproject.toml" -[tool.commitizen] -version_scheme = "semver" +### Recommended use case + +At the moment, we've identified that the most common error code to skip is + +| Error name | Exit code | +| ----------------- | --------- | +| NoneIncrementExit | 21 | + +There are some situations where you don't want to get an error code when some +commits do not match your rules, you just want those commits to be skipped. + +```sh +cz -nr 21 bump +``` + +### Easy way + +Check which error code was raised by Commitizen by running in the terminal + +```sh +echo $? +``` + +The output should be an integer like this + +```sh +3 +``` + +And then you can tell Commitizen to ignore it: + +```sh +cz --no-raise 3 +``` + +You can tell Commitizen to skip more than one if needed: + +```sh +cz --no-raise 3,4,5 +``` + +### Longer way + +Check the list of [exit_codes](../exit_codes.md) and understand which one you have +to skip and why. + +Remember to document somewhere this, because you'll forget. + +For example if the system raises a `NoneIncrementExit` error, you look it up +on the list, and then you can use the exit code: + +```sh +cz -nr 21 bump ``` ## Custom bump diff --git a/docs/config.md b/docs/config.md index 94aa2076b4..a3e3179887 100644 --- a/docs/config.md +++ b/docs/config.md @@ -408,7 +408,7 @@ setup( [prerelease-offset]: commands/bump.md#prerelease_offset [retry_after_failure]: commands/commit.md#retry [allow_abort]: commands/check.md#allow-abort -[version-scheme]: commands/bump.md#-version-scheme +[version-scheme]: commands/bump.md#version-schemes-version-scheme [pre_bump_hooks]: commands/bump.md#pre_bump_hooks [post_bump_hooks]: commands/bump.md#post_bump_hooks [allowed_prefixes]: commands/check.md#allowed-prefixes From 6fb02926251ce55e20255f257d0eb0b457ede031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 01:05:04 +0000 Subject: [PATCH 089/221] ci(deps): bump dawidd6/action-homebrew-bump-formula from 5 to 6 Bumps [dawidd6/action-homebrew-bump-formula](https://github.com/dawidd6/action-homebrew-bump-formula) from 5 to 6. - [Release notes](https://github.com/dawidd6/action-homebrew-bump-formula/releases) - [Commits](https://github.com/dawidd6/action-homebrew-bump-formula/compare/v5...v6) --- updated-dependencies: - dependency-name: dawidd6/action-homebrew-bump-formula dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/homebrewpublish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/homebrewpublish.yml b/.github/workflows/homebrewpublish.yml index 8c315b6322..b603acd181 100644 --- a/.github/workflows/homebrewpublish.yml +++ b/.github/workflows/homebrewpublish.yml @@ -24,7 +24,7 @@ jobs: run: | echo "project_version=$(cz version --project)" >> $GITHUB_ENV - name: Update Homebrew formula - uses: dawidd6/action-homebrew-bump-formula@v5 + uses: dawidd6/action-homebrew-bump-formula@v6 with: token: ${{secrets.PERSONAL_ACCESS_TOKEN}} formula: commitizen From d037977a3939e50b95e88dce9d8fc8a34aa6e0fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 01:05:10 +0000 Subject: [PATCH 090/221] ci(deps): bump actions/checkout from 5 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/bumpversion.yml | 2 +- .github/workflows/docspublish.yml | 4 ++-- .github/workflows/homebrewpublish.yml | 2 +- .github/workflows/label_pr.yml | 2 +- .github/workflows/pythonpackage.yml | 2 +- .github/workflows/pythonpublish.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/bumpversion.yml b/.github/workflows/bumpversion.yml index ba48d677e0..d74ed624a7 100644 --- a/.github/workflows/bumpversion.yml +++ b/.github/workflows/bumpversion.yml @@ -12,7 +12,7 @@ jobs: name: "Bump version and create changelog with commitizen" steps: - name: Check out - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index eb52dc46a8..0102856cbc 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -10,7 +10,7 @@ jobs: update-cli-screenshots: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} fetch-depth: 0 @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest needs: update-cli-screenshots steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" fetch-depth: 0 diff --git a/.github/workflows/homebrewpublish.yml b/.github/workflows/homebrewpublish.yml index b603acd181..ca4f66c872 100644 --- a/.github/workflows/homebrewpublish.yml +++ b/.github/workflows/homebrewpublish.yml @@ -12,7 +12,7 @@ jobs: if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 with: diff --git a/.github/workflows/label_pr.yml b/.github/workflows/label_pr.yml index c1a3df2c70..8e2d674f2b 100644 --- a/.github/workflows/label_pr.yml +++ b/.github/workflows/label_pr.yml @@ -9,7 +9,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: sparse-checkout: | .github/labeler.yml diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 7a574c9e0a..2c332391db 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -10,7 +10,7 @@ jobs: platform: [ubuntu-22.04, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index e70690a1a3..de078815fa 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -9,7 +9,7 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" fetch-depth: 0 From 84629b5831f5ba508b03ae02abf9d53d4dacd773 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Fri, 21 Nov 2025 10:31:21 +0800 Subject: [PATCH 091/221] docs(external_links): fix outdated link and add links to another commitizen talk --- docs/external_links.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/external_links.md b/docs/external_links.md index a90bbd085b..1b5efb05df 100644 --- a/docs/external_links.md +++ b/docs/external_links.md @@ -3,14 +3,15 @@ ## Talks | Name | Speaker | Occasion | Language | Extra | -| ------------------------------------------------------------------------- | --------------- | ---------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- | -| commitizen-tools: What can we gain from crafting a git message convention | Wei Lee | Taipei.py 2020 June Meetup, Remote Python Pizza 2020 | English | [slides](https://speakerdeck.com/leew/commitizen-tools-what-can-we-gain-from-crafting-a-git-message-convention-at-taipey-dot-py) | -| Automating release cycles | Santiago Fraire | PyAmsterdam June 24, 2020, Online | English | [slides](https://woile.github.io/commitizen-presentation/) | -| [Automatizando Releases con Commitizen y Github Actions][automatizando] | Santiago Fraire | PyConAr 2020, Remote | Español | [slides](https://woile.github.io/automating-releases-github-actions-presentation/#/) | +| ------------------------------------------------------------------------- | --------------- | ---------------------------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| [Atomic Commits: An Easy & Proven Way to Manage & Automate Release Process](https://www.youtube.com/watch?v=IxzN9ClXhs8) | Wei Lee | COSCUP 2023 | Taiwanese Mandarin | [slides](https://speakerdeck.com/leew/atomic-commits-an-easy-and-proven-way-to-manage-and-automate-release-process) | +| commitizen-tools: What can we gain from crafting a git message convention | Wei Lee | Taipei.py 2020 June Meetup, Remote Python Pizza 2020 | English | [slides](https://speakerdeck.com/leew/commitizen-tools-what-can-we-gain-from-crafting-a-git-message-convention-at-taipey-dot-py) | +| Automating release cycles | Santiago Fraire | PyAmsterdam June 24, 2020, Online | English | [slides](https://woile.github.io/commitizen-presentation/) | +| [Automatizando Releases con Commitizen y Github Actions][automatizando] | Santiago Fraire | PyConAr 2020, Remote | Español | [slides](https://woile.github.io/automating-releases-github-actions-presentation/#/) | ## Articles -- [Python Table Manners - Commitizen: 規格化 commit message](https://lee-w.github.io/posts/tech/2020/03/python-table-manners-commitizen/) (Written in Traditional Mandarin) +- [Python Table Manners - Commitizen: 規格化 commit message](https://blog.wei-lee.me/posts/tech/2020/03/python-table-manners-commitizen/) (Written in Traditional Mandarin) - [Automating semantic release with commitizen](https://woile.dev/posts/automating-semver-releases-with-commitizen/) (English) - [How to Write Better Git Commit Messages – A Step-By-Step Guide](https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/?utm_source=tldrnewsletter) (English) - [Continuous delivery made easy (in Python)](https://medium.com/dev-genius/continuous-delivery-made-easy-in-python-c085e9c82e69) From 89564c694139a73f317860a9eae693cbc0f67d1f Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 19 Nov 2025 13:09:43 +0800 Subject: [PATCH 092/221] docs(bump): check consistency warning minor update --- docs/commands/bump.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index eb807f841c..d819b38be0 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -222,10 +222,11 @@ In this example, it will detect that `setup.py` contains `1.0.5` instead of `1.2 ``` 2. Manually update the version in `setup.py` to match the version in `pyproject.toml`: - ```python title="setup.py" + ```diff title="setup.py" from setuptools import setup - setup(..., version="1.21.0", ...) + - setup(..., version="1.0.5", ...) + + setup(..., version="1.21.0", ...) ``` 3. Run the bump command again: From c92280fb82697559b626c47e575c00f4ec7e831c Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 19 Nov 2025 14:57:47 +0800 Subject: [PATCH 093/221] docs(bump): add missing --allow-no-commit behaviors and other minor documentation changes --- docs/commands/bump.md | 78 +++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index d819b38be0..ebd8b2774e 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -111,7 +111,7 @@ Commitizen supports the [PEP 440][pep440] version format, which includes several ### `--files-only` -Bumps the version in the files defined in [`version_files`](#version_files) without creating a commit and tag on the git repository, +Bumps the version in the files defined in [`version_files`](#version_files) without creating a commit and tag on the git repository. ```bash cz bump --files-only @@ -128,7 +128,7 @@ cz bump --changelog ### `--prerelease` The bump is a pre-release bump, meaning that in addition to a possible version bump the new version receives a -pre-release segment compatible with the bump’s version scheme, where the segment consist of a _phase_ and a +pre-release segment compatible with the bump's version scheme, where the segment consists of a _phase_ and a non-negative number. Supported options for `--prerelease` are the following phase names `alpha`, `beta`, or `rc` (release candidate). For more details, refer to the [Python Packaging User Guide](https://packaging.python.org/en/latest/specifications/version-specifiers/#pre-releases). @@ -281,19 +281,20 @@ Any other messages generated by `cz bump` will be sent to `stderr`. When this flag is used, `--changelog` is implied. However, it is recommended to set `--changelog` (or the setting `update_changelog_on_bump`) explicitly when the option `--changelog-to-stdout` is used. -#### Useful scenarios +!!! note "Useful scenarios" + Pipe the newly created changelog to another tool. -This is useful to pipe the newly created changelog to another tool. For example, it can be sent to an auditing system, or to create a GitHub Release, etc. + The output can be redirected to an auditing system, or used to create a GitHub Release, etc. -```bash -cz bump --changelog --changelog-to-stdout > body.md -``` + ```bash + cz bump --changelog --changelog-to-stdout > body.md + ``` ### `--git-output-to-stderr` -If `--git-output-to-stderr` is used, git commands output is redirected to `stderr`. +Redirects git commands output to `stderr`. -Useful when used with `--changelog-to-stdout` and piping the output to a file, +Useful when used with `--changelog-to-stdout` and piping the output to a file. For example, `git commit` output may pollute `stdout`, so it is recommended to use this flag when piping the output to a file. @@ -306,7 +307,7 @@ Useful to combine with code formatters, like [Prettier](https://prettier.io/). ### `--major-version-zero` -Breaking changes does not bump the major version number. +Breaking changes do not bump the major version number. Say you have a project with the version `0.1.x` and you commit a breaking change like this: @@ -344,7 +345,7 @@ Then the version of your project will be bumped to `0.2.0` instead of `1.0.0`. ### `--gpg-sign` -Create gpg signed tags. +Creates gpg signed tags. ```bash cz bump --gpg-sign @@ -367,18 +368,16 @@ See [the template customization section](../customization.md#customizing-the-cha ### `--build-metadata` -Provides a way to specify additional metadata in the version string. This parameter is not compatible with `--local-version` as it uses the same part of the version string. +Specifies additional metadata in the version string. ```bash +# creates a version like `1.1.2+yourmetadata`. cz bump --build-metadata yourmetadata ``` -Will create a version like `1.1.2+yourmetadata`. - -This can be useful for multiple things - -- Git hash in version -- Labeling the version with additional metadata. +!!! note "Example usage" + - Git hash in version + - Labeling the version with additional metadata. !!! note Commitizen ignores everything after `+` when it bumps the version. @@ -392,16 +391,19 @@ This can be useful for multiple things - Version `1.2.3+a`, and `1.2.3+b` are the same version! Tools should not use the string after `+` for version calculation. This is probably not a guarantee (example in helm) even tho it is in the spec. - It might be problematic having the metadata in place when doing upgrades depending on what tool you use. +!!! warning + This parameter is not compatible with `--local-version` as it uses the same part of the version string. + ### `--get-next` -Provides a way to determine the next version and write it to stdout. This parameter is not compatible with `--changelog` -and `manual version`. +Similar to `--dry-run` but only outputs the next version. ```bash +# outputs 1.0.1 if the current version is 1.0.0 and the increment is PATCH cz bump --get-next ``` -Will only output the next version, e.g., `1.2.3`. This can be useful for determining the next version based on CI for non-production environments/builds. +Useful for determining the next version based on CI for non-production environments/builds. !!! note "Compare with `--dry-run`" `--dry-run` provides a more detailed output including the changes as they would appear in the changelog file, while `--get-next` only outputs the next version. @@ -427,15 +429,27 @@ Will only output the next version, e.g., `1.2.3`. This can be useful for determi ### `--allow-no-commit` -Allow the project version to be bumped even when there's no eligible version. This is most useful when used with `--increment {MAJOR,MINOR,PATCH}` or `[MANUAL_VERSION]` +Allow the project version to be bumped even when there's no eligible version. -```sh -# bump a minor version even when there's only bug fixes, documentation changes or even no commits -cz bump --incremental MINOR --allow-no-commit +!!! note "Example usage" + ```sh + # bump a minor version even when there's only bug fixes, documentation changes or even no commits -# bump version to 2.0.0 even when there's no breaking changes changes or even no commits -cz bump --allow-no-commit 2.0.0 -``` + cz bump --increment MINOR --allow-no-commit + + # bump version to 2.0.0 even when there's no breaking changes or even no commits + cz bump --allow-no-commit 2.0.0 + ``` + +!!! note "Default increment" + The increment is overridden to `PATCH` if there is no increment detected or specified. + + In other words, `cz bump --allow-no-commit` allows you to bump the version to the next patch version even when there is no eligible commit. + + ```sh + # will bump to `1.0.1` if the current version is `1.0.0`. + cz bump --allow-no-commit + ``` ### `--version-scheme` @@ -480,19 +494,19 @@ Supported variables: | Variable | Description | |--------------------------------|---------------------------------------------| -| `$version`, `${version}` | fully generated version | +| `$version`, `${version}` | fully generated version | | `$major`, `${major}` | MAJOR increment | | `$minor`, `${minor}` | MINOR increment | | `$patch`, `${patch}` | PATCH increment | | `$prerelease`, `${prerelease}` | Prerelease (alpha, beta, release candidate) | -| `$devrelease`, ${devrelease}` | Development release | +| `$devrelease`, `${devrelease}` | Development release | ### `version_files` Identify the files or glob patterns which should be updated with the new version. Commitizen will update its configuration file automatically when bumping, -regarding if the file is present or not in `version_files`. +regardless of whether the file is present or not in `version_files`. You may specify the `version_files` in your configuration file. @@ -686,7 +700,7 @@ See [Version Schemes](#version-schemes-version-scheme). Some situations from Commitizen raise an exit code different from 0. If the error code is different from 0, any CI or script running Commitizen might be interrupted. -If you have a special use case, where you don't want to raise one of this error codes, you can +If you have a special use case, where you don't want to raise one of these error codes, you can tell Commitizen to not raise them. ### Recommended use case From b565e4b45e5a82810797a5ab27dd01c3d23a0261 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 21 Nov 2025 01:21:19 +0800 Subject: [PATCH 094/221] docs(third-party): resturcture commitizen plugin documentation --- docs/customization.md | 2 +- docs/third-party-commitizen.md | 200 ------------------ docs/third-party-plugins/about.md | 73 +++++++ .../commitizen-deno-provider.md | 28 +++ docs/third-party-plugins/commitizen-emoji.md | 17 ++ docs/third-party-plugins/conventional-jira.md | 13 ++ docs/third-party-plugins/cz-ai.md | 17 ++ .../cz-conventional-gitmoji.md | 19 ++ docs/third-party-plugins/cz-emoji.md | 17 ++ docs/third-party-plugins/cz-legacy.md | 19 ++ docs/third-party-plugins/cz-path.md | 54 +++++ .../github-jira-conventional.md | 17 ++ mkdocs.yml | 13 +- 13 files changed, 287 insertions(+), 202 deletions(-) delete mode 100644 docs/third-party-commitizen.md create mode 100644 docs/third-party-plugins/about.md create mode 100644 docs/third-party-plugins/commitizen-deno-provider.md create mode 100644 docs/third-party-plugins/commitizen-emoji.md create mode 100644 docs/third-party-plugins/conventional-jira.md create mode 100644 docs/third-party-plugins/cz-ai.md create mode 100644 docs/third-party-plugins/cz-conventional-gitmoji.md create mode 100644 docs/third-party-plugins/cz-emoji.md create mode 100644 docs/third-party-plugins/cz-legacy.md create mode 100644 docs/third-party-plugins/cz-path.md create mode 100644 docs/third-party-plugins/github-jira-conventional.md diff --git a/docs/customization.md b/docs/customization.md index 99ffd39ba7..50bb0c8fbb 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -207,7 +207,7 @@ cookiecutter gh:commitizen-tools/commitizen_cz_template See [commitizen_cz_template](https://github.com/commitizen-tools/commitizen_cz_template) for details. -Once you publish your rules, you can send us a PR to the [Third-party section](./third-party-commitizen.md). +Once you publish your rules, you can send us a PR to the [Third-party section](./third-party-plugins/about.md). ### Custom commit rules diff --git a/docs/third-party-commitizen.md b/docs/third-party-commitizen.md deleted file mode 100644 index 0c35a31557..0000000000 --- a/docs/third-party-commitizen.md +++ /dev/null @@ -1,200 +0,0 @@ -## Third-Party Commitizen Templates - -In addition to the native templates, some alternative commit format templates -are available as PyPI packages (installable with `pip`). - -### [cz-ai](https://github.com/watadarkstar/cz_ai) - -A Commitizen plugin that leverages OpenAI's GPT-4o to automatically generate clear, concise, and conventional commit messages based on your staged git changes. - -#### Installation - -```sh -pip install cz-ai -``` - -#### Usage - -```sh -cz --name cz_ai commit -``` - -### [Conventional JIRA](https://pypi.org/project/conventional-JIRA/) - -Just like _conventional commit_ format, but the scope has been restricted to a -JIRA issue format, i.e. `project-issueNumber`. This standardises scopes in a -meaningful way. - -#### Installation - -```sh -pip install conventional-JIRA -``` - -### [GitHub JIRA Conventional](https://pypi.org/project/cz-github-jira-conventional/) - -This plugin extends the Commitizen tools by: - -- requiring a JIRA issue ID in the commit message -- creating links to GitHub commits in the CHANGELOG.md -- creating links to JIRA issues in the CHANGELOG.md - -#### Installation - -```sh -pip install cz-github-jira-conventional -``` - -For installation instructions (configuration and pre-commit) please visit [https://github.com/apheris/cz-github-jira-conventional](https://github.com/apheris/cz-github-jira-conventional) - -### [cz-emoji](https://github.com/adam-grant-hendry/cz-emoji) - -_conventional commit_ format, but with emojis - -#### Installation - -```sh -pip install cz-emoji -``` - -#### Usage - -```sh -cz --name cz_emoji commit -``` - -### [cz-conventional-gitmoji](https://github.com/ljnsn/cz-conventional-gitmoji) - -*conventional commit*s, but with [gitmojis](https://gitmoji.dev). - -Includes a pre-commit hook that automatically adds the correct gitmoji to the commit message based on the conventional type. - -#### Installation - -```sh -pip install cz-conventional-gitmoji -``` - -#### Usage - -```sh -cz --name cz_gitmoji commit -``` - -### [Commitizen emoji](https://pypi.org/project/commitizen-emoji/) (Unmaintained) - -Just like _conventional commit_ format, but with emojis and optionally time spent and related tasks. - -#### Installation - -```sh -pip install commitizen-emoji -``` - -#### Usage - -```sh -cz --name cz_commitizen_emoji commit -``` - -### [Conventional Legacy (cz_legacy)][1] - -An extension of the _conventional commit_ format to include user-specified -legacy change types in the `CHANGELOG` while preventing the legacy change types -from being used in new commit messages - -#### Installation - -```sh -pip install cz_legacy -``` - -#### Usage - -See the [README][1] for instructions on configuration - -[1]: https://pypi.org/project/cz_legacy - -## Third-Party Commitizen Providers - -Commitizen can read and write version from different sources. In addition to the native providers, some alternative version sources are available as PyPI packages (installable with `pip`). - -### [commitizen-deno-provider](https://pypi.org/project/commitizen-deno-provider/) - -A provider for **Deno** projects. The provider updates the version in deno.json and jsr.json files. - -#### Installation - -```sh -pip install commitizen-deno-provider -``` - -#### Usage - -Add `deno-provider` to your configuration file. - -Example for `.cz.yaml`: - -```yaml ---- -commitizen: - major_version_zero: true - name: cz_conventional_commits - tag_format: $version - update_changelog_on_bump: true - version_provider: deno-provider - version_scheme: semver -``` - -### [cz-path](https://pypi.org/project/cz-path/) - -Provides prefix choices for commit messages based on staged files (Git only). -For example, if the staged files are `component/z/a.ts` and `component/z/b.ts`, -the path prefix option will be `component/z` and commit message might look like: -`component/z/: description of changes`. If only one file is staged, the extension -is removed in the prefix. - -#### Installation - -```sh -pip install cz-path -``` - -#### Usage - -Add `cz-path` to your configuration file. - -Example for `.cz.json`: - -```json -{ - "commitizen": { - "name": "cz_path", - "remove_path_prefixes": ["src", "module_name"] - } -} -``` - -The default value for `remove_path_prefixes` is `["src"]`. Adding `/` to the -prefixes is not required. - -#### Example session - -```plain - $ git add .vscode/ - $ cz -n cz_path c -? Prefix: (Use arrow keys) - » .vscode - .vscode/ - project - (empty) -? Prefix: .vscode -? Commit title: adjust settings - -.vscode: adjust settings - -[main 0000000] .vscode: adjust settings - 2 files changed, 1 insertion(+), 11 deletions(-) - -Commit successful! -``` diff --git a/docs/third-party-plugins/about.md b/docs/third-party-plugins/about.md new file mode 100644 index 0000000000..9711386fc8 --- /dev/null +++ b/docs/third-party-plugins/about.md @@ -0,0 +1,73 @@ +# What are third-party plugins? + +Third-party plugins are a way to extend Commitizen with additional customized features. + +These plugins are available as PyPI packages (installable with `pip`). + +!!! note + New plugins are welcome! Once you published your plugins, please send us a PR to update this page. + +!!! note "Historical notes" + This section was originally called "Third-Party Commitizen Templates", but has been renamed to "Third-Party Commitizen Plugins" to better reflect the content. + +## Plugin features + + + + +### Commit message convention + +Includes the rules to validate and generate commit messages. + +### Version scheme + +Includes the rules to generate version numbers. + +### Version provider + +Read and write version from data sources. + +### Changelog format + +Generate changelog in customized formats. + + + + +## How to help us update the list of plugins? + +Please document what features the plugin provides: + +- a convention +- a scheme +- a provider +- a `changelog_format` + +Of course, a plugin can provide multiple features. +You may have noticed that `commitizen` itself can be viewed as a plugin that provides all the above features. + +Please see [cz-path](./cz-path.md) for a detailed example. + +## New plugin documentation template + + # [Package name](https://github.com/author/package-name) + + + + + + ## Installation + + ```sh + pip install package-name + ``` + + ## Usage + + ```sh + cz --name package-name commit + ``` + + ## Example + + diff --git a/docs/third-party-plugins/commitizen-deno-provider.md b/docs/third-party-plugins/commitizen-deno-provider.md new file mode 100644 index 0000000000..77f7d2e177 --- /dev/null +++ b/docs/third-party-plugins/commitizen-deno-provider.md @@ -0,0 +1,28 @@ +# [commitizen-deno-provider](https://pypi.org/project/commitizen-deno-provider/) + +A provider for **Deno** projects. The provider updates the version in `deno.json` and `jsr.json` files. + + + +## Installation + +```sh +pip install commitizen-deno-provider +``` + +## Usage + +Add `deno-provider` to your configuration file. + +Example for `.cz.yaml`: + +```yaml +--- +commitizen: + major_version_zero: true + name: cz_conventional_commits + tag_format: $version + update_changelog_on_bump: true + version_provider: deno-provider + version_scheme: semver +``` diff --git a/docs/third-party-plugins/commitizen-emoji.md b/docs/third-party-plugins/commitizen-emoji.md new file mode 100644 index 0000000000..e8e2654516 --- /dev/null +++ b/docs/third-party-plugins/commitizen-emoji.md @@ -0,0 +1,17 @@ +# [Commitizen emoji](https://pypi.org/project/commitizen-emoji/) (Unmaintained) + +Just like *conventional commit* format, but with emojis and optionally time spent and related tasks. + + + +## Installation + +```sh +pip install commitizen-emoji +``` + +## Usage + +```sh +cz --name cz_commitizen_emoji commit +``` diff --git a/docs/third-party-plugins/conventional-jira.md b/docs/third-party-plugins/conventional-jira.md new file mode 100644 index 0000000000..99505a2743 --- /dev/null +++ b/docs/third-party-plugins/conventional-jira.md @@ -0,0 +1,13 @@ +# [Conventional JIRA](https://pypi.org/project/conventional-JIRA/) + +Just like _conventional commit_ format, but the scope has been restricted to a +JIRA issue format, i.e. `project-issueNumber`. This standardises scopes in a +meaningful way. + + + +## Installation + +```sh +pip install conventional-JIRA +``` diff --git a/docs/third-party-plugins/cz-ai.md b/docs/third-party-plugins/cz-ai.md new file mode 100644 index 0000000000..e9ced907bf --- /dev/null +++ b/docs/third-party-plugins/cz-ai.md @@ -0,0 +1,17 @@ +# [cz-ai](https://github.com/watadarkstar/cz_ai) + +A Commitizen plugin that leverages OpenAI's GPT-4o to automatically generate clear, concise, and conventional commit messages based on your staged git changes. + + + +## Installation + +```sh +pip install cz-ai +``` + +## Usage + +```sh +cz --name cz_ai commit +``` diff --git a/docs/third-party-plugins/cz-conventional-gitmoji.md b/docs/third-party-plugins/cz-conventional-gitmoji.md new file mode 100644 index 0000000000..f4157105e7 --- /dev/null +++ b/docs/third-party-plugins/cz-conventional-gitmoji.md @@ -0,0 +1,19 @@ +# [cz-conventional-gitmoji](https://github.com/ljnsn/cz-conventional-gitmoji) + +*conventional commit*s, but with [gitmojis](https://gitmoji.dev). + +Includes a pre-commit hook that automatically adds the correct gitmoji to the commit message based on the conventional type. + + + +## Installation + +```sh +pip install cz-conventional-gitmoji +``` + +## Usage + +```sh +cz --name cz_gitmoji commit +``` diff --git a/docs/third-party-plugins/cz-emoji.md b/docs/third-party-plugins/cz-emoji.md new file mode 100644 index 0000000000..c638f4bfa1 --- /dev/null +++ b/docs/third-party-plugins/cz-emoji.md @@ -0,0 +1,17 @@ +# [cz-emoji](https://github.com/adam-grant-hendry/cz-emoji) + +_conventional commit_ format, but with emojis. + + + +## Installation + +```sh +pip install cz-emoji +``` + +## Usage + +```sh +cz --name cz_emoji commit +``` diff --git a/docs/third-party-plugins/cz-legacy.md b/docs/third-party-plugins/cz-legacy.md new file mode 100644 index 0000000000..4f0a2e1221 --- /dev/null +++ b/docs/third-party-plugins/cz-legacy.md @@ -0,0 +1,19 @@ +# [Conventional Legacy (cz_legacy)][cz_legacy] + +An extension of the *conventional commit* format to include user-specified +legacy change types in the `CHANGELOG` while preventing the legacy change types +from being used in new commit messages. + + + +## Installation + +```sh +pip install cz_legacy +``` + +## Usage + +See the [Conventional Legacy README][cz_legacy] for instructions on configuration. + +[cz_legacy]: https://pypi.org/project/cz_legacy diff --git a/docs/third-party-plugins/cz-path.md b/docs/third-party-plugins/cz-path.md new file mode 100644 index 0000000000..7a2ba59176 --- /dev/null +++ b/docs/third-party-plugins/cz-path.md @@ -0,0 +1,54 @@ +# [cz-path](https://pypi.org/project/cz-path/) + +Provides prefix choices for commit messages based on staged files (Git only). +For example, if the staged files are `component/z/a.ts` and `component/z/b.ts`, +the path prefix option will be `component/z` and commit message might look like: +`component/z/: description of changes`. If only one file is staged, the extension +is removed in the prefix. + +This plugins provides a commitizen convention for commit messages. + +## Installation + +```sh +pip install cz-path +``` + +## Usage + +Add `cz-path` to your configuration file. + +Example for `.cz.json`: + +```json +{ + "commitizen": { + "name": "cz_path", + "remove_path_prefixes": ["src", "module_name"] + } +} +``` + +The default value for `remove_path_prefixes` is `["src"]`. Adding `/` to the +prefixes is not required. + +## Example session + +```plain + $ git add .vscode/ + $ cz -n cz_path c +? Prefix: (Use arrow keys) + » .vscode + .vscode/ + project + (empty) +? Prefix: .vscode +? Commit title: adjust settings + +.vscode: adjust settings + +[main 0000000] .vscode: adjust settings + 2 files changed, 1 insertion(+), 11 deletions(-) + +Commit successful! +``` diff --git a/docs/third-party-plugins/github-jira-conventional.md b/docs/third-party-plugins/github-jira-conventional.md new file mode 100644 index 0000000000..6032b8e7ff --- /dev/null +++ b/docs/third-party-plugins/github-jira-conventional.md @@ -0,0 +1,17 @@ +# [GitHub JIRA Conventional](https://pypi.org/project/cz-github-jira-conventional/) + +This plugin extends the Commitizen tools by: + +- requiring a JIRA issue ID in the commit message +- creating links to GitHub commits in `CHANGELOG.md` +- creating links to JIRA issues in `CHANGELOG.md` + + + +## Installation + +```sh +pip install cz-github-jira-conventional +``` + +For installation instructions (configuration and pre-commit), please visit the [GitHub repository](https://github.com/apheris/cz-github-jira-conventional). diff --git a/mkdocs.yml b/mkdocs.yml index dec8d3fd5d..49d76c30ad 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,7 +56,18 @@ nav: - Monorepo support: "tutorials/monorepo_guidance.md" - FAQ: "faq.md" - Exit Codes: "exit_codes.md" - - Third-Party Commitizen Templates: "third-party-commitizen.md" + - Third-Party Commitizen Plugins: + - About: "third-party-plugins/about.md" + # Please sort the plugins alphabetically + - "third-party-plugins/commitizen-deno-provider.md" + - "third-party-plugins/commitizen-emoji.md" + - "third-party-plugins/conventional-jira.md" + - "third-party-plugins/cz-ai.md" + - "third-party-plugins/cz-conventional-gitmoji.md" + - "third-party-plugins/cz-emoji.md" + - "third-party-plugins/cz-legacy.md" + - "third-party-plugins/cz-path.md" + - "third-party-plugins/github-jira-conventional.md" - Contributing: "contributing.md" - Contributing TL;DR: "contributing_tldr.md" - Resources: "external_links.md" From 52cb251726c36084471deec242181b4196f3a5ac Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 21 Nov 2025 13:41:51 +0800 Subject: [PATCH 095/221] docs(faq): minor updates in faq and make features wont add a separate page --- docs/faq.md | 46 +++++++++++++++++++-------------------- docs/features_wont_add.md | 7 ++++++ mkdocs.yml | 1 + 3 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 docs/features_wont_add.md diff --git a/docs/faq.md b/docs/faq.md index ee9d97068d..22cd9e8d6c 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,14 +1,8 @@ -## Features we won't add +This page contains frequently asked questions about Commitizen. -For a comprehensive list of features that have been considered but won't be implemented, please refer to our [issue tracker](https://github.com/commitizen-tools/commitizen/issues?q=is:issue%20state:closed%20label:%22issue-status:%20wont-fix%22%20OR%20label:%22issue-status:%20wont-implement%22). +## Support for [`PEP621`](https://peps.python.org/pep-0621/) -- Enable multiple locations of config file `.cz.*` [#955](https://github.com/commitizen-tools/commitizen/issues/955) -- Create a flag to build the changelog from commits in multiple git repositories [#790](https://github.com/commitizen-tools/commitizen/issues/790) -- Global Configuration [#597](https://github.com/commitizen-tools/commitizen/issues/597) - -## Support for PEP621 - -PEP621 establishes a `[project]` definition inside `pyproject.toml` +`PEP621` establishes a `[project]` definition inside `pyproject.toml` ```toml [project] @@ -16,7 +10,7 @@ name = "spam" version = "2.5.1" ``` -Commitizen provides a [`pep621` version provider](config.md#version-providers) to get and set version from this field. +Commitizen provides a `PEP621` [version provider](config.md#version-providers) to get and set version from this field. You just need to set the proper `version_provider` setting: ```toml @@ -28,12 +22,14 @@ version = "2.5.1" version_provider = "pep621" ``` -## Why are `revert` and `chore` valid types in the check pattern of cz conventional_commits but not types we can select? +## Why are `revert` and `chore` valid types in the check pattern of `cz_conventional_commits` but not types we can select? -`revert` and `chore` are added to the "pattern" in `cz check` in order to prevent backward errors, but officially they are not part of conventional commits, we are using the latest [types from Angular](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type) (they used to but were removed). -However, you can create a customized `cz` with those extra types. (See [Customization](customization.md)). +`revert` and `chore` are added to `pattern` in `cz check` in order to prevent backward errors, but officially they are not part of conventional commits, we are using the latest [types from Angular](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type) (they used to but were removed). +However, you can create a customized `cz` with those extra types. See [Customization](customization.md) for more details. -See more discussion in issue [#142](https://github.com/commitizen-tools/commitizen/issues/142) and [#36](https://github.com/commitizen-tools/commitizen/issues/36) +See more discussion in +- [issue #142](https://github.com/commitizen-tools/commitizen/issues/142) +- [issue #36](https://github.com/commitizen-tools/commitizen/issues/36) ## How to revert a bump? @@ -47,23 +43,25 @@ git reset --hard HEAD This will remove the last tag created, plus the commit containing the update to `.cz.toml` and the changelog generated for the version. -In case the commit was pushed to the server you can remove it by running +In case the commit was pushed to the server, you can remove it by running: ```sh git push --delete origin ``` -## Is this project affiliated with the Commitizen JS project? +## Is this project affiliated with the [Commitizen JS][cz-js] project? -It is not affiliated. +**It is not affiliated.** Both are used for similar purposes, parsing commits, generating changelog and version we presume. This one is written in python to make integration easier for python projects and the other serves the JS packages. -They differ a bit in design, not sure if cz-js does any of this, but these are some things you can do with this repo (python's commitizen): + -- create custom rules, version bumps and changelog generation, by default we use the popular conventional commits (I think cz-js allows this). -- single package, install one thing and it will work (cz-js is a monorepo, but you have to install different dependencies AFAIK) +They differ a bit in design, not sure if cz-js does any of this, but these are some things you can do with our Commitizen: + +- create custom rules, version bumps and changelog generation. By default, we use the popular conventional commits (I think cz-js allows this). +- single package, install one thing and it will work. cz-js is a monorepo, but you have to install different dependencies as far as I know. - pre-commit integration - works on any language project, as long as you create the `.cz.toml` or `cz.toml` file. @@ -73,8 +71,6 @@ If you are using conventional commits in your git history, then you could swap o Regarding the name, [cz-js][cz-js] came first, they used the word Commitizen first. When this project was created originally, the creator read "be a good commitizen", and thought it was just a cool word that made sense, and this would be a package that helps you be a good "commit citizen". -[cz-js]: https://github.com/commitizen/cz-cli - ## How to handle revert commits? ```sh @@ -82,7 +78,7 @@ git revert --no-commit git commit -m "revert: foo bar" ``` -## Why don't we use Pydantic? +## Why don't we use [Pydantic](https://docs.pydantic.dev/)? While Pydantic is a powerful and popular library for data validation, we intentionally avoid using it in this project to keep our dependency tree minimal and maintainable. @@ -98,7 +94,7 @@ In short, avoiding Pydantic helps us: ## I got `Exception [WinError 995] The I/O operation ...` error -This error was caused by a Python bug on Windows. It's been fixed by [this PR](https://github.com/python/cpython/pull/22017), and according to Python's changelog, [3.8.6rc1](https://docs.python.org/3.8/whatsnew/changelog.html#python-3-8-6-release-candidate-1) and [3.9.0rc2](https://docs.python.org/3.9/whatsnew/changelog.html#python-3-9-0-release-candidate-2) should be the accurate versions first contain this fix. In conclusion, upgrade your Python version might solve this issue. +This error was caused by a Python bug on Windows. It's been fixed by [cpython #22017](https://github.com/python/cpython/pull/22017), and according to Python's changelog, [3.8.6rc1](https://docs.python.org/3.8/whatsnew/changelog.html#python-3-8-6-release-candidate-1) and [3.9.0rc2](https://docs.python.org/3.9/whatsnew/changelog.html#python-3-9-0-release-candidate-2) should be the accurate versions first contain this fix. In conclusion, upgrade your Python version might solve this issue. More discussion can be found in issue [#318](https://github.com/commitizen-tools/commitizen/issues/318). @@ -162,3 +158,5 @@ ignored_tag_formats = [ "v${major}.${minor}", ] ``` + +[cz-js]: https://github.com/commitizen/cz-cli diff --git a/docs/features_wont_add.md b/docs/features_wont_add.md new file mode 100644 index 0000000000..9fbd6d5b5c --- /dev/null +++ b/docs/features_wont_add.md @@ -0,0 +1,7 @@ +This page contains features that have been proposed or considered but won't be implemented in Commitizen. + +For a comprehensive list, please refer to our [issue tracker](https://github.com/commitizen-tools/commitizen/issues?q=is:issue%20state:closed%20label:%22issue-status:%20wont-fix%22%20OR%20label:%22issue-status:%20wont-implement%22). + +- Enable multiple locations of config file `.cz.*` [#955](https://github.com/commitizen-tools/commitizen/issues/955) +- Create a flag to build the changelog from commits in multiple git repositories [#790](https://github.com/commitizen-tools/commitizen/issues/790) +- Global Configuration [#597](https://github.com/commitizen-tools/commitizen/issues/597) diff --git a/mkdocs.yml b/mkdocs.yml index 49d76c30ad..8a55bb23fa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -55,6 +55,7 @@ nav: - Developmental releases: "tutorials/dev_releases.md" - Monorepo support: "tutorials/monorepo_guidance.md" - FAQ: "faq.md" + - Features we won't add: "features_wont_add.md" - Exit Codes: "exit_codes.md" - Third-Party Commitizen Plugins: - About: "third-party-plugins/about.md" From 771b2172a6c4860c61d9871a0a9d51abcc6be874 Mon Sep 17 00:00:00 2001 From: Tim Hsiung Date: Wed, 3 Dec 2025 16:13:20 +0800 Subject: [PATCH 096/221] docs(pyproject): update maintainers list (#1681) --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 8211b969d0..bebf011187 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,7 @@ authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ { name = "Wei Lee", email = "weilee.rx@gmail.com" }, { name = "Axel H.", email = "noirbizarre@gmail.com" }, + { name = "Tim Hsiung", email = "bear890707@gmail.com" }, ] license = { file = "LICENSE" } readme = "docs/README.md" From 7c64b9189c17291f072ee9f73974642793457502 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 01:05:20 +0000 Subject: [PATCH 097/221] ci(deps): bump dawidd6/action-homebrew-bump-formula from 6 to 7 Bumps [dawidd6/action-homebrew-bump-formula](https://github.com/dawidd6/action-homebrew-bump-formula) from 6 to 7. - [Release notes](https://github.com/dawidd6/action-homebrew-bump-formula/releases) - [Commits](https://github.com/dawidd6/action-homebrew-bump-formula/compare/v6...v7) --- updated-dependencies: - dependency-name: dawidd6/action-homebrew-bump-formula dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/homebrewpublish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/homebrewpublish.yml b/.github/workflows/homebrewpublish.yml index ca4f66c872..3ca67da811 100644 --- a/.github/workflows/homebrewpublish.yml +++ b/.github/workflows/homebrewpublish.yml @@ -24,7 +24,7 @@ jobs: run: | echo "project_version=$(cz version --project)" >> $GITHUB_ENV - name: Update Homebrew formula - uses: dawidd6/action-homebrew-bump-formula@v6 + uses: dawidd6/action-homebrew-bump-formula@v7 with: token: ${{secrets.PERSONAL_ACCESS_TOKEN}} formula: commitizen From 295d7a925e4ac21ab782befbded6cdfe33bb4eb1 Mon Sep 17 00:00:00 2001 From: Tim Hsiung Date: Thu, 4 Dec 2025 11:23:27 +0800 Subject: [PATCH 098/221] docs(contributing): fix broken link (#1684) --- docs/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.md b/docs/contributing.md index 16db930626..9ba95f5ec5 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -4,7 +4,7 @@ First, thank you for taking the time to contribute! 🎉 Your contributions help When contributing to Commitizen, we encourage you to: -1. First, check out the [issues](https://github.com/commitizen-tools/commitizen/issues) and [Features we won't add](faq.md#features-we-wont-add) to see if there's already a discussion about the change you wish to make. +1. First, check out the [issues](https://github.com/commitizen-tools/commitizen/issues) and [Features we won't add](features_wont_add.md) to see if there's already a discussion about the change you wish to make. 2. If there's no discussion, [create an issue](https://github.com/commitizen-tools/commitizen/issues/new) to discuss your proposed changes. 3. Follow our [development workflow](#development-workflow) and guidelines below. From 4ade72164c2489c80b90d8318f6827d913256c2a Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 3 Dec 2025 22:45:43 +0800 Subject: [PATCH 099/221] docs(monorepo_guidance): fix wording and grammar issues, update structure --- docs/tutorials/monorepo_guidance.md | 120 +++++++++++++++------------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/docs/tutorials/monorepo_guidance.md b/docs/tutorials/monorepo_guidance.md index 6f15a87247..f863a9e531 100644 --- a/docs/tutorials/monorepo_guidance.md +++ b/docs/tutorials/monorepo_guidance.md @@ -1,81 +1,87 @@ # Configuring Commitizen in a monorepo -This tutorial assumes the monorepo layout is designed with multiple components that can be released independently of each -other, it also assumes that conventional commits with scopes are in use. Some suggested layouts: - -```shell-session -. -├── library-b -│   └── .cz.toml -└── library-z - └── .cz.toml -``` - -```shell-session -src -├── library-b -│   └── .cz.toml -└── library-z - └── .cz.toml -``` - -Sample `.cz.toml` for each component: - -```toml -# library-b/.cz.toml -[tool.commitizen] -name = "cz_customize" -version = "0.0.0" -tag_format = "${version}-library-b" # the component name can be a prefix or suffix with or without a separator -ignored_tag_formats = ["${version}-library-*"] # Avoid noise from other tags -update_changelog_on_bump = true -``` - -```toml -# library-z/.cz.toml -[tool.commitizen] -name = "cz_customize" -version = "0.0.0" -tag_format = "${version}-library-z" -ignored_tag_formats = ["${version}-library-*"] # Avoid noise from other tags -update_changelog_on_bump = true -``` - -And finally, to bump each of these: - -```sh -cz --config library-b/.cz.toml bump --yes -cz --config library-z/.cz.toml bump --yes -``` +This tutorial assumes that your monorepo is structured with multiple components that can be released independently of each other. +It also assumes that you are using conventional commits with scopes. + +Here is a step-by-step example using two libraries, `library-b` and `library-z`: + +1. **Organize your monorepo** + + For example, you might have one of these layouts: + + ```shell-session + . + ├── library-b + │   └── .cz.toml + └── library-z + └── .cz.toml + ``` + + ```shell-session + src + ├── library-b + │   └── .cz.toml + └── library-z + └── .cz.toml + ``` + +2. **Add a Commitizen configuration for each component** + + ```toml + # library-b/.cz.toml + [tool.commitizen] + name = "cz_customize" + version = "0.0.0" + tag_format = "${version}-library-b" # the component name can be a prefix or suffix with or without a separator + ignored_tag_formats = ["${version}-library-*"] # Avoid noise from other tags + update_changelog_on_bump = true + ``` + + ```toml + # library-z/.cz.toml + [tool.commitizen] + name = "cz_customize" + version = "0.0.0" + tag_format = "${version}-library-z" + ignored_tag_formats = ["${version}-library-*"] # Avoid noise from other tags + update_changelog_on_bump = true + ``` + +3. **Bump each component independently** + + ```sh + cz --config library-b/.cz.toml bump --yes + cz --config library-z/.cz.toml bump --yes + ``` ## Changelog per component -In order to filter the correct commits for each component, you'll have to come up with a strategy. +To filter the correct commits for each component, you'll need to define a strategy. For example: -- Trigger the pipeline based on the changed path, which can have some downsides, as you'll rely on the developer not including files from other files - - [GitHub actions](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore) uses `path` +- Trigger the pipeline based on the changed path. This can have some downsides, as you'll rely on the developer not including files from unrelated components. + - [GitHub Actions](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore) uses `path` - [Jenkins](https://www.jenkins.io/doc/book/pipeline/syntax/#built-in-conditions) uses `changeset` - [GitLab](https://docs.gitlab.com/ee/ci/yaml/#ruleschanges) uses `rules:changes` -- Filter certain pattern of the commit message (recommended) +- Filter commits by a specific pattern in the commit message (recommended) ### Example with scope in conventional commits -For this example, to include the message in the changelog, we will require commits to use a specific scope. -This way, only relevant commits will be included in the appropriate change log for a given component, and any other commit will be ignored. +In this example, we want `library-b`'s changelog to only include commits that use the `library-b` scope. +To achieve this, we configure Commitizen to match only commit messages with that scope. -Example config and commit for `library-b`: +Here is an example configuration for `library-b`: ```toml [tool.commitizen.customize] -changelog_pattern = "^(feat|fix)\\(library-b\\)(!)?:" #the pattern on types can be a wild card or any types you wish to include +changelog_pattern = "^(feat|fix)\\(library-b\\)(!)?:" # the type pattern can be a wildcard or any types you wish to include ``` -A commit message looking like this, would be included: +With this configuration, a commit message like the following would be included in `library-b`'s changelog: -``` +```text fix(library-b): Some awesome message ``` From e241812a15c078e91bb019af2b95753fd50ff3b0 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Fri, 5 Dec 2025 00:06:38 +0800 Subject: [PATCH 100/221] docs(check): rewrite command document --- docs/commands/check.md | 151 ++++++++++++++++++++++++++++++----------- docs/config.md | 4 +- 2 files changed, 112 insertions(+), 43 deletions(-) diff --git a/docs/commands/check.md b/docs/commands/check.md index 320bffb881..ef7f8f5f90 100644 --- a/docs/commands/check.md +++ b/docs/commands/check.md @@ -1,95 +1,164 @@ -# Check +This feature checks whether a string or a range of git commits follows the given committing rules. Comments in git messages will be ignored. -## About - -This feature checks whether the commit message follows the given committing rules. Comments in git messages will be ignored. - -If you want to set up an automatic check before every git commit, please refer to -[Automatically check message before commit](../tutorials/auto_check.md). +To set up an automatic check before every git commit, please refer to [Automatically check message before commit](../tutorials/auto_check.md). ## Usage ![cz check --help](../images/cli_help/cz_check___help.svg) -There are three mutually exclusive ways to use `cz check`: +More specifically, there are three mutually exclusive ways to use `cz check`: + +- Validate a range of git commit messages with `--rev-range` +- Validate a given string with `--message` or by piping the message to it +- Validate a commit message from a file with `--commit-msg-file` + +### Use `cz check` to validate a commit message before committing + +#### Option 1: use `--message` to check a given string: + +```bash +cz check --message +``` + +#### Option 2: pipe the message to `cz check`: +```bash +echo | cz check +``` + +#### Option 3: use `--commit-msg-file` to read the commit message from a file +```bash +cz check --commit-msg-file /path/to/file.txt +``` -- with `--rev-range` to check a range of pre-existing commits -- with `--message` or by piping the message to it to check a given string -- or with `--commit-msg-file` to read the commit message from a file +## Command Line Options -### Git Rev Range +### `--rev-range` -If you'd like to check a commit's message after it has already been created, then you can specify the range of commits to check with `--rev-range REV_RANGE`. +Test if a given range of commits in the git log passes `cz check`. ```bash -$ cz check --rev-range REV_RANGE +cz check --rev-range REV_RANGE ``` -For example, if you'd like to check all commits on a branch, you can use `--rev-range master..HEAD`. Or, if you'd like to check all commits starting from when you first implemented commit message linting, you can use `--rev-range ..HEAD`. +For more information on `REV_RANGE`, check the [git documentation](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#_commit_ranges). + +#### Use cases + +1. Validate the latest 3 commit messages: + ```bash + cz check --rev-range HEAD~3..HEAD + # or + cz check --rev-range HEAD~3.. + # or + cz check --rev-range HEAD~~~.. + ``` -You can also use `--use-default-range` to check all commits from the default branch up to HEAD. This is equivalent to using `--rev-range ..HEAD`. +1. Validate all git commit messages on some branch up to HEAD: + ```bash + cz check --rev-range ..HEAD + ``` -For more information on how git commit ranges work, you can check the [git documentation](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#_commit_ranges). + For example, to check all git commit messages on `main` branch up to HEAD: + ```bash + cz check --rev-range main..HEAD + ``` -### Commit Message + or if your project still uses `master` branch: + ```bash + cz check --rev-range master..HEAD + ``` -There are two ways you can provide your plain message and check it. + !!! note "Default branch" + Usually the default branch is `main` or `master`. + You can check the default branch by running `cz check --use-default-range`. -#### Method 1: use `-m` or `--message` +1. Validate all git commit messages starting from when you first implemented commit message linting: + + **(Why this is useful?)** Let's say you decided to enforce commit message today. However, it is impractical to `git rebase` all your previous commits. `--rev-range` helps you skip commits before you first implemented commit message linting by using a specific commit hash. + + ```bash + cz check --rev-range ..HEAD + ``` + +### `--use-default-range` + +Equivalent to `--rev-range ..HEAD`. ```bash -$ cz check --message MESSAGE +cz check --use-default-range +# or +cz check -d ``` -In this option, `MESSAGE` is the commit message to be checked. +### `--message` -#### Method 2: use pipe to pipe it to `cz check` +Test if a given string passes `cz check`. ```bash -$ echo MESSAGE | cz check +cz check --message ``` -In this option, `MESSAGE` is piped to `cz check` and will be checked. +### `--commit-msg-file` -### Commit Message File +Test if a given file contains a commit message that passes `cz check`. ```bash -$ cz check --commit-msg-file COMMIT_MSG_FILE +cz check --commit-msg-file ``` -In this option, `COMMIT_MSG_FILE` is the path of the temporary file that contains the commit message. -This argument can be useful when cooperating with git hooks. Please check [Automatically check message before commit](../tutorials/auto_check.md) for more information about how to use this argument with git hooks. +This can be useful when cooperating with git hooks. Please check [Automatically check message before commit](../tutorials/auto_check.md) for more detailed examples. -### Allow Abort +### `--allow-abort` + +Example: ```bash -cz check --message MESSAGE --allow-abort +cz check --message --allow-abort ``` Empty commit messages typically instruct Git to abort a commit, so you can pass `--allow-abort` to permit them. Since `git commit` accepts the `--allow-empty-message` flag (primarily for wrapper scripts), you may wish to disallow such commits in CI. `--allow-abort` may be used in conjunction with any of the other options. -### Allowed Prefixes +### `--allowed-prefixes` + +Skip validation for commit messages that start with the specified prefixes. -If the commit message starts with some specific prefixes, `cz check` returns `True` without checking the regex. -By default, the following prefixes are allowed: +If not set, commit messages starting with the following prefixes are ignored by `cz check`: - `Merge` - `Revert` - `Pull request` - `fixup!` - `squash!` +- `amend!` ```bash -cz check --message MESSAGE --allowed-prefixes 'Merge' 'Revert' 'Custom Prefix' +cz check --message --allowed-prefixes 'Merge' 'Revert' 'Custom Prefix' ``` -### Commit message length limit +For example, + +```bash +# The following message passes the check because it starts with 'Merge' +cz check --message "Merge branch 'main' into feature/new-feature" --allowed-prefixes 'Merge' -The argument `-l` (or `--message-length-limit`) followed by a positive number can limit the length of commit messages. -For example, `cz check --message MESSAGE -l 3` would fail the check, since `MESSAGE` is more than 3 characters long. -By default, the limit is set to 0, which means no limit on the length. +# The following fails +cz check --message "Merge branch 'main' into feature/new-feature" --allowed-prefixes 'aaa' +``` + +### `--message-length-limit` + +Restrict the length of **the first line** of the commit message. + +```bash +# The following passes +cz check --message "docs(check): fix grammar issues" -l 80 + +# The following fails +cz check --message "docs:very long long long long message with many words" -l 3 +``` -**Note that the limit applies only to the first line of the message.** +By default, the limit is set to `0`, which means no limit on the length. -Specifically, for `ConventionalCommitsCz` the length only counts from the type of change to the subject, while the body and the footer are not counted. +!!! note + Specifically, for `ConventionalCommitsCz` the length only counts from the type of change to the subject, while the body and the footer are not counted. diff --git a/docs/config.md b/docs/config.md index a3e3179887..307cf54a9f 100644 --- a/docs/config.md +++ b/docs/config.md @@ -407,11 +407,11 @@ setup( [major-version-zero]: commands/bump.md#-major-version-zero [prerelease-offset]: commands/bump.md#prerelease_offset [retry_after_failure]: commands/commit.md#retry -[allow_abort]: commands/check.md#allow-abort +[allow_abort]: commands/check.md#-allow-abort [version-scheme]: commands/bump.md#version-schemes-version-scheme [pre_bump_hooks]: commands/bump.md#pre_bump_hooks [post_bump_hooks]: commands/bump.md#post_bump_hooks -[allowed_prefixes]: commands/check.md#allowed-prefixes +[allowed_prefixes]: commands/check.md#-allowed-prefixes [additional-features]: https://github.com/tmbo/questionary#additional-features [customization]: customization.md [shortcuts]: customization.md#shortcut-keys From b1e74a5411e1a47bb5d6eadd85ae64cc3c755fa6 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sun, 16 Nov 2025 10:16:56 +0800 Subject: [PATCH 101/221] build(pyproject.toml): update dev group spec from poetry style to PEP 735 style This requires poetry-core >= 2.2.0 https://python-poetry.org/blog/announcing-poetry-2.2.0/ --- docs/contributing.md | 2 +- docs/contributing_tldr.md | 2 +- poetry.lock | 4 +-- pyproject.toml | 64 +++++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index 9ba95f5ec5..741a13f213 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -16,7 +16,7 @@ If you're a first-time contributor, please check out issues labeled [good first 1. **Python Environment** - Python `>=3.9` - - [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.0.0` + - [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.2.0` 2. **Version Control & Security** - Git - Commitizen diff --git a/docs/contributing_tldr.md b/docs/contributing_tldr.md index 9eecc3efa0..7b040c2951 100644 --- a/docs/contributing_tldr.md +++ b/docs/contributing_tldr.md @@ -3,7 +3,7 @@ Feel free to send a PR to update this file if you find anything useful. 🙇 ## Environment - Python `>=3.9` -- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.0.0` +- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.2.0` ## Useful commands diff --git a/poetry.lock b/poetry.lock index 49df9dcd52..4a60b32da5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "argcomplete" @@ -1955,4 +1955,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "cd5648d8aad7b58913b1c0e4cd4f04c98d5bcfa7e4ef8e7bb994a59492d7d4a2" +content-hash = "8f4edbdaff3ae48098899feacba7ea3764bdf2d960b78b8f5e8c39b19cc8c2e1" diff --git a/pyproject.toml b/pyproject.toml index bebf011187..7890edee2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,8 +85,38 @@ pep440 = "commitizen.version_schemes:Pep440" semver = "commitizen.version_schemes:SemVer" semver2 = "commitizen.version_schemes:SemVer2" +[dependency-groups] +dev = ["ipython>=8.0,<9.0", "tox>4", "poethepoet>=0.34.0,<1.0.0"] + +test = [ + "pytest>=7.2,<9.0", + "pytest-cov>=4,<7", + "pytest-mock>=3.10,<4.0", + "pytest-regressions>=2.4.0,<3.0.0", + "pytest-freezer>=0.4.6,<1.0.0", + "pytest-xdist>=3.1.0,<4.0.0", +] + +linters = [ + "ruff>=0.11.5,<1.0.0", + "pre-commit>=3.2.0,<5.0", + "mypy>=1.16.0,<2.0", + "types-deprecated>=1.2.9.2,<2.0", + "types-python-dateutil>=2.8.19.13,<3.0", + "types-PyYAML>=5.4.3,<7.0.0", + "types-termcolor>=0.1.1,<1.0", + "types-colorama>=0.4.15.20240311,<1.0", +] + +documentation = ["mkdocs>=1.4.2,<2.0", "mkdocs-material>=9.1.6,<10.0"] + +script = [ + # for scripts/gen_cli_help_screenshots.py + "rich>=13.7.1,<14.0", +] + [build-system] -requires = ["poetry-core>=2.0"] +requires = ["poetry-core>=2.2"] build-backend = "poetry.core.masonry.api" @@ -107,38 +137,6 @@ packages = [{ include = "commitizen" }, { include = "commitizen/py.typed" }] [tool.poetry.requires-plugins] "poethepoet" = ">=0.32.2" -[tool.poetry.group.dev.dependencies] -ipython = "^8.0" -tox = ">4" -poethepoet = "^0.34.0" - -[tool.poetry.group.test.dependencies] -pytest = ">=7.2,<9.0" -pytest-cov = ">=4,<7" -pytest-mock = "^3.10" -pytest-regressions = "^2.4.0" -pytest-freezer = "^0.4.6" -pytest-xdist = "^3.1.0" - -[tool.poetry.group.linters.dependencies] -ruff = "^0.11.5" -pre-commit = ">=3.2.0,<5.0" -mypy = "^1.16.0" -types-deprecated = "^1.2.9.2" -types-python-dateutil = "^2.8.19.13" -types-PyYAML = ">=5.4.3,<7.0.0" -types-termcolor = "^0.1.1" -types-colorama = "^0.4.15.20240311" - -[tool.poetry.group.documentation.dependencies] -mkdocs = "^1.4.2" -mkdocs-material = "^9.1.6" - -[tool.poetry.group.script.dependencies] -# for scripts/gen_cli_help_screenshots.py -rich = "^13.7.1" - - [tool.coverage] [tool.coverage.report] show_missing = true From fbee9418c58d566c431b4b1f4851c8305cbbf231 Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Sun, 16 Nov 2025 10:21:13 +0800 Subject: [PATCH 102/221] build(dev-dependencies): relax upper bound of dev dependencies Unless something is breaking. Wee could use the latest version of our dev dependencies for enhanced stability and features --- poetry.lock | 1281 +++++++++++++++++++++++++++--------------------- pyproject.toml | 34 +- 2 files changed, 727 insertions(+), 588 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4a60b32da5..80051bf4de 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "argcomplete" -version = "3.6.2" +version = "3.6.3" description = "Bash tab completion for argparse" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591"}, - {file = "argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf"}, + {file = "argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce"}, + {file = "argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c"}, ] [package.extras] @@ -17,19 +17,19 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] [[package]] name = "asttokens" -version = "3.0.0" +version = "3.0.1" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, - {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, + {file = "asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"}, + {file = "asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"}, ] [package.extras] -astroid = ["astroid (>=2,<4)"] -test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] +astroid = ["astroid (>=2,<5)"] +test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] [[package]] name = "babel" @@ -48,19 +48,19 @@ dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)" [[package]] name = "backrefs" -version = "5.9" +version = "6.1" description = "A wrapper around re and regex that adds additional back references." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f"}, - {file = "backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf"}, - {file = "backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa"}, - {file = "backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b"}, - {file = "backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9"}, - {file = "backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60"}, - {file = "backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59"}, + {file = "backrefs-6.1-py310-none-any.whl", hash = "sha256:2a2ccb96302337ce61ee4717ceacfbf26ba4efb1d55af86564b8bbaeda39cac1"}, + {file = "backrefs-6.1-py311-none-any.whl", hash = "sha256:e82bba3875ee4430f4de4b6db19429a27275d95a5f3773c57e9e18abc23fd2b7"}, + {file = "backrefs-6.1-py312-none-any.whl", hash = "sha256:c64698c8d2269343d88947c0735cb4b78745bd3ba590e10313fbf3f78c34da5a"}, + {file = "backrefs-6.1-py313-none-any.whl", hash = "sha256:4c9d3dc1e2e558965202c012304f33d4e0e477e1c103663fd2c3cc9bb18b0d05"}, + {file = "backrefs-6.1-py314-none-any.whl", hash = "sha256:13eafbc9ccd5222e9c1f0bec563e6d2a6d21514962f11e7fc79872fd56cbc853"}, + {file = "backrefs-6.1-py39-none-any.whl", hash = "sha256:a9e99b8a4867852cad177a6430e31b0f6e495d65f8c6c134b68c14c3c95bf4b0"}, + {file = "backrefs-6.1.tar.gz", hash = "sha256:3bba1749aafe1db9b915f00e0dd166cba613b6f788ffd63060ac3485dc9be231"}, ] [package.extras] @@ -68,26 +68,26 @@ extras = ["regex"] [[package]] name = "cachetools" -version = "6.2.0" +version = "6.2.2" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "cachetools-6.2.0-py3-none-any.whl", hash = "sha256:1c76a8960c0041fcc21097e357f882197c79da0dbff766e7317890a65d7d8ba6"}, - {file = "cachetools-6.2.0.tar.gz", hash = "sha256:38b328c0889450f05f5e120f56ab68c8abaf424e1275522b138ffc93253f7e32"}, + {file = "cachetools-6.2.2-py3-none-any.whl", hash = "sha256:6c09c98183bf58560c97b2abfcedcbaf6a896a490f534b031b661d3723b45ace"}, + {file = "cachetools-6.2.2.tar.gz", hash = "sha256:8e6d266b25e539df852251cfd6f990b4bc3a141db73b939058d809ebd2590fc6"}, ] [[package]] name = "certifi" -version = "2025.8.3" +version = "2025.11.12" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["documentation"] files = [ - {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, - {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, + {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, + {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, ] [[package]] @@ -116,91 +116,125 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.4.3" +version = "3.4.4" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["main", "documentation"] files = [ - {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, - {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, - {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d"}, + {file = "charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14"}, + {file = "charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c"}, + {file = "charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-win32.whl", hash = "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa"}, + {file = "charset_normalizer-3.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966"}, + {file = "charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50"}, + {file = "charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f"}, + {file = "charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a"}, ] [[package]] @@ -232,100 +266,116 @@ files = [ [[package]] name = "coverage" -version = "7.10.6" +version = "7.10.7" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356"}, - {file = "coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301"}, - {file = "coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460"}, - {file = "coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd"}, - {file = "coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb"}, - {file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6"}, - {file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945"}, - {file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e"}, - {file = "coverage-7.10.6-cp310-cp310-win32.whl", hash = "sha256:86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1"}, - {file = "coverage-7.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528"}, - {file = "coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f"}, - {file = "coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc"}, - {file = "coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a"}, - {file = "coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a"}, - {file = "coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62"}, - {file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153"}, - {file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5"}, - {file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619"}, - {file = "coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba"}, - {file = "coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e"}, - {file = "coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c"}, - {file = "coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea"}, - {file = "coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634"}, - {file = "coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6"}, - {file = "coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9"}, - {file = "coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c"}, - {file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a"}, - {file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5"}, - {file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972"}, - {file = "coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d"}, - {file = "coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629"}, - {file = "coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80"}, - {file = "coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6"}, - {file = "coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80"}, - {file = "coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003"}, - {file = "coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27"}, - {file = "coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4"}, - {file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d"}, - {file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc"}, - {file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc"}, - {file = "coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e"}, - {file = "coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32"}, - {file = "coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2"}, - {file = "coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b"}, - {file = "coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393"}, - {file = "coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27"}, - {file = "coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df"}, - {file = "coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb"}, - {file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282"}, - {file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4"}, - {file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21"}, - {file = "coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0"}, - {file = "coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5"}, - {file = "coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b"}, - {file = "coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e"}, - {file = "coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb"}, - {file = "coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034"}, - {file = "coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1"}, - {file = "coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a"}, - {file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb"}, - {file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d"}, - {file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747"}, - {file = "coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5"}, - {file = "coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713"}, - {file = "coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32"}, - {file = "coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65"}, - {file = "coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6"}, - {file = "coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0"}, - {file = "coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e"}, - {file = "coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5"}, - {file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7"}, - {file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5"}, - {file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0"}, - {file = "coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7"}, - {file = "coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930"}, - {file = "coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b"}, - {file = "coverage-7.10.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90558c35af64971d65fbd935c32010f9a2f52776103a259f1dee865fe8259352"}, - {file = "coverage-7.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8953746d371e5695405806c46d705a3cd170b9cc2b9f93953ad838f6c1e58612"}, - {file = "coverage-7.10.6-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c83f6afb480eae0313114297d29d7c295670a41c11b274e6bca0c64540c1ce7b"}, - {file = "coverage-7.10.6-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7eb68d356ba0cc158ca535ce1381dbf2037fa8cb5b1ae5ddfc302e7317d04144"}, - {file = "coverage-7.10.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b15a87265e96307482746d86995f4bff282f14b027db75469c446da6127433b"}, - {file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fc53ba868875bfbb66ee447d64d6413c2db91fddcfca57025a0e7ab5b07d5862"}, - {file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efeda443000aa23f276f4df973cb82beca682fd800bb119d19e80504ffe53ec2"}, - {file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9702b59d582ff1e184945d8b501ffdd08d2cee38d93a2206aa5f1365ce0b8d78"}, - {file = "coverage-7.10.6-cp39-cp39-win32.whl", hash = "sha256:2195f8e16ba1a44651ca684db2ea2b2d4b5345da12f07d9c22a395202a05b23c"}, - {file = "coverage-7.10.6-cp39-cp39-win_amd64.whl", hash = "sha256:f32ff80e7ef6a5b5b606ea69a36e97b219cd9dc799bcf2963018a4d8f788cfbf"}, - {file = "coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3"}, - {file = "coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90"}, + {file = "coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a"}, + {file = "coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87"}, + {file = "coverage-7.10.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0"}, + {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13"}, + {file = "coverage-7.10.7-cp310-cp310-win32.whl", hash = "sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b"}, + {file = "coverage-7.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807"}, + {file = "coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59"}, + {file = "coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e"}, + {file = "coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2"}, + {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61"}, + {file = "coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14"}, + {file = "coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2"}, + {file = "coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a"}, + {file = "coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417"}, + {file = "coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6"}, + {file = "coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb"}, + {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1"}, + {file = "coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256"}, + {file = "coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba"}, + {file = "coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf"}, + {file = "coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d"}, + {file = "coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49"}, + {file = "coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c"}, + {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f"}, + {file = "coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698"}, + {file = "coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843"}, + {file = "coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546"}, + {file = "coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c"}, + {file = "coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0"}, + {file = "coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999"}, + {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2"}, + {file = "coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a"}, + {file = "coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb"}, + {file = "coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb"}, + {file = "coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520"}, + {file = "coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360"}, + {file = "coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e"}, + {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd"}, + {file = "coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2"}, + {file = "coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681"}, + {file = "coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880"}, + {file = "coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63"}, + {file = "coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699"}, + {file = "coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0"}, + {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399"}, + {file = "coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235"}, + {file = "coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d"}, + {file = "coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a"}, + {file = "coverage-7.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3"}, + {file = "coverage-7.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594"}, + {file = "coverage-7.10.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0"}, + {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f"}, + {file = "coverage-7.10.7-cp39-cp39-win32.whl", hash = "sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431"}, + {file = "coverage-7.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07"}, + {file = "coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260"}, + {file = "coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239"}, ] [package.dependencies] @@ -360,18 +410,18 @@ files = [ [[package]] name = "deprecated" -version = "1.2.18" +version = "1.3.1" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" groups = ["main"] files = [ - {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"}, - {file = "deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"}, + {file = "deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f"}, + {file = "deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223"}, ] [package.dependencies] -wrapt = ">=1.10,<2" +wrapt = ">=1.10,<3" [package.extras] dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version >= \"3.12\"", "tox"] @@ -409,14 +459,14 @@ test = ["pytest (>=6)"] [[package]] name = "execnet" -version = "2.1.1" +version = "2.1.2" description = "execnet: rapid multi-Python deployment" optional = false python-versions = ">=3.8" groups = ["test"] files = [ - {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, - {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, + {file = "execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec"}, + {file = "execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd"}, ] [package.extras] @@ -424,14 +474,14 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] [[package]] name = "executing" -version = "2.2.0" +version = "2.2.1" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, - {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, + {file = "executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017"}, + {file = "executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4"}, ] [package.extras] @@ -484,14 +534,14 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "identify" -version = "2.6.13" +version = "2.6.15" description = "File identification library for Python" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b"}, - {file = "identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32"}, + {file = "identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757"}, + {file = "identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf"}, ] [package.extras] @@ -499,14 +549,14 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.10" +version = "3.11" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" groups = ["documentation"] files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, + {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, + {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, ] [package.extras] @@ -627,14 +677,14 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "markdown" -version = "3.8.2" +version = "3.9" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "markdown-3.8.2-py3-none-any.whl", hash = "sha256:5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24"}, - {file = "markdown-3.8.2.tar.gz", hash = "sha256:247b9a70dd12e27f67431ce62523e675b866d254f900c4fe75ce3dda62237c45"}, + {file = "markdown-3.9-py3-none-any.whl", hash = "sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280"}, + {file = "markdown-3.9.tar.gz", hash = "sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a"}, ] [package.dependencies] @@ -671,90 +721,121 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "3.0.2" +version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" groups = ["main", "documentation"] files = [ - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, + {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, + {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, + {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, + {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, + {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, + {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, + {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] [[package]] name = "matplotlib-inline" -version = "0.1.7" +version = "0.2.1" description = "Inline Matplotlib backend for Jupyter" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, - {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, + {file = "matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76"}, + {file = "matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe"}, ] [package.dependencies] traitlets = "*" +[package.extras] +test = ["flake8", "nbdime", "nbval", "notebook", "pytest"] + [[package]] name = "mdurl" version = "0.1.2" @@ -831,33 +912,32 @@ pyyaml = ">=5.1" [[package]] name = "mkdocs-material" -version = "9.6.18" +version = "9.7.0" description = "Documentation that simply works" optional = false python-versions = ">=3.8" groups = ["documentation"] files = [ - {file = "mkdocs_material-9.6.18-py3-none-any.whl", hash = "sha256:dbc1e146a0ecce951a4d84f97b816a54936cdc9e1edd1667fc6868878ac06701"}, - {file = "mkdocs_material-9.6.18.tar.gz", hash = "sha256:a2eb253bcc8b66f8c6eaf8379c10ed6e9644090c2e2e9d0971c7722dc7211c05"}, + {file = "mkdocs_material-9.7.0-py3-none-any.whl", hash = "sha256:da2866ea53601125ff5baa8aa06404c6e07af3c5ce3d5de95e3b52b80b442887"}, + {file = "mkdocs_material-9.7.0.tar.gz", hash = "sha256:602b359844e906ee402b7ed9640340cf8a474420d02d8891451733b6b02314ec"}, ] [package.dependencies] -babel = ">=2.10,<3.0" -backrefs = ">=5.7.post1,<6.0" -click = "<8.2.2" -colorama = ">=0.4,<1.0" -jinja2 = ">=3.1,<4.0" -markdown = ">=3.2,<4.0" -mkdocs = ">=1.6,<2.0" -mkdocs-material-extensions = ">=1.3,<2.0" -paginate = ">=0.5,<1.0" -pygments = ">=2.16,<3.0" -pymdown-extensions = ">=10.2,<11.0" -requests = ">=2.26,<3.0" +babel = ">=2.10" +backrefs = ">=5.7.post1" +colorama = ">=0.4" +jinja2 = ">=3.1" +markdown = ">=3.2" +mkdocs = ">=1.6" +mkdocs-material-extensions = ">=1.3" +paginate = ">=0.5" +pygments = ">=2.16" +pymdown-extensions = ">=10.2" +requests = ">=2.26" [package.extras] git = ["mkdocs-git-committers-plugin-2 (>=1.1,<3)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] -imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] +imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<12.0)"] recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] [[package]] @@ -874,50 +954,50 @@ files = [ [[package]] name = "mypy" -version = "1.17.1" +version = "1.18.2" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972"}, - {file = "mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7"}, - {file = "mypy-1.17.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df"}, - {file = "mypy-1.17.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390"}, - {file = "mypy-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94"}, - {file = "mypy-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b"}, - {file = "mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58"}, - {file = "mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5"}, - {file = "mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd"}, - {file = "mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b"}, - {file = "mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5"}, - {file = "mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b"}, - {file = "mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb"}, - {file = "mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403"}, - {file = "mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056"}, - {file = "mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341"}, - {file = "mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb"}, - {file = "mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19"}, - {file = "mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7"}, - {file = "mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81"}, - {file = "mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6"}, - {file = "mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849"}, - {file = "mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14"}, - {file = "mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a"}, - {file = "mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733"}, - {file = "mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd"}, - {file = "mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0"}, - {file = "mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a"}, - {file = "mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91"}, - {file = "mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed"}, - {file = "mypy-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9"}, - {file = "mypy-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99"}, - {file = "mypy-1.17.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8"}, - {file = "mypy-1.17.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8"}, - {file = "mypy-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259"}, - {file = "mypy-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d"}, - {file = "mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9"}, - {file = "mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01"}, + {file = "mypy-1.18.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eab0cf6294dafe397c261a75f96dc2c31bffe3b944faa24db5def4e2b0f77c"}, + {file = "mypy-1.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a780ca61fc239e4865968ebc5240bb3bf610ef59ac398de9a7421b54e4a207e"}, + {file = "mypy-1.18.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448acd386266989ef11662ce3c8011fd2a7b632e0ec7d61a98edd8e27472225b"}, + {file = "mypy-1.18.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9e171c465ad3901dc652643ee4bffa8e9fef4d7d0eece23b428908c77a76a66"}, + {file = "mypy-1.18.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:592ec214750bc00741af1f80cbf96b5013d81486b7bb24cb052382c19e40b428"}, + {file = "mypy-1.18.2-cp310-cp310-win_amd64.whl", hash = "sha256:7fb95f97199ea11769ebe3638c29b550b5221e997c63b14ef93d2e971606ebed"}, + {file = "mypy-1.18.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:807d9315ab9d464125aa9fcf6d84fde6e1dc67da0b6f80e7405506b8ac72bc7f"}, + {file = "mypy-1.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:776bb00de1778caf4db739c6e83919c1d85a448f71979b6a0edd774ea8399341"}, + {file = "mypy-1.18.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1379451880512ffce14505493bd9fe469e0697543717298242574882cf8cdb8d"}, + {file = "mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1331eb7fd110d60c24999893320967594ff84c38ac6d19e0a76c5fd809a84c86"}, + {file = "mypy-1.18.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ca30b50a51e7ba93b00422e486cbb124f1c56a535e20eff7b2d6ab72b3b2e37"}, + {file = "mypy-1.18.2-cp311-cp311-win_amd64.whl", hash = "sha256:664dc726e67fa54e14536f6e1224bcfce1d9e5ac02426d2326e2bb4e081d1ce8"}, + {file = "mypy-1.18.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:33eca32dd124b29400c31d7cf784e795b050ace0e1f91b8dc035672725617e34"}, + {file = "mypy-1.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3c47adf30d65e89b2dcd2fa32f3aeb5e94ca970d2c15fcb25e297871c8e4764"}, + {file = "mypy-1.18.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d6c838e831a062f5f29d11c9057c6009f60cb294fea33a98422688181fe2893"}, + {file = "mypy-1.18.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01199871b6110a2ce984bde85acd481232d17413868c9807e95c1b0739a58914"}, + {file = "mypy-1.18.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a2afc0fa0b0e91b4599ddfe0f91e2c26c2b5a5ab263737e998d6817874c5f7c8"}, + {file = "mypy-1.18.2-cp312-cp312-win_amd64.whl", hash = "sha256:d8068d0afe682c7c4897c0f7ce84ea77f6de953262b12d07038f4d296d547074"}, + {file = "mypy-1.18.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:07b8b0f580ca6d289e69209ec9d3911b4a26e5abfde32228a288eb79df129fcc"}, + {file = "mypy-1.18.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ed4482847168439651d3feee5833ccedbf6657e964572706a2adb1f7fa4dfe2e"}, + {file = "mypy-1.18.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3ad2afadd1e9fea5cf99a45a822346971ede8685cc581ed9cd4d42eaf940986"}, + {file = "mypy-1.18.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a431a6f1ef14cf8c144c6b14793a23ec4eae3db28277c358136e79d7d062f62d"}, + {file = "mypy-1.18.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7ab28cc197f1dd77a67e1c6f35cd1f8e8b73ed2217e4fc005f9e6a504e46e7ba"}, + {file = "mypy-1.18.2-cp313-cp313-win_amd64.whl", hash = "sha256:0e2785a84b34a72ba55fb5daf079a1003a34c05b22238da94fcae2bbe46f3544"}, + {file = "mypy-1.18.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:62f0e1e988ad41c2a110edde6c398383a889d95b36b3e60bcf155f5164c4fdce"}, + {file = "mypy-1.18.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8795a039bab805ff0c1dfdb8cd3344642c2b99b8e439d057aba30850b8d3423d"}, + {file = "mypy-1.18.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ca1e64b24a700ab5ce10133f7ccd956a04715463d30498e64ea8715236f9c9c"}, + {file = "mypy-1.18.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d924eef3795cc89fecf6bedc6ed32b33ac13e8321344f6ddbf8ee89f706c05cb"}, + {file = "mypy-1.18.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20c02215a080e3a2be3aa50506c67242df1c151eaba0dcbc1e4e557922a26075"}, + {file = "mypy-1.18.2-cp314-cp314-win_amd64.whl", hash = "sha256:749b5f83198f1ca64345603118a6f01a4e99ad4bf9d103ddc5a3200cc4614adf"}, + {file = "mypy-1.18.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25a9c8fb67b00599f839cf472713f54249a62efd53a54b565eb61956a7e3296b"}, + {file = "mypy-1.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2b9c7e284ee20e7598d6f42e13ca40b4928e6957ed6813d1ab6348aa3f47133"}, + {file = "mypy-1.18.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6985ed057513e344e43a26cc1cd815c7a94602fb6a3130a34798625bc2f07b6"}, + {file = "mypy-1.18.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f27105f1525ec024b5c630c0b9f36d5c1cc4d447d61fe51ff4bd60633f47ac"}, + {file = "mypy-1.18.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:030c52d0ea8144e721e49b1f68391e39553d7451f0c3f8a7565b59e19fcb608b"}, + {file = "mypy-1.18.2-cp39-cp39-win_amd64.whl", hash = "sha256:aa5e07ac1a60a253445797e42b8b2963c9675563a94f11291ab40718b016a7a0"}, + {file = "mypy-1.18.2-py3-none-any.whl", hash = "sha256:22a1748707dd62b58d2ae53562ffc4d7f8bcc727e8ac7cbc69c053ddc874d47e"}, + {file = "mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b"}, ] [package.dependencies] @@ -1076,14 +1156,14 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "poethepoet" -version = "0.34.0" -description = "A task runner that works well with poetry." +version = "0.37.0" +description = "A task runner that works well with poetry and uv." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "poethepoet-0.34.0-py3-none-any.whl", hash = "sha256:c472d6f0fdb341b48d346f4ccd49779840c15b30dfd6bc6347a80d6274b5e34e"}, - {file = "poethepoet-0.34.0.tar.gz", hash = "sha256:86203acce555bbfe45cb6ccac61ba8b16a5784264484195874da457ddabf5850"}, + {file = "poethepoet-0.37.0-py3-none-any.whl", hash = "sha256:861790276315abcc8df1b4bd60e28c3d48a06db273edd3092f3c94e1a46e5e22"}, + {file = "poethepoet-0.37.0.tar.gz", hash = "sha256:73edf458707c674a079baa46802e21455bda3a7f82a408e58c31b9f4fe8e933d"}, ] [package.dependencies] @@ -1173,14 +1253,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.16.1" +version = "10.17.1" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "pymdown_extensions-10.16.1-py3-none-any.whl", hash = "sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d"}, - {file = "pymdown_extensions-10.16.1.tar.gz", hash = "sha256:aace82bcccba3efc03e25d584e6a22d27a8e17caa3f4dd9f207e49b787aa9a91"}, + {file = "pymdown_extensions-10.17.1-py3-none-any.whl", hash = "sha256:1f160209c82eecbb5d8a0d8f89a4d9bd6bdcbde9a8537761844cfc57ad5cd8a6"}, + {file = "pymdown_extensions-10.17.1.tar.gz", hash = "sha256:60d05fe55e7fb5a1e4740fc575facad20dc6ee3a748e8d3d36ba44142e75ce03"}, ] [package.dependencies] @@ -1212,14 +1292,14 @@ testing = ["covdefaults (>=2.3)", "pytest (>=8.3.5)", "pytest-cov (>=6.1.1)", "p [[package]] name = "pytest" -version = "8.4.1" +version = "8.4.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, - {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, + {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, + {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, ] [package.dependencies] @@ -1236,23 +1316,23 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests [[package]] name = "pytest-cov" -version = "6.2.1" +version = "7.0.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, - {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, + {file = "pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861"}, + {file = "pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1"}, ] [package.dependencies] -coverage = {version = ">=7.5", extras = ["toml"]} +coverage = {version = ">=7.10.6", extras = ["toml"]} pluggy = ">=1.2" -pytest = ">=6.2.5" +pytest = ">=7" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] +testing = ["process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-datadir" @@ -1291,14 +1371,14 @@ pytest = ">=3.6" [[package]] name = "pytest-mock" -version = "3.14.1" +version = "3.15.1" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0"}, - {file = "pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e"}, + {file = "pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d"}, + {file = "pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f"}, ] [package.dependencies] @@ -1309,14 +1389,14 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "pytest-regressions" -version = "2.8.2" +version = "2.8.3" description = "Easy to use fixtures to write regression tests." optional = false python-versions = ">=3.9" groups = ["test"] files = [ - {file = "pytest_regressions-2.8.2-py3-none-any.whl", hash = "sha256:a0804c1ce66d8e4d9a3c7c68f42a3d436182edca8e86565c232caeaf9e080fc2"}, - {file = "pytest_regressions-2.8.2.tar.gz", hash = "sha256:1d8f4767be58b9994bfa7d60271099469ad32b8ca9f9d9ceca1c1d6827156b19"}, + {file = "pytest_regressions-2.8.3-py3-none-any.whl", hash = "sha256:72500dd95bde418c850f290a3108dacb56427067f364f7112cb5b16f6d6cc29c"}, + {file = "pytest_regressions-2.8.3.tar.gz", hash = "sha256:1ad90708bee02a3d36c78ef0b6f9692a9a30d312dd828680fd6d2a7235fcd221"}, ] [package.dependencies] @@ -1368,65 +1448,85 @@ six = ">=1.5" [[package]] name = "pyyaml" -version = "6.0.2" +version = "6.0.3" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" groups = ["main", "dev", "documentation", "linters", "test"] files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, + {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, + {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, + {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, + {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, + {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, + {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b"}, + {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0"}, + {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69"}, + {file = "pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e"}, + {file = "pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, + {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, + {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, + {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, + {file = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}, + {file = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}, + {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}, + {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}, + {file = "pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}, + {file = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}, + {file = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}, + {file = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}, + {file = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}, + {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}, + {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}, + {file = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}, + {file = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}, + {file = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}, + {file = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}, + {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}, + {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}, + {file = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}, + {file = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}, + {file = "pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da"}, + {file = "pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a"}, + {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926"}, + {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7"}, + {file = "pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0"}, + {file = "pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007"}, + {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] [[package]] @@ -1483,50 +1583,50 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.9.4" +version = "14.2.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" groups = ["script"] files = [ - {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, - {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, + {file = "rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd"}, + {file = "rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4"}, ] [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.11.13" +version = "0.14.5" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["linters"] files = [ - {file = "ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46"}, - {file = "ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48"}, - {file = "ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492"}, - {file = "ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250"}, - {file = "ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3"}, - {file = "ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b"}, - {file = "ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514"}, + {file = "ruff-0.14.5-py3-none-linux_armv6l.whl", hash = "sha256:f3b8248123b586de44a8018bcc9fefe31d23dda57a34e6f0e1e53bd51fd63594"}, + {file = "ruff-0.14.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f7a75236570318c7a30edd7f5491945f0169de738d945ca8784500b517163a72"}, + {file = "ruff-0.14.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6d146132d1ee115f8802356a2dc9a634dbf58184c51bff21f313e8cd1c74899a"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2380596653dcd20b057794d55681571a257a42327da8894b93bbd6111aa801f"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d1fa985a42b1f075a098fa1ab9d472b712bdb17ad87a8ec86e45e7fa6273e68"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88f0770d42b7fa02bbefddde15d235ca3aa24e2f0137388cc15b2dcbb1f7c7a7"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3676cb02b9061fee7294661071c4709fa21419ea9176087cb77e64410926eb78"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b595bedf6bc9cab647c4a173a61acf4f1ac5f2b545203ba82f30fcb10b0318fb"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f55382725ad0bdb2e8ee2babcbbfb16f124f5a59496a2f6a46f1d9d99d93e6e2"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7497d19dce23976bdaca24345ae131a1d38dcfe1b0850ad8e9e6e4fa321a6e19"}, + {file = "ruff-0.14.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:410e781f1122d6be4f446981dd479470af86537fb0b8857f27a6e872f65a38e4"}, + {file = "ruff-0.14.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c01be527ef4c91a6d55e53b337bfe2c0f82af024cc1a33c44792d6844e2331e1"}, + {file = "ruff-0.14.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f66e9bb762e68d66e48550b59c74314168ebb46199886c5c5aa0b0fbcc81b151"}, + {file = "ruff-0.14.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d93be8f1fa01022337f1f8f3bcaa7ffee2d0b03f00922c45c2207954f351f465"}, + {file = "ruff-0.14.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:c135d4b681f7401fe0e7312017e41aba9b3160861105726b76cfa14bc25aa367"}, + {file = "ruff-0.14.5-py3-none-win32.whl", hash = "sha256:c83642e6fccfb6dea8b785eb9f456800dcd6a63f362238af5fc0c83d027dd08b"}, + {file = "ruff-0.14.5-py3-none-win_amd64.whl", hash = "sha256:9d55d7af7166f143c94eae1db3312f9ea8f95a4defef1979ed516dbb38c27621"}, + {file = "ruff-0.14.5-py3-none-win_arm64.whl", hash = "sha256:4b700459d4649e2594b31f20a9de33bc7c19976d4746d8d0798ad959621d64a4"}, + {file = "ruff-0.14.5.tar.gz", hash = "sha256:8d3b48d7d8aad423d3137af7ab6c8b1e38e4de104800f0d596990f6ada1a9fc1"}, ] [[package]] @@ -1578,44 +1678,54 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "tomli" -version = "2.2.1" +version = "2.3.0" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" groups = ["dev", "linters", "test"] files = [ - {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, - {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, - {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, - {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, - {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, - {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, - {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, - {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, - {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, - {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, + {file = "tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45"}, + {file = "tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba"}, + {file = "tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf"}, + {file = "tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441"}, + {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845"}, + {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c"}, + {file = "tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456"}, + {file = "tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be"}, + {file = "tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac"}, + {file = "tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22"}, + {file = "tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f"}, + {file = "tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52"}, + {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8"}, + {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6"}, + {file = "tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876"}, + {file = "tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878"}, + {file = "tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b"}, + {file = "tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae"}, + {file = "tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b"}, + {file = "tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf"}, + {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f"}, + {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05"}, + {file = "tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606"}, + {file = "tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999"}, + {file = "tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e"}, + {file = "tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3"}, + {file = "tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc"}, + {file = "tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0"}, + {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879"}, + {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005"}, + {file = "tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463"}, + {file = "tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8"}, + {file = "tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77"}, + {file = "tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf"}, + {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530"}, + {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b"}, + {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67"}, + {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f"}, + {file = "tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0"}, + {file = "tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba"}, + {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"}, + {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, ] markers = {dev = "python_version < \"3.11\"", linters = "python_version < \"3.11\"", test = "python_full_version <= \"3.11.0a6\""} @@ -1633,14 +1743,14 @@ files = [ [[package]] name = "tox" -version = "4.29.0" +version = "4.30.3" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tox-4.29.0-py3-none-any.whl", hash = "sha256:b914f134176cea74c5e01c29cb4befc8afa4cd38b356c3756eff85832d27b5c0"}, - {file = "tox-4.29.0.tar.gz", hash = "sha256:7b3a2bb43974285110eee35a859f2b3f2e87a24f6e1011d83f466b7c75835bd2"}, + {file = "tox-4.30.3-py3-none-any.whl", hash = "sha256:a9f17b4b2d0f74fe0d76207236925a119095011e5c2e661a133115a8061178c9"}, + {file = "tox-4.30.3.tar.gz", hash = "sha256:f3dd0735f1cd4e8fbea5a3661b77f517456b5f0031a6256432533900e34b90bf"}, ] [package.dependencies] @@ -1686,50 +1796,50 @@ files = [ [[package]] name = "types-deprecated" -version = "1.2.15.20250304" +version = "1.3.1.20251101" description = "Typing stubs for Deprecated" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "types_deprecated-1.2.15.20250304-py3-none-any.whl", hash = "sha256:86a65aa550ea8acf49f27e226b8953288cd851de887970fbbdf2239c116c3107"}, - {file = "types_deprecated-1.2.15.20250304.tar.gz", hash = "sha256:c329030553029de5cc6cb30f269c11f4e00e598c4241290179f63cda7d33f719"}, + {file = "types_deprecated-1.3.1.20251101-py3-none-any.whl", hash = "sha256:274edcc2a084d3fe31802d3c1379abd630716d3db34e40577e12ad84d6b73134"}, + {file = "types_deprecated-1.3.1.20251101.tar.gz", hash = "sha256:f002d266b73201f46ec6fc712c1f016067ec6cb44357559cdb50c86b010951a7"}, ] [[package]] name = "types-python-dateutil" -version = "2.9.0.20250822" +version = "2.9.0.20251115" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "types_python_dateutil-2.9.0.20250822-py3-none-any.whl", hash = "sha256:849d52b737e10a6dc6621d2bd7940ec7c65fcb69e6aa2882acf4e56b2b508ddc"}, - {file = "types_python_dateutil-2.9.0.20250822.tar.gz", hash = "sha256:84c92c34bd8e68b117bff742bc00b692a1e8531262d4507b33afcc9f7716cd53"}, + {file = "types_python_dateutil-2.9.0.20251115-py3-none-any.whl", hash = "sha256:9cf9c1c582019753b8639a081deefd7e044b9fa36bd8217f565c6c4e36ee0624"}, + {file = "types_python_dateutil-2.9.0.20251115.tar.gz", hash = "sha256:8a47f2c3920f52a994056b8786309b43143faa5a64d4cbb2722d6addabdf1a58"}, ] [[package]] name = "types-pyyaml" -version = "6.0.12.20250822" +version = "6.0.12.20250915" description = "Typing stubs for PyYAML" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "types_pyyaml-6.0.12.20250822-py3-none-any.whl", hash = "sha256:1fe1a5e146aa315483592d292b72a172b65b946a6d98aa6ddd8e4aa838ab7098"}, - {file = "types_pyyaml-6.0.12.20250822.tar.gz", hash = "sha256:259f1d93079d335730a9db7cff2bcaf65d7e04b4a56b5927d49a612199b59413"}, + {file = "types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6"}, + {file = "types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3"}, ] [[package]] name = "types-termcolor" -version = "0.1.1" +version = "1.1.6.2" description = "Typing stubs for termcolor" optional = false python-versions = "*" groups = ["linters"] files = [ - {file = "types-termcolor-0.1.1.tar.gz", hash = "sha256:4d9e09ce7f3267985f5280b22e25790c98cb64628b6466e1fb915dbb52ad7136"}, - {file = "types_termcolor-0.1.1-py2.py3-none-any.whl", hash = "sha256:3694c312e32f71fdc0f469c334ea21645f3130d90c93cd53bcb06b1233e174d5"}, + {file = "types-termcolor-1.1.6.2.tar.gz", hash = "sha256:d8f0f69cf5552cc59ce75aa5172937cec9b320c17453adefe4168b93d16daad6"}, + {file = "types_termcolor-1.1.6.2-py3-none-any.whl", hash = "sha256:44c4c762c54a90d99b5c1033ef008aaa5610056d31d5c66b9288a942682a64d7"}, ] [[package]] @@ -1738,12 +1848,12 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" -groups = ["main", "dev", "linters", "script", "test"] +groups = ["main", "dev", "linters", "test"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] -markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"", script = "python_version < \"3.11\"", test = "python_version < \"3.11\""} +markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"", test = "python_version < \"3.11\""} [[package]] name = "urllib3" @@ -1765,14 +1875,14 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.34.0" +version = "20.35.4" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" groups = ["dev", "linters"] files = [ - {file = "virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026"}, - {file = "virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a"}, + {file = "virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b"}, + {file = "virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c"}, ] [package.dependencies] @@ -1830,107 +1940,136 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "wcwidth" -version = "0.2.13" +version = "0.2.14" description = "Measures the displayed width of unicode strings in a terminal" optional = false -python-versions = "*" +python-versions = ">=3.6" groups = ["main", "dev"] files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, + {file = "wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1"}, + {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"}, ] [[package]] name = "wrapt" -version = "1.17.3" +version = "2.0.1" description = "Module for decorators, wrappers and monkey patching." optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"}, - {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"}, - {file = "wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"}, - {file = "wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775"}, - {file = "wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd"}, - {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05"}, - {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418"}, - {file = "wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390"}, - {file = "wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6"}, - {file = "wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18"}, - {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7"}, - {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85"}, - {file = "wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f"}, - {file = "wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311"}, - {file = "wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1"}, - {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5"}, - {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2"}, - {file = "wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89"}, - {file = "wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77"}, - {file = "wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a"}, - {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"}, - {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"}, - {file = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"}, - {file = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"}, - {file = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"}, - {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"}, - {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"}, - {file = "wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"}, - {file = "wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"}, - {file = "wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"}, - {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"}, - {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"}, - {file = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"}, - {file = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"}, - {file = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"}, - {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"}, - {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"}, - {file = "wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"}, - {file = "wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"}, - {file = "wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"}, - {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"}, - {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"}, - {file = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"}, - {file = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"}, - {file = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"}, - {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"}, - {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"}, - {file = "wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"}, - {file = "wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"}, - {file = "wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"}, - {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"}, - {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"}, - {file = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"}, - {file = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"}, - {file = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"}, - {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"}, - {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"}, - {file = "wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"}, - {file = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"}, - {file = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"}, - {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225"}, - {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a"}, - {file = "wrapt-1.17.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f"}, - {file = "wrapt-1.17.3-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00"}, - {file = "wrapt-1.17.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56"}, - {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5"}, - {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22"}, - {file = "wrapt-1.17.3-cp38-cp38-win32.whl", hash = "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c"}, - {file = "wrapt-1.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2"}, - {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc"}, - {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9"}, - {file = "wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d"}, - {file = "wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a"}, - {file = "wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139"}, - {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df"}, - {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b"}, - {file = "wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81"}, - {file = "wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f"}, - {file = "wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f"}, - {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, - {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, + {file = "wrapt-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:64b103acdaa53b7caf409e8d45d39a8442fe6dcfec6ba3f3d141e0cc2b5b4dbd"}, + {file = "wrapt-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91bcc576260a274b169c3098e9a3519fb01f2989f6d3d386ef9cbf8653de1374"}, + {file = "wrapt-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab594f346517010050126fcd822697b25a7031d815bb4fbc238ccbe568216489"}, + {file = "wrapt-2.0.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:36982b26f190f4d737f04a492a68accbfc6fa042c3f42326fdfbb6c5b7a20a31"}, + {file = "wrapt-2.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23097ed8bc4c93b7bf36fa2113c6c733c976316ce0ee2c816f64ca06102034ef"}, + {file = "wrapt-2.0.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8bacfe6e001749a3b64db47bcf0341da757c95959f592823a93931a422395013"}, + {file = "wrapt-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8ec3303e8a81932171f455f792f8df500fc1a09f20069e5c16bd7049ab4e8e38"}, + {file = "wrapt-2.0.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:3f373a4ab5dbc528a94334f9fe444395b23c2f5332adab9ff4ea82f5a9e33bc1"}, + {file = "wrapt-2.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f49027b0b9503bf6c8cdc297ca55006b80c2f5dd36cecc72c6835ab6e10e8a25"}, + {file = "wrapt-2.0.1-cp310-cp310-win32.whl", hash = "sha256:8330b42d769965e96e01fa14034b28a2a7600fbf7e8f0cc90ebb36d492c993e4"}, + {file = "wrapt-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:1218573502a8235bb8a7ecaed12736213b22dcde9feab115fa2989d42b5ded45"}, + {file = "wrapt-2.0.1-cp310-cp310-win_arm64.whl", hash = "sha256:eda8e4ecd662d48c28bb86be9e837c13e45c58b8300e43ba3c9b4fa9900302f7"}, + {file = "wrapt-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e17283f533a0d24d6e5429a7d11f250a58d28b4ae5186f8f47853e3e70d2590"}, + {file = "wrapt-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85df8d92158cb8f3965aecc27cf821461bb5f40b450b03facc5d9f0d4d6ddec6"}, + {file = "wrapt-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1be685ac7700c966b8610ccc63c3187a72e33cab53526a27b2a285a662cd4f7"}, + {file = "wrapt-2.0.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:df0b6d3b95932809c5b3fecc18fda0f1e07452d05e2662a0b35548985f256e28"}, + {file = "wrapt-2.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da7384b0e5d4cae05c97cd6f94faaf78cc8b0f791fc63af43436d98c4ab37bb"}, + {file = "wrapt-2.0.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ec65a78fbd9d6f083a15d7613b2800d5663dbb6bb96003899c834beaa68b242c"}, + {file = "wrapt-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7de3cc939be0e1174969f943f3b44e0d79b6f9a82198133a5b7fc6cc92882f16"}, + {file = "wrapt-2.0.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fb1a5b72cbd751813adc02ef01ada0b0d05d3dcbc32976ce189a1279d80ad4a2"}, + {file = "wrapt-2.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3fa272ca34332581e00bf7773e993d4f632594eb2d1b0b162a9038df0fd971dd"}, + {file = "wrapt-2.0.1-cp311-cp311-win32.whl", hash = "sha256:fc007fdf480c77301ab1afdbb6ab22a5deee8885f3b1ed7afcb7e5e84a0e27be"}, + {file = "wrapt-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:47434236c396d04875180171ee1f3815ca1eada05e24a1ee99546320d54d1d1b"}, + {file = "wrapt-2.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:837e31620e06b16030b1d126ed78e9383815cbac914693f54926d816d35d8edf"}, + {file = "wrapt-2.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1fdbb34da15450f2b1d735a0e969c24bdb8d8924892380126e2a293d9902078c"}, + {file = "wrapt-2.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d32794fe940b7000f0519904e247f902f0149edbe6316c710a8562fb6738841"}, + {file = "wrapt-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:386fb54d9cd903ee0012c09291336469eb7b244f7183d40dc3e86a16a4bace62"}, + {file = "wrapt-2.0.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7b219cb2182f230676308cdcacd428fa837987b89e4b7c5c9025088b8a6c9faf"}, + {file = "wrapt-2.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:641e94e789b5f6b4822bb8d8ebbdfc10f4e4eae7756d648b717d980f657a9eb9"}, + {file = "wrapt-2.0.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe21b118b9f58859b5ebaa4b130dee18669df4bd111daad082b7beb8799ad16b"}, + {file = "wrapt-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17fb85fa4abc26a5184d93b3efd2dcc14deb4b09edcdb3535a536ad34f0b4dba"}, + {file = "wrapt-2.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b89ef9223d665ab255ae42cc282d27d69704d94be0deffc8b9d919179a609684"}, + {file = "wrapt-2.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a453257f19c31b31ba593c30d997d6e5be39e3b5ad9148c2af5a7314061c63eb"}, + {file = "wrapt-2.0.1-cp312-cp312-win32.whl", hash = "sha256:3e271346f01e9c8b1130a6a3b0e11908049fe5be2d365a5f402778049147e7e9"}, + {file = "wrapt-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:2da620b31a90cdefa9cd0c2b661882329e2e19d1d7b9b920189956b76c564d75"}, + {file = "wrapt-2.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:aea9c7224c302bc8bfc892b908537f56c430802560e827b75ecbde81b604598b"}, + {file = "wrapt-2.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:47b0f8bafe90f7736151f61482c583c86b0693d80f075a58701dd1549b0010a9"}, + {file = "wrapt-2.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cbeb0971e13b4bd81d34169ed57a6dda017328d1a22b62fda45e1d21dd06148f"}, + {file = "wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218"}, + {file = "wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9"}, + {file = "wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c"}, + {file = "wrapt-2.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:98d873ed6c8b4ee2418f7afce666751854d6d03e3c0ec2a399bb039cd2ae89db"}, + {file = "wrapt-2.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9e850f5b7fc67af856ff054c71690d54fa940c3ef74209ad9f935b4f66a0233"}, + {file = "wrapt-2.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e505629359cb5f751e16e30cf3f91a1d3ddb4552480c205947da415d597f7ac2"}, + {file = "wrapt-2.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2879af909312d0baf35f08edeea918ee3af7ab57c37fe47cb6a373c9f2749c7b"}, + {file = "wrapt-2.0.1-cp313-cp313-win32.whl", hash = "sha256:d67956c676be5a24102c7407a71f4126d30de2a569a1c7871c9f3cabc94225d7"}, + {file = "wrapt-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9ca66b38dd642bf90c59b6738af8070747b610115a39af2498535f62b5cdc1c3"}, + {file = "wrapt-2.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:5a4939eae35db6b6cec8e7aa0e833dcca0acad8231672c26c2a9ab7a0f8ac9c8"}, + {file = "wrapt-2.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a52f93d95c8d38fed0669da2ebdb0b0376e895d84596a976c15a9eb45e3eccb3"}, + {file = "wrapt-2.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e54bbf554ee29fcceee24fa41c4d091398b911da6e7f5d7bffda963c9aed2e1"}, + {file = "wrapt-2.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:908f8c6c71557f4deaa280f55d0728c3bca0960e8c3dd5ceeeafb3c19942719d"}, + {file = "wrapt-2.0.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e2f84e9af2060e3904a32cea9bb6db23ce3f91cfd90c6b426757cf7cc01c45c7"}, + {file = "wrapt-2.0.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3612dc06b436968dfb9142c62e5dfa9eb5924f91120b3c8ff501ad878f90eb3"}, + {file = "wrapt-2.0.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d2d947d266d99a1477cd005b23cbd09465276e302515e122df56bb9511aca1b"}, + {file = "wrapt-2.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7d539241e87b650cbc4c3ac9f32c8d1ac8a54e510f6dca3f6ab60dcfd48c9b10"}, + {file = "wrapt-2.0.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4811e15d88ee62dbf5c77f2c3ff3932b1e3ac92323ba3912f51fc4016ce81ecf"}, + {file = "wrapt-2.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c1c91405fcf1d501fa5d55df21e58ea49e6b879ae829f1039faaf7e5e509b41e"}, + {file = "wrapt-2.0.1-cp313-cp313t-win32.whl", hash = "sha256:e76e3f91f864e89db8b8d2a8311d57df93f01ad6bb1e9b9976d1f2e83e18315c"}, + {file = "wrapt-2.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:83ce30937f0ba0d28818807b303a412440c4b63e39d3d8fc036a94764b728c92"}, + {file = "wrapt-2.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:4b55cacc57e1dc2d0991dbe74c6419ffd415fb66474a02335cb10efd1aa3f84f"}, + {file = "wrapt-2.0.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5e53b428f65ece6d9dad23cb87e64506392b720a0b45076c05354d27a13351a1"}, + {file = "wrapt-2.0.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ad3ee9d0f254851c71780966eb417ef8e72117155cff04821ab9b60549694a55"}, + {file = "wrapt-2.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7b822c61ed04ee6ad64bc90d13368ad6eb094db54883b5dde2182f67a7f22c0"}, + {file = "wrapt-2.0.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7164a55f5e83a9a0b031d3ffab4d4e36bbec42e7025db560f225489fa929e509"}, + {file = "wrapt-2.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e60690ba71a57424c8d9ff28f8d006b7ad7772c22a4af432188572cd7fa004a1"}, + {file = "wrapt-2.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3cd1a4bd9a7a619922a8557e1318232e7269b5fb69d4ba97b04d20450a6bf970"}, + {file = "wrapt-2.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b4c2e3d777e38e913b8ce3a6257af72fb608f86a1df471cb1d4339755d0a807c"}, + {file = "wrapt-2.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3d366aa598d69416b5afedf1faa539fac40c1d80a42f6b236c88c73a3c8f2d41"}, + {file = "wrapt-2.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c235095d6d090aa903f1db61f892fffb779c1eaeb2a50e566b52001f7a0f66ed"}, + {file = "wrapt-2.0.1-cp314-cp314-win32.whl", hash = "sha256:bfb5539005259f8127ea9c885bdc231978c06b7a980e63a8a61c8c4c979719d0"}, + {file = "wrapt-2.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:4ae879acc449caa9ed43fc36ba08392b9412ee67941748d31d94e3cedb36628c"}, + {file = "wrapt-2.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:8639b843c9efd84675f1e100ed9e99538ebea7297b62c4b45a7042edb84db03e"}, + {file = "wrapt-2.0.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:9219a1d946a9b32bb23ccae66bdb61e35c62773ce7ca6509ceea70f344656b7b"}, + {file = "wrapt-2.0.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fa4184e74197af3adad3c889a1af95b53bb0466bced92ea99a0c014e48323eec"}, + {file = "wrapt-2.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c5ef2f2b8a53b7caee2f797ef166a390fef73979b15778a4a153e4b5fedce8fa"}, + {file = "wrapt-2.0.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e042d653a4745be832d5aa190ff80ee4f02c34b21f4b785745eceacd0907b815"}, + {file = "wrapt-2.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2afa23318136709c4b23d87d543b425c399887b4057936cd20386d5b1422b6fa"}, + {file = "wrapt-2.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c72328f668cf4c503ffcf9434c2b71fdd624345ced7941bc6693e61bbe36bef"}, + {file = "wrapt-2.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3793ac154afb0e5b45d1233cb94d354ef7a983708cc3bb12563853b1d8d53747"}, + {file = "wrapt-2.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:fec0d993ecba3991645b4857837277469c8cc4c554a7e24d064d1ca291cfb81f"}, + {file = "wrapt-2.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:949520bccc1fa227274da7d03bf238be15389cd94e32e4297b92337df9b7a349"}, + {file = "wrapt-2.0.1-cp314-cp314t-win32.whl", hash = "sha256:be9e84e91d6497ba62594158d3d31ec0486c60055c49179edc51ee43d095f79c"}, + {file = "wrapt-2.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:61c4956171c7434634401db448371277d07032a81cc21c599c22953374781395"}, + {file = "wrapt-2.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:35cdbd478607036fee40273be8ed54a451f5f23121bd9d4be515158f9498f7ad"}, + {file = "wrapt-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:90897ea1cf0679763b62e79657958cd54eae5659f6360fc7d2ccc6f906342183"}, + {file = "wrapt-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:50844efc8cdf63b2d90cd3d62d4947a28311e6266ce5235a219d21b195b4ec2c"}, + {file = "wrapt-2.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49989061a9977a8cbd6d20f2efa813f24bf657c6990a42967019ce779a878dbf"}, + {file = "wrapt-2.0.1-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:09c7476ab884b74dce081ad9bfd07fe5822d8600abade571cb1f66d5fc915af6"}, + {file = "wrapt-2.0.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1a8a09a004ef100e614beec82862d11fc17d601092c3599afd22b1f36e4137e"}, + {file = "wrapt-2.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:89a82053b193837bf93c0f8a57ded6e4b6d88033a499dadff5067e912c2a41e9"}, + {file = "wrapt-2.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f26f8e2ca19564e2e1fdbb6a0e47f36e0efbab1acc31e15471fad88f828c75f6"}, + {file = "wrapt-2.0.1-cp38-cp38-win32.whl", hash = "sha256:115cae4beed3542e37866469a8a1f2b9ec549b4463572b000611e9946b86e6f6"}, + {file = "wrapt-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:c4012a2bd37059d04f8209916aa771dfb564cccb86079072bdcd48a308b6a5c5"}, + {file = "wrapt-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:68424221a2dc00d634b54f92441914929c5ffb1c30b3b837343978343a3512a3"}, + {file = "wrapt-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd1a18f5a797fe740cb3d7a0e853a8ce6461cc62023b630caec80171a6b8097"}, + {file = "wrapt-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fb3a86e703868561c5cad155a15c36c716e1ab513b7065bd2ac8ed353c503333"}, + {file = "wrapt-2.0.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5dc1b852337c6792aa111ca8becff5bacf576bf4a0255b0f05eb749da6a1643e"}, + {file = "wrapt-2.0.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c046781d422f0830de6329fa4b16796096f28a92c8aef3850674442cdcb87b7f"}, + {file = "wrapt-2.0.1-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f73f9f7a0ebd0db139253d27e5fc8d2866ceaeef19c30ab5d69dcbe35e1a6981"}, + {file = "wrapt-2.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b667189cf8efe008f55bbda321890bef628a67ab4147ebf90d182f2dadc78790"}, + {file = "wrapt-2.0.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:a9a83618c4f0757557c077ef71d708ddd9847ed66b7cc63416632af70d3e2308"}, + {file = "wrapt-2.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e9b121e9aeb15df416c2c960b8255a49d44b4038016ee17af03975992d03931"}, + {file = "wrapt-2.0.1-cp39-cp39-win32.whl", hash = "sha256:1f186e26ea0a55f809f232e92cc8556a0977e00183c3ebda039a807a42be1494"}, + {file = "wrapt-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:bf4cb76f36be5de950ce13e22e7fdf462b35b04665a12b64f3ac5c1bbbcf3728"}, + {file = "wrapt-2.0.1-cp39-cp39-win_arm64.whl", hash = "sha256:d6cc985b9c8b235bd933990cdbf0f891f8e010b65a3911f7a55179cd7b0fc57b"}, + {file = "wrapt-2.0.1-py3-none-any.whl", hash = "sha256:4d2ce1bf1a48c5277d7969259232b57645aae5686dba1eaeade39442277afbca"}, + {file = "wrapt-2.0.1.tar.gz", hash = "sha256:9c9c635e78497cacb81e84f8b11b23e0aacac7a136e73b8e5b2109a1d9fc468f"}, ] +[package.extras] +dev = ["pytest", "setuptools"] + [[package]] name = "zipp" version = "3.23.0" diff --git a/pyproject.toml b/pyproject.toml index 7890edee2e..01b16fec3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,33 +86,33 @@ semver = "commitizen.version_schemes:SemVer" semver2 = "commitizen.version_schemes:SemVer2" [dependency-groups] -dev = ["ipython>=8.0,<9.0", "tox>4", "poethepoet>=0.34.0,<1.0.0"] +dev = ["ipython>=8.0", "tox>4", "poethepoet>=0.34.0"] test = [ - "pytest>=7.2,<9.0", - "pytest-cov>=4,<7", - "pytest-mock>=3.10,<4.0", - "pytest-regressions>=2.4.0,<3.0.0", - "pytest-freezer>=0.4.6,<1.0.0", - "pytest-xdist>=3.1.0,<4.0.0", + "pytest>=7.2", + "pytest-cov>=4", + "pytest-mock>=3.10", + "pytest-regressions>=2.4.0", + "pytest-freezer>=0.4.6", + "pytest-xdist>=3.1.0", ] linters = [ - "ruff>=0.11.5,<1.0.0", - "pre-commit>=3.2.0,<5.0", - "mypy>=1.16.0,<2.0", - "types-deprecated>=1.2.9.2,<2.0", - "types-python-dateutil>=2.8.19.13,<3.0", - "types-PyYAML>=5.4.3,<7.0.0", - "types-termcolor>=0.1.1,<1.0", - "types-colorama>=0.4.15.20240311,<1.0", + "ruff>=0.11.5", + "pre-commit>=3.2.0", + "mypy>=1.16.0", + "types-deprecated>=1.2.9.2", + "types-python-dateutil>=2.8.19.13", + "types-PyYAML>=5.4.3", + "types-termcolor>=0.1.1", + "types-colorama>=0.4.15.20240311", ] -documentation = ["mkdocs>=1.4.2,<2.0", "mkdocs-material>=9.1.6,<10.0"] +documentation = ["mkdocs>=1.4.2", "mkdocs-material>=9.1.6"] script = [ # for scripts/gen_cli_help_screenshots.py - "rich>=13.7.1,<14.0", + "rich>=13.7.1", ] [build-system] From 583acf42deb14fb04f7c188b5f8d09b623e335cc Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 19 Nov 2025 17:12:08 +0800 Subject: [PATCH 103/221] docs(config): split the configuration documentation into pages Co-authored-by: Wei Lee --- docs/commands/bump.md | 233 +--------- docs/commands/changelog.md | 110 +++-- docs/commands/commit.md | 2 +- docs/commands/init.md | 16 +- docs/config.md | 421 ------------------ docs/config/bump.md | 217 ++++++++++ docs/config/changelog.md | 8 + docs/config/check.md | 27 ++ docs/config/commit.md | 26 ++ docs/config/configuration_file.md | 234 ++++++++++ docs/config/option.md | 38 ++ docs/config/version_provider.md | 318 ++++++++++++++ docs/customization.md | 529 ----------------------- docs/customization/changelog_template.md | 85 ++++ docs/customization/config_file.md | 187 ++++++++ docs/customization/python_class.md | 310 +++++++++++++ docs/faq.md | 11 +- docs/tutorials/tag_format.md | 5 +- docs/tutorials/writing_commits.md | 6 +- mkdocs.yml | 14 +- 20 files changed, 1553 insertions(+), 1244 deletions(-) delete mode 100644 docs/config.md create mode 100644 docs/config/bump.md create mode 100644 docs/config/changelog.md create mode 100644 docs/config/check.md create mode 100644 docs/config/commit.md create mode 100644 docs/config/configuration_file.md create mode 100644 docs/config/option.md create mode 100644 docs/config/version_provider.md delete mode 100644 docs/customization.md create mode 100644 docs/customization/changelog_template.md create mode 100644 docs/customization/config_file.md create mode 100644 docs/customization/python_class.md diff --git a/docs/commands/bump.md b/docs/commands/bump.md index ebd8b2774e..78ff9777cf 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -11,7 +11,7 @@ It analyzes your commits to determine the appropriate version increment accordin We will use `pyproject.toml` as the configuration file throughout the documentation. - See [Configuration file](../config.md#configuration-file) for more details. + See [Configuration file](../config/configuration_file.md) for more details. ## Key Features @@ -30,7 +30,7 @@ The version follows the `MAJOR.MINOR.PATCH` format, with increments determined b | `MINOR` | New features | `feat` | | `PATCH` | Fixes and improvements | `fix`, `perf`, `refactor`| -### Version Schemes (`--version-scheme`) +### `--version-scheme` By default, Commitizen uses [PEP 440][pep440] for version formatting. You can switch to semantic versioning using either: @@ -50,7 +50,7 @@ Available options are: - `pep440`: [PEP 440][pep440] (**default** and recommended for Python projects) - `semver`: [Semantic Versioning][semver] (recommended for non-Python projects) -You can also set this in the [configuration](#version_scheme) with `version_scheme = "semver"`. +You can also set this in the configuration file with `version_scheme = "semver"`. !!! note [pep440][pep440] and [semver][semver] are quite similar, although their difference lies in @@ -111,7 +111,7 @@ Commitizen supports the [PEP 440][pep440] version format, which includes several ### `--files-only` -Bumps the version in the files defined in [`version_files`](#version_files) without creating a commit and tag on the git repository. +Bumps the version in the files defined in [`version_files`][version_files] without creating a commit and tag on the git repository. ```bash cz bump --files-only @@ -178,7 +178,7 @@ The following table illustrates the difference in behavior between the two modes ### `--check-consistency` -Check whether the versions defined in [`version_files`](#version_files) and the version in Commitizen configuration are consistent before bumping version. +Check whether the versions defined in [version_files][version_files] and the version in Commitizen configuration are consistent before bumping version. ```bash cz bump --check-consistency @@ -207,7 +207,7 @@ from setuptools import setup setup(..., version="1.0.5", ...) ``` -When you run `cz bump --check-consistency`, Commitizen will verify that the current version in `pyproject.toml` (`1.21.0`) exists in all files listed in [`version_files`](#version_files). +When you run `cz bump --check-consistency`, Commitizen will verify that the current version in `pyproject.toml` (`1.21.0`) exists in all files listed in [version_files][version_files]. In this example, it will detect that `setup.py` contains `1.0.5` instead of `1.21.0`, causing the bump to fail. !!! warning "Partial updates on failure" @@ -260,6 +260,9 @@ For example, in `pyproject.toml`: annotated_tag = true ``` +!!! note + By default, Commitizen uses lightweight tags. + ### `--annotated-tag-message` Create annotated tags with the given message. @@ -351,10 +354,13 @@ Creates gpg signed tags. cz bump --gpg-sign ``` +!!! note + By default, Commitizen uses lightweight tags. + ### `--template` Provides your own changelog jinja template. -See [the template customization section](../customization.md#customizing-the-changelog-template) +See [the template customization section](../customization/changelog_template.md) ### `--extra` @@ -364,7 +370,7 @@ Provides your own changelog extra variables by using the `extras` settings or th cz bump --changelog --extra key=value -e short="quoted value" ``` -See [the template customization section](../customization.md#customizing-the-changelog-template). +See [the template customization section](../customization/changelog_template.md). ### `--build-metadata` @@ -451,15 +457,13 @@ Allow the project version to be bumped even when there's no eligible version. cz bump --allow-no-commit ``` -### `--version-scheme` - -See [Version Schemes](#version-schemes-version-scheme). - -## Configuration file options + # bump version to 2.0.0 even when there's no breaking changes or even no commits + cz bump --allow-no-commit 2.0.0 + ``` -### `tag_format` +### `--tag-format` -`tag_format` and [`version_scheme`](#version-schemes-version-scheme) are combined to make Git tag names from versions. +`tag_format` and [version_scheme][version_scheme] are combined to make Git tag names from versions. These are used in: @@ -501,200 +505,6 @@ Supported variables: | `$prerelease`, `${prerelease}` | Prerelease (alpha, beta, release candidate) | | `$devrelease`, `${devrelease}` | Development release | -### `version_files` - -Identify the files or glob patterns which should be updated with the new version. - -Commitizen will update its configuration file automatically when bumping, -regardless of whether the file is present or not in `version_files`. - -You may specify the `version_files` in your configuration file. - -```toml title="pyproject.toml" -[tool.commitizen] -version_files = [ - "src/__version__.py", -] -``` - -It is also possible to provide a pattern for each file, separated by a colon (e.g. `file:pattern`). See the below example for more details. - -```toml title="pyproject.toml" -[tool.commitizen] -version_files = [ - "packages/*/pyproject.toml:version", - "setup.json:version", -] -``` - -#### Example scenario - -We have a project with the following configuration file `pyproject.toml`: - -```toml title="pyproject.toml" -[tool.commitizen] -version_files = [ - "src/__version__.py", - "packages/*/pyproject.toml:version", - "setup.json:version", -] -``` - -For the reference `"setup.json:version"`, it means that it will look for a file `setup.json` and will only change the lines that contain the substring `"version"`. - -For example, if the content of `setup.json` is: - - - -```json title="setup.json" -{ - "name": "magictool", - "version": "1.2.3", - "dependencies": { - "lodash": "1.2.3" - } -} -``` - -After running `cz bump 2.0.0`, its content will be updated to: - -```diff title="setup.json" -{ - "name": "magictool", -- "version": "1.2.3", -+ "version": "2.0.0", - "dependencies": { - "lodash": "1.2.3" - } -} -``` - -!!! note - Files can be specified using relative (to the execution) paths, absolute paths, or glob patterns. - -!!! note "Historical note" - This option was renamed from `files` to `version_files`. - -### `bump_message` - -Template used to specify the commit message generated when bumping. - -Defaults to: `bump: version $current_version → $new_version` - -| Variable | Description | -| ------------------ | ----------------------------------- | -| `$current_version` | the version existing before bumping | -| `$new_version` | version generated after bumping | - -#### Example configuration - -```toml title="pyproject.toml" -[tool.commitizen] -bump_message = "release $current_version → $new_version [skip-ci]" -``` - -### `update_changelog_on_bump` - -When set to `true`, `cz bump` is equivalent to `cz bump --changelog`. - -```toml title="pyproject.toml" -[tool.commitizen] -update_changelog_on_bump = true -``` - -### `annotated_tag` - -When set to `true`, `cz bump` is equivalent to `cz bump --annotated-tag`. - -```toml title="pyproject.toml" -[tool.commitizen] -annotated_tag = true -``` - -### `gpg_sign` - -When set to `true`, `cz bump` is equivalent to `cz bump --gpg-sign`. See [--gpg-sign](#-gpg-sign). - -```toml title="pyproject.toml" -[tool.commitizen] -gpg_sign = true -``` - -### `major_version_zero` - -When set to `true`, `cz bump` is equivalent to `cz bump --major-version-zero`. See [--major-version-zero](#-major-version-zero). - -```toml title="pyproject.toml" -[tool.commitizen] -major_version_zero = true -``` - -### `pre_bump_hooks` - -A list of optional commands that will run right _after_ updating [`version_files`](#version_files) -and _before_ actual committing and tagging the release. - -Useful when you need to generate documentation based on the new version. During -execution of the script, some environment variables are available: - -| Variable | Description | -| ---------------------------- | ---------------------------------------------------------- | -| `CZ_PRE_IS_INITIAL` | `True` when this is the initial release, `False` otherwise | -| `CZ_PRE_CURRENT_VERSION` | Current version, before the bump | -| `CZ_PRE_CURRENT_TAG_VERSION` | Current version tag, before the bump | -| `CZ_PRE_NEW_VERSION` | New version, after the bump | -| `CZ_PRE_NEW_TAG_VERSION` | New version tag, after the bump | -| `CZ_PRE_MESSAGE` | Commit message of the bump | -| `CZ_PRE_INCREMENT` | Whether this is a `MAJOR`, `MINOR` or `PATCH` release | -| `CZ_PRE_CHANGELOG_FILE_NAME` | Path to the changelog file, if available | - -```toml title="pyproject.toml" -[tool.commitizen] -pre_bump_hooks = [ - "scripts/generate_documentation.sh" -] -``` - -### `post_bump_hooks` - -A list of optional commands that will run right _after_ committing and tagging the release. - -Useful when you need to send notifications about a release, or further automate deploying the -release. During execution of the script, some environment variables are available: - -| Variable | Description | -| ------------------------------ | ----------------------------------------------------------- | -| `CZ_POST_WAS_INITIAL` | `True` when this was the initial release, `False` otherwise | -| `CZ_POST_PREVIOUS_VERSION` | Previous version, before the bump | -| `CZ_POST_PREVIOUS_TAG_VERSION` | Previous version tag, before the bump | -| `CZ_POST_CURRENT_VERSION` | Current version, after the bump | -| `CZ_POST_CURRENT_TAG_VERSION` | Current version tag, after the bump | -| `CZ_POST_MESSAGE` | Commit message of the bump | -| `CZ_POST_INCREMENT` | Whether this was a `MAJOR`, `MINOR` or `PATCH` release | -| `CZ_POST_CHANGELOG_FILE_NAME` | Path to the changelog file, if available | - -```toml title="pyproject.toml" -[tool.commitizen] -post_bump_hooks = [ - "scripts/slack_notification.sh" -] -``` - -### `prerelease_offset` - -Offset with which to start counting prereleases. - -Defaults to: `0` - -```toml title="pyproject.toml" -[tool.commitizen] -prerelease_offset = 1 -``` - -### `version_scheme` - -See [Version Schemes](#version-schemes-version-scheme). - ## Avoid raising errors Some situations from Commitizen raise an exit code different from 0. @@ -758,9 +568,6 @@ on the list, and then you can use the exit code: cz -nr 21 bump ``` -## Custom bump - -Read the [customizing section](../customization.md). - [pep440]: https://www.python.org/dev/peps/pep-0440/ [semver]: https://semver.org/ +[version_files]: ../config/bump.md#version_files diff --git a/docs/commands/changelog.md b/docs/commands/changelog.md index aee1a0e075..3f2425a51f 100644 --- a/docs/commands/changelog.md +++ b/docs/commands/changelog.md @@ -2,44 +2,37 @@ This command will generate a changelog following the committing rules established. -To create the changelog automatically on bump, add the setting [update_changelog_on_bump](./bump.md#update_changelog_on_bump) +!!! tip + To create the changelog automatically on bump, add the setting [update_changelog_on_bump](../config/bump.md#update_changelog_on_bump) -```toml -[tool.commitizen] -update_changelog_on_bump = true -``` + ```toml + [tool.commitizen] + update_changelog_on_bump = true + ``` ## Usage ![cz changelog --help](../images/cli_help/cz_changelog___help.svg) -### Examples - -#### Generate full changelog +## Examples ```bash +# Generate full changelog cz changelog -``` -```bash +# or use the alias cz ch -``` -#### Get the changelog for the given version - -```bash +# Get the changelog for the given version cz changelog 0.3.0 --dry-run -``` - -#### Get the changelog for the given version range -```bash +# Get the changelog for the given version range cz changelog 0.3.0..0.4.0 --dry-run ``` ## Constrains -changelog generation is constrained only to **markdown** files. +Changelog generation is constrained only to **markdown** files. ## Description @@ -72,41 +65,19 @@ and the following variables are expected: - **required**: is the only one required to be parsed by the regex -## Configuration - -### `unreleased_version` - -There is usually a chicken and egg situation when automatically -bumping the version and creating the changelog. -If you bump the version first, you have no changelog, you have to -create it later, and it won't be included in -the release of the created version. - -If you create the changelog before bumping the version, then you -usually don't have the latest tag, and the _Unreleased_ title appears. - -By introducing `unreleased_version` you can prevent this situation. - -Before bumping you can run: - -```bash -cz changelog --unreleased-version="v1.0.0" -``` - -Remember to use the tag instead of the raw version number +## Command line options -For example if the format of your tag includes a `v` (`v1.0.0`), then you should use that, -if your tag is the same as the raw version, then ignore this. +### `--extras` -Alternatively you can directly bump the version and create the changelog by doing +Provides your own changelog extra variables by using the `extras` settings or the `--extra/-e` parameter. ```bash -cz bump --changelog +cz changelog --extra key=value -e short="quoted value" ``` -### `file-name` +### `--file-name` -This value can be updated in the `toml` file with the key `changelog_file` under `tools.commitizen` +This value can be updated in the configuration file with the key `changelog_file` under `tools.commitizen` Specify the name of the output file, remember that changelog only works with Markdown. @@ -114,9 +85,9 @@ Specify the name of the output file, remember that changelog only works with Mar cz changelog --file-name="CHANGES.md" ``` -### `incremental` +### `--incremental` -This flag can be set in the `toml` file with the key `changelog_incremental` under `tools.commitizen` +This flag can be set in the configuration file with the key `changelog_incremental` under `tools.commitizen` Benefits: @@ -134,9 +105,9 @@ cz changelog --incremental changelog_incremental = true ``` -### `start-rev` +### `--start-rev` -This value can be set in the `toml` file with the key `changelog_start_rev` under `tools.commitizen` +This value can be set in the configuration file with the key `changelog_start_rev` under `tools.commitizen` Start from a given git rev to generate the changelog. Commits before that rev will not be considered. This is especially useful for long-running projects adopting conventional commits, where old commit messages might fail to be parsed for changelog generation. @@ -150,9 +121,9 @@ cz changelog --start-rev="v0.2.0" changelog_start_rev = "v0.2.0" ``` -### merge-prerelease +### `--merge-prerelease` -This flag can be set in the `toml` file with the key `changelog_merge_prerelease` under `tools.commitizen` +This flag can be set in the configuration file with the key `changelog_merge_prerelease` under `tools.commitizen` Collects changes from prereleases into the next non-prerelease. This means that if you have a prerelease version, and then a normal release, the changelog will show the prerelease changes as part of the changes of the normal release. If not set, it will include prereleases in the changelog. @@ -166,20 +137,39 @@ cz changelog --merge-prerelease changelog_merge_prerelease = true ``` -### `template` +### `--template` Provides your own changelog jinja template by using the `template` settings or the `--template` parameter. -See [the template customization section](../customization.md#customizing-the-changelog-template) -### `extras` +### `--unreleased-version` -Provides your own changelog extra variables by using the `extras` settings or the `--extra/-e` parameter. +There is usually a chicken and egg situation when automatically +bumping the version and creating the changelog. +If you bump the version first, you have no changelog, you have to +create it later, and it won't be included in +the release of the created version. + +If you create the changelog before bumping the version, then you +usually don't have the latest tag, and the _Unreleased_ title appears. + +By introducing `--unreleased-version` you can prevent this situation. + +Before bumping you can run: ```bash -cz changelog --extra key=value -e short="quoted value" +cz changelog --unreleased-version="v1.0.0" ``` -See [the template customization section](../customization.md#customizing-the-changelog-template) +Remember to use the tag instead of the raw version number + +For example if the format of your tag includes a `v` (`v1.0.0`), then you should use that, +if your tag is the same as the raw version, then ignore this. + +Alternatively you can directly bump the version and create the changelog by doing + +```bash +cz bump --changelog +``` ## Hooks @@ -192,4 +182,4 @@ Read more about hooks in the [customization page][customization] [keepachangelog]: https://keepachangelog.com/ [semver]: https://semver.org/ -[customization]: ../customization.md +[customization]: ../customization/config_file.md diff --git a/docs/commands/commit.md b/docs/commands/commit.md index be9d193b97..54e0c8b07a 100644 --- a/docs/commands/commit.md +++ b/docs/commands/commit.md @@ -11,7 +11,7 @@ The `commit` command provides an interactive way to create structured commits. U - `cz commit` - `cz c` (shortcut) -By default, Commitizen uses conventional commits, but you can customize the commit rules to match your project's needs. See the [customization guide](../customization.md) for details. +By default, Commitizen uses conventional commits, but you can customize the commit rules to match your project's needs. See the [customization guide](../customization/config_file.md) for details. ## Basic Usage diff --git a/docs/commands/init.md b/docs/commands/init.md index 4d92112d34..b673ba1276 100644 --- a/docs/commands/init.md +++ b/docs/commands/init.md @@ -20,10 +20,7 @@ When you run `cz init`, Commitizen will guide you through an interactive setup p The initialization process will create a configuration file in your project root. -Choose the configuration file format based on your project type: - -- Use `pyproject.toml` for Python projects -- Use `.cz.toml`, `.cz.yaml`, `.cz.json`, etc. for other projects. +See [Configuration File][configuration_file] for more details. ## Configuration Options @@ -48,6 +45,8 @@ During the initialization process, you'll be prompted to configure the following 7. **Alpha Versioning**: Option to keep major version at 0 for alpha/beta software 8. **Pre-commit Hooks**: Set up Git pre-commit hooks for automated commit message validation +See [Configuration Options][configuration_options] for more details. + ## Example ```sh @@ -61,6 +60,9 @@ cz init After initialization, you can: -1. Start using `cz commit` to create conventional commits -2. Use `cz bump` to manage versioning -3. Configure additional settings in your project's configuration file +1. Start using [`cz commit`](./commit.md) to create conventional commits +2. Use [`cz bump`](./bump.md) to manage versioning +3. Configure additional settings in your project's [configuration_file][configuration_file] + +[configuration_file]: ../config/configuration_file.md +[configuration_options]: ../config/option.md diff --git a/docs/config.md b/docs/config.md deleted file mode 100644 index 307cf54a9f..0000000000 --- a/docs/config.md +++ /dev/null @@ -1,421 +0,0 @@ -# Configuration - -## Settings - -### `name` - -- Type: `str` -- Default: `"cz_conventional_commits"` - -Name of the committing rules to use. - -### `version` - -- Type: `str` -- Default: `None` - -Current version. Example: `"0.1.2"`. Required if you use `version_provider = "commitizen"`. - -### `version_files` - -- Type: `list` -- Default: `[]` - -Files (or glob patterns) where the version will be updated. A pattern to match a line, can also be specified, separated by `:` [Read more][version_files] - -### `version_provider` - -- Type: `str` -- Default: `commitizen` - -Version provider used to read and write version. [Read more](#version-providers) - -### `version_scheme` - -- Type: `str` -- Default: `pep440` - -Select a version scheme from the following options: - -- `pep440` -- `semver` -- `semver2` - -Useful for non-python projects. [Read more][version-scheme] - -### `tag_format` - -- Type: `str` -- Default: `$version` - -Format for the git tag, useful for old projects, that use a convention like `"v1.2.1"`. [Read more][tag_format] - -### `legacy_tag_formats` - -- Type: `list` -- Default: `[]` - -Legacy git tag formats, useful for old projects that changed tag format. -Tags matching those formats will be recognized as version tags and be included in the changelog. -Each entry uses the syntax as [`tag_format`](#tag_format). [Read more][tag_format] - -### `ignored_tag_formats` - -- Type: `list` -- Default: `[]` - -Tags matching those formats will be totally ignored and won't raise a warning. -Each entry uses the syntax as [`tag_format`](#tag_format) with the addition of `*` -that will match everything (non-greedy). [Read more][tag_format] - -### `update_changelog_on_bump` - -- Type: `bool` -- Default: `False` - -Create changelog when running `cz bump`. - -### `gpg_sign` - -- Type: `bool` -- Default: `False` - -Use gpg signed tags instead of lightweight tags. - -### `annotated_tag` - -- Type: `bool` -- Default: `False` - -Use annotated tags instead of lightweight tags. [See difference][annotated-tags-vs-lightweight] - -### `bump_message` - -- Type: `str` -- Default: `None` - -Create custom commit message. Useful to skip CI. [Read more][bump_message] - -### `breaking_change_exclamation_in_title` - -Type: `bool` - -Default: `False` - -When true, breaking changes will be also indicated by an exclamation mark in the commit title (e.g., `feat!: breaking change`). -When false, breaking changes will be only indicated by `BREAKING CHANGE:` in the footer. [Read more][writing_commits] - -### `retry_after_failure` - -- Type: `bool` -- Default: `False` - -Automatically retry failed commit when running `cz commit`. [Read more][retry_after_failure] - -### `allow_abort` - -- Type: `bool` -- Default: `False` - -Disallow empty commit messages. Useful in CI. [Read more][allow_abort] - -### `message_length_limit` - -Type: `int` - -Default: `0` - -Maximum length of the commit message. Setting it to `0` disables the length limit. It can be overridden by the `-l/--message-length-limit` command line argument. - -### `allowed_prefixes` - -- Type: `list` -- Default: `["Merge", "Revert", "Pull request", "fixup!", "squash!"]` - -List of prefixes that commitizen ignores when verifying messages. [Read more][allowed_prefixes] - -### `changelog_file` - -- Type: `str` -- Default: `CHANGELOG.md` - -Filename of exported changelog - -### `changelog_format` - -- Type: `str` -- Default: `None` - -Format used to parse and generate the changelog. If not specified, guessed from [`changelog_file`](#changelog_file). - -### `changelog_incremental` - -- Type: `bool` -- Default: `False` - -Update changelog with the missing versions. This is good if you don't want to replace previous versions in the file. - -!!! note - When doing `cz bump --changelog` this is automatically set to `True` - -### `changelog_start_rev` - -- Type: `str` -- Default: `None` - -Start from a given git rev to generate the changelog - -### `changelog_merge_prerelease` - -- Type: `bool` -- Default: `False` - -Collect all changes of prerelease versions into the next non-prerelease version when creating the changelog. - -### `style` - -- Type: `list` -- Default: `[]` - -Style for the prompts (It will merge this value with default style.) [See More (Styling your prompts with your favorite colors)][additional-features] - -### `customize` - -- Type: `dict` -- Default: `None` - -**This is only supported when config through `toml`.** Custom rules for committing and bumping. [Read more][customization] - -### `use_shortcuts` - -- Type: `bool` -- Default: `False` - -If enabled, Commitizen will show keyboard shortcuts when selecting from a list. Define a `key` for each of your choices to set the key. [Read more][shortcuts] - -### `major_version_zero` - -- Type: `bool` -- Default: `False` - -If enabled, breaking changes on a `0.x` will remain as a `0.x` version. Otherwise, a breaking change will bump a `0.x` version to `1.0`. [Read more][major-version-zero] - -### `prerelease_offset` - -- Type: `int` -- Default: `0` - -In some circumstances, a prerelease cannot start with `0`-for example, in embedded projects where individual characters are encoded as bytes. You can specify an offset from which to start counting. [Read more][prerelease-offset] - -### `pre_bump_hooks` - -- Type: `list[str]` -- Default: `[]` - -Calls the hook scripts **before** bumping version. [Read more][pre_bump_hooks] - -### `post_bump_hooks` - -- Type: `list[str]` -- Default: `[]` - -Calls the hook scripts **after** bumping the version. [Read more][post_bump_hooks] - -### `encoding` - -- Type: `str` -- Default: `"utf-8"` - -Sets the character encoding to be used when parsing commit messages. [Read more][encoding] - -### `template` - -- Type: `str` -- Default: `None` (provided by plugin) - -Provide custom changelog jinja template path relative to the current working directory. [Read more][template-customization] - -### `extras` - -- Type: `dict[str, Any]` -- Default: `{}` - -Provide extra variables to the changelog template. [Read more][template-customization] - -## Configuration file - -### `pyproject.toml`, `.cz.toml` or `cz.toml` - -Default and recommended configuration format for a project. -For a **python** project, we recommend adding an entry to your `pyproject.toml`. -You can also create a `.cz.toml` or `cz.toml` file at the root of your project folder. - -Example configuration: - -```toml title=".cz.toml" -[tool.commitizen] -name = "cz_conventional_commits" -version = "0.1.0" -version_files = [ - "src/__version__.py", - "pyproject.toml:version" -] -update_changelog_on_bump = true -style = [ - ["qmark", "fg:#ff9d00 bold"], - ["question", "bold"], - ["answer", "fg:#ff9d00 bold"], - ["pointer", "fg:#ff9d00 bold"], - ["highlighted", "fg:#ff9d00 bold"], - ["selected", "fg:#cc5454"], - ["separator", "fg:#cc5454"], - ["instruction", ""], - ["text", ""], - ["disabled", "fg:#858585 italic"] -] -``` - -### `.cz.json` or `cz.json` - -Commitizen has support for JSON configuration. Recommended for `NodeJS` projects. - -```json title=".cz.json" -{ - "commitizen": { - "name": "cz_conventional_commits", - "version": "0.1.0", - "version_files": ["src/__version__.py", "pyproject.toml:version"], - "style": [ - ["qmark", "fg:#ff9d00 bold"], - ["question", "bold"], - ["answer", "fg:#ff9d00 bold"], - ["pointer", "fg:#ff9d00 bold"], - ["highlighted", "fg:#ff9d00 bold"], - ["selected", "fg:#cc5454"], - ["separator", "fg:#cc5454"], - ["instruction", ""], - ["text", ""], - ["disabled", "fg:#858585 italic"] - ] - } -} -``` - -### `.cz.yaml` or `cz.yaml` - -YAML configuration is supported by Commitizen. Recommended for `Go`, `ansible`, or even `helm` charts projects. - -```yaml title=".cz.yaml" -commitizen: - name: cz_conventional_commits - version: 0.1.0 - version_files: - - src/__version__.py - - pyproject.toml:version - style: - - - qmark - - fg:#ff9d00 bold - - - question - - bold - - - answer - - fg:#ff9d00 bold - - - pointer - - fg:#ff9d00 bold - - - highlighted - - fg:#ff9d00 bold - - - selected - - fg:#cc5454 - - - separator - - fg:#cc5454 - - - instruction - - "" - - - text - - "" - - - disabled - - fg:#858585 italic -``` - -## Version providers - -Commitizen can read and write version from different sources. -By default, it uses the `commitizen` one which is using the `version` field from the Commitizen settings. -But you can use any `commitizen.provider` entrypoint as value for `version_provider`. - -Commitizen provides some version providers for some well known formats: - -| name | description | -| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `commitizen` | Default version provider: Fetch and set version in Commitizen config. | -| `scm` | Fetch the version from git and does not need to set it back | -| `pep621` | Get and set version from `pyproject.toml` `project.version` field | -| `poetry` | Get and set version from `pyproject.toml` `tool.poetry.version` field | -| `uv` | Get and set version from `pyproject.toml` `project.version` field and `uv.lock` `package.version` field whose `package.name` field is the same as `pyproject.toml` `project.name` field | -| `cargo` | Get and set version from `Cargo.toml` `package.version` field and `Cargo.lock` `package.version` field whose `package.name` field is the same as `Cargo.toml` `package.name` field | -| `npm` | Get and set version from `package.json` `version` field, `package-lock.json` `version,packages.''.version` fields if the file exists, and `npm-shrinkwrap.json` `version,packages.''.version` fields if the file exists | -| `composer` | Get and set version from `composer.json` `project.version` field | - -!!! note - The `scm` provider is meant to be used with `setuptools-scm` or any packager `*-scm` plugin. - -An example in your `.cz.toml` or `cz.toml` would look like this: - -```toml -[tool.commitizen] -version_provider = "pep621" -``` - -### Custom version provider - -You can add your own version provider by extending `VersionProvider` and exposing it on the `commitizen.provider` entrypoint. - -Here is a quick example of a provider `my_provider.py`, reading and writing version in a `VERSION` file. - -```python title="my_provider.py" -from pathlib import Path -from commitizen.providers import VersionProvider - - -class MyProvider(VersionProvider): - file = Path() / "VERSION" - - def get_version(self) -> str: - return self.file.read_text() - - def set_version(self, version: str): - self.file.write_text(version) -``` - -```python title="setup.py" -from setuptools import setup - -setup( - name="my-commitizen-provider", - version="0.1.0", - py_modules=["my_provider"], - install_requires=["commitizen"], - entry_points={ - "commitizen.provider": [ - "my-provider = my_provider:MyProvider", - ] - }, -) -``` - -[version_files]: commands/bump.md#version_files -[tag_format]: commands/bump.md#tag_format -[bump_message]: commands/bump.md#bump_message -[major-version-zero]: commands/bump.md#-major-version-zero -[prerelease-offset]: commands/bump.md#prerelease_offset -[retry_after_failure]: commands/commit.md#retry -[allow_abort]: commands/check.md#-allow-abort -[version-scheme]: commands/bump.md#version-schemes-version-scheme -[pre_bump_hooks]: commands/bump.md#pre_bump_hooks -[post_bump_hooks]: commands/bump.md#post_bump_hooks -[allowed_prefixes]: commands/check.md#-allowed-prefixes -[additional-features]: https://github.com/tmbo/questionary#additional-features -[customization]: customization.md -[shortcuts]: customization.md#shortcut-keys -[template-customization]: customization.md#customizing-the-changelog-template -[annotated-tags-vs-lightweight]: https://stackoverflow.com/a/11514139/2047185 -[encoding]: tutorials/writing_commits.md#writing-commits -[writing_commits]: tutorials/writing_commits.md#conventional-commits diff --git a/docs/config/bump.md b/docs/config/bump.md new file mode 100644 index 0000000000..fa46e18f8d --- /dev/null +++ b/docs/config/bump.md @@ -0,0 +1,217 @@ +# Bump Options + + + +## `annotated_tag` + +When set to `true`, `cz bump` is equivalent to `cz bump --annotated-tag`. + +```toml title="pyproject.toml" +[tool.commitizen] +annotated_tag = true +``` + +## `bump_message` + +Template used to specify the commit message generated when bumping. + +Defaults to: `bump: version $current_version → $new_version` + +| Variable | Description | +| ------------------ | ----------------------------------- | +| `$current_version` | the version existing before bumping | +| `$new_version` | version generated after bumping | + +```toml title="pyproject.toml" +[tool.commitizen] +bump_message = "release $current_version → $new_version [skip-ci]" +``` + +## `gpg_sign` + +When set to `true`, `cz bump` is equivalent to `cz bump --gpg-sign`. See [`--gpg-sign`](../commands/bump.md#-gpg-sign). + +```toml title="pyproject.toml" +[tool.commitizen] +gpg_sign = true +``` + +## `ignored_tag_formats` + +- Type: `list` +- Default: `[]` + +Tags matching those formats will be totally ignored and won't raise a warning. +Each entry uses the syntax as [`tag_format`](#tag_format) with the addition of `*` that will match everything (non-greedy). + +## `major_version_zero` + +When set to `true`, `cz bump` is equivalent to `cz bump --major-version-zero`. See [`--major-version-zero`](../commands/bump.md#-major-version-zero). + +```toml title="pyproject.toml" +[tool.commitizen] +major_version_zero = true +``` + +## `legacy_tag_formats` + +- Type: `list` +- Default: `[]` + +Legacy git tag formats, useful for old projects that changed tag format. +Tags matching those formats will be recognized as version tags and be included in the changelog. +Each entry uses the syntax as `tag_format`. + +## `pre_bump_hooks` + +A list of optional commands that will run right *after* updating [`version_files`](#version_files) and *before* actual committing and tagging the release. + +Useful when you need to generate documentation based on the new version. During +execution of the script, some environment variables are available: + +| Variable | Description | +| ---------------------------- | ---------------------------------------------------------- | +| `CZ_PRE_IS_INITIAL` | `True` when this is the initial release, `False` otherwise | +| `CZ_PRE_CURRENT_VERSION` | Current version, before the bump | +| `CZ_PRE_CURRENT_TAG_VERSION` | Current version tag, before the bump | +| `CZ_PRE_NEW_VERSION` | New version, after the bump | +| `CZ_PRE_NEW_TAG_VERSION` | New version tag, after the bump | +| `CZ_PRE_MESSAGE` | Commit message of the bump | +| `CZ_PRE_INCREMENT` | Whether this is a `MAJOR`, `MINOR` or `PATCH` release | +| `CZ_PRE_CHANGELOG_FILE_NAME` | Path to the changelog file, if available | + +```toml title="pyproject.toml" +[tool.commitizen] +pre_bump_hooks = [ + "scripts/generate_documentation.sh" +] +``` + +## `post_bump_hooks` + +A list of optional commands that will run right *after* committing and tagging the release. + +Useful when you need to send notifications about a release, or further automate deploying the +release. During execution of the script, some environment variables are available: + +| Variable | Description | +| ------------------------------ | ----------------------------------------------------------- | +| `CZ_POST_WAS_INITIAL` | `True` when this was the initial release, `False` otherwise | +| `CZ_POST_PREVIOUS_VERSION` | Previous version, before the bump | +| `CZ_POST_PREVIOUS_TAG_VERSION` | Previous version tag, before the bump | +| `CZ_POST_CURRENT_VERSION` | Current version, after the bump | +| `CZ_POST_CURRENT_TAG_VERSION` | Current version tag, after the bump | +| `CZ_POST_MESSAGE` | Commit message of the bump | +| `CZ_POST_INCREMENT` | Whether this was a `MAJOR`, `MINOR` or `PATCH` release | +| `CZ_POST_CHANGELOG_FILE_NAME` | Path to the changelog file, if available | + +```toml title="pyproject.toml" +[tool.commitizen] +post_bump_hooks = [ + "scripts/slack_notification.sh" +] +``` + +## `prerelease_offset` + +Offset with which to start counting prereleases. + +If not specified, defaults to `0`. + +```toml title="pyproject.toml" +[tool.commitizen] +prerelease_offset = 1 +``` + +!!! note + Under some circumstances, a prerelease cannot start with `0`-for example, in embedded projects where individual characters are encoded as bytes. You can specify an offset from which to start counting. + +## `tag_format` + +See [`--tag-format`](../commands/bump.md#-tag-format). + +## `update_changelog_on_bump` + +When set to `true`, `cz bump` is equivalent to `cz bump --changelog`. + +```toml title="pyproject.toml" +[tool.commitizen] +update_changelog_on_bump = true +``` + +## `version_files` + +Identify the files or glob patterns which should be updated with the new version. + +Commitizen will update its configuration file automatically when bumping, +regardless of whether the file is present or not in `version_files`. + +You may specify the `version_files` in your configuration file. + +```toml title="pyproject.toml" +[tool.commitizen] +version_files = [ + "src/__version__.py", +] +``` + +It is also possible to provide a pattern for each file, separated by a colon (e.g. `file:pattern`). See the below example for more details. + +```toml title="pyproject.toml" +[tool.commitizen] +version_files = [ + "packages/*/pyproject.toml:version", + "setup.json:version", +] +``` + +!!! note "Example scenario" + We have a project with the following configuration file `pyproject.toml`: + + ```toml title="pyproject.toml" + [tool.commitizen] + version_files = [ + "src/__version__.py", + "packages/*/pyproject.toml:version", + "setup.json:version", + ] + ``` + + For the reference `"setup.json:version"`, it means that it will look for a file `setup.json` and will only change the lines that contain the substring `"version"`. + + For example, if the content of `setup.json` is: + + + + ```json title="setup.json" + { + "name": "magictool", + "version": "1.2.3", + "dependencies": { + "lodash": "1.2.3" + } + } + ``` + + After running `cz bump 2.0.0`, its content will be updated to: + + ```diff title="setup.json" + { + "name": "magictool", + - "version": "1.2.3", + + "version": "2.0.0", + "dependencies": { + "lodash": "1.2.3" + } + } + ``` + +!!! note + Files can be specified using relative (to the execution) paths, absolute paths, or glob patterns. + +!!! note "Historical note" + This option was renamed from `files` to `version_files`. + +## `version_scheme` + +See [`--version-scheme`](../commands/bump.md#-version-scheme). diff --git a/docs/config/changelog.md b/docs/config/changelog.md new file mode 100644 index 0000000000..86d4363105 --- /dev/null +++ b/docs/config/changelog.md @@ -0,0 +1,8 @@ +# Changelog Options + + + + +As for now, each of the options that is used by `cz changelog` command can correlate to a command line option. + +See [changelog command line options](../commands/changelog.md#command-line-options) for more details. diff --git a/docs/config/check.md b/docs/config/check.md new file mode 100644 index 0000000000..2c8dda27b4 --- /dev/null +++ b/docs/config/check.md @@ -0,0 +1,27 @@ +# Check Options + + + +## `allow_abort` + +- Type: `bool` +- Default: `False` + +Disallow empty commit messages. Useful in CI. + +## `allowed_prefixes` + +- Type: `list` +- Default: `["Merge", "Revert", "Pull request", "fixup!", "squash!"]` + +List of prefixes that commitizen ignores when verifying messages. + +## `message_length_limit` + +- Type: `int` +- Default: `0` (no limit) + +Maximum length of the commit message. Setting it to `0` disables the length limit. + +!!! note + This option can be overridden by the `-l/--message-length-limit` command line argument. diff --git a/docs/config/commit.md b/docs/config/commit.md new file mode 100644 index 0000000000..72fdff947c --- /dev/null +++ b/docs/config/commit.md @@ -0,0 +1,26 @@ +# Commit Options + + + +## `breaking_change_exclamation_in_title` + +- Type: `bool` +- Default: `False` + +When true, breaking changes will be also indicated by an exclamation mark in the commit title (e.g., `feat!: breaking change`). + +When false, breaking changes will be only indicated by `BREAKING CHANGE:` in the footer. See [writing commits](../tutorials/writing_commits.md) for more details. + +## `encoding` + +- Type: `str` +- Default: `"utf-8"` + +Sets the character encoding to be used when parsing commit messages. + +## `retry_after_failure` + +- Type: `bool` +- Default: `False` + +Retries failed commit when running `cz commit`. diff --git a/docs/config/configuration_file.md b/docs/config/configuration_file.md new file mode 100644 index 0000000000..8469102550 --- /dev/null +++ b/docs/config/configuration_file.md @@ -0,0 +1,234 @@ +# Configuration File + +Commitizen uses configuration files to customize its behavior for your project. These files define settings such as which commit rules to use, version management preferences, changelog generation options, and more. + +## Creating a Configuration File + +It is recommended to create a configuration file via our [`cz init`](../commands/init.md) command. This command will guide you through setting up your configuration file with the appropriate settings for your project. + +## File Location and Search Order + +Configuration files are typically located in the root of your project directory. Commitizen searches for configuration files in the following order: + +1. `pyproject.toml` (in the `[tool.commitizen]` section) +2. `.cz.toml` +3. `.cz.json` +4. `cz.json` +5. `.cz.yaml` +6. `cz.yaml` +7. `cz.toml` + +The first valid configuration file found will be used. If no configuration file is found, Commitizen will use its default settings. + +!!! tip + For Python projects, it's recommended to add your Commitizen configuration to `pyproject.toml` to keep all project configuration in one place. + +## Supported Formats + +Commitizen supports three configuration file formats: + +- **TOML** (`.toml`) - Recommended for Python projects +- **JSON** (`.json`) +- **YAML** (`.yaml`) + +All formats support the same configuration options. Choose the format that best fits your project's ecosystem. + +## Configuration Structure + +### TOML Format + +For TOML files, Commitizen settings are placed under the `[tool.commitizen]` section. If you're using a standalone `.cz.toml` or `cz.toml` file, you can use `[tool.commitizen]` or just `[commitizen]`. + +**Example: `pyproject.toml`, `.cz.toml` or `cz.toml`** + +```toml title="pyproject.toml" +[tool.commitizen] +name = "cz_conventional_commits" +version = "0.1.0" +version_provider = "commitizen" +version_scheme = "pep440" +version_files = [ + "src/__version__.py", + "pyproject.toml:version" +] +tag_format = "$version" +update_changelog_on_bump = true +changelog_file = "CHANGELOG.md" +changelog_incremental = false +bump_message = "bump: version $current_version → $new_version" +gpg_sign = false +annotated_tag = false +major_version_zero = false +prerelease_offset = 0 +retry_after_failure = false +allow_abort = false +message_length_limit = 0 +allowed_prefixes = [ + "Merge", + "Revert", + "Pull request", + "fixup!", + "squash!", + "amend!" +] +breaking_change_exclamation_in_title = false +use_shortcuts = false +pre_bump_hooks = [] +post_bump_hooks = [] +encoding = "utf-8" + +# Optional: Custom styling for prompts +style = [ + ["qmark", "fg:#ff9d00 bold"], + ["question", "bold"], + ["answer", "fg:#ff9d00 bold"], + ["pointer", "fg:#ff9d00 bold"], + ["highlighted", "fg:#ff9d00 bold"], + ["selected", "fg:#cc5454"], + ["separator", "fg:#cc5454"], + ["instruction", ""], + ["text", ""], + ["disabled", "fg:#858585 italic"] +] +``` + +### JSON Format + +For JSON files, Commitizen settings are placed under the `commitizen` key. + +**Example: `.cz.json` or `cz.json`** + +```json title=".cz.json" +{ + "commitizen": { + "name": "cz_conventional_commits", + "version": "0.1.0", + "version_provider": "commitizen", + "version_scheme": "pep440", + "version_files": [ + "src/__version__.py", + "pyproject.toml:version" + ], + "tag_format": "$version", + "update_changelog_on_bump": true, + "changelog_file": "CHANGELOG.md", + "changelog_incremental": false, + "bump_message": "bump: version $current_version → $new_version", + "gpg_sign": false, + "annotated_tag": false, + "major_version_zero": false, + "prerelease_offset": 0, + "retry_after_failure": false, + "allow_abort": false, + "message_length_limit": 0, + "allowed_prefixes": [ + "Merge", + "Revert", + "Pull request", + "fixup!", + "squash!", + "amend!" + ], + "breaking_change_exclamation_in_title": false, + "use_shortcuts": false, + "pre_bump_hooks": [], + "post_bump_hooks": [], + "encoding": "utf-8", + "style": [ + ["qmark", "fg:#ff9d00 bold"], + ["question", "bold"], + ["answer", "fg:#ff9d00 bold"], + ["pointer", "fg:#ff9d00 bold"], + ["highlighted", "fg:#ff9d00 bold"], + ["selected", "fg:#cc5454"], + ["separator", "fg:#cc5454"], + ["instruction", ""], + ["text", ""], + ["disabled", "fg:#858585 italic"] + ] + } +} +``` + +### YAML Format + +For YAML files, Commitizen settings are placed under the `commitizen` key. + +**Example: `.cz.yaml` or `cz.yaml`** + +```yaml title=".cz.yaml" +commitizen: + name: cz_conventional_commits + version: "0.1.0" + version_provider: commitizen + version_scheme: pep440 + version_files: + - src/__version__.py + - pyproject.toml:version + tag_format: "$version" + update_changelog_on_bump: true + changelog_file: CHANGELOG.md + changelog_incremental: false + bump_message: "bump: version $current_version → $new_version" + gpg_sign: false + annotated_tag: false + major_version_zero: false + prerelease_offset: 0 + retry_after_failure: false + allow_abort: false + message_length_limit: 0 + allowed_prefixes: + - Merge + - Revert + - Pull request + - fixup! + - squash! + - amend! + breaking_change_exclamation_in_title: false + use_shortcuts: false + pre_bump_hooks: [] + post_bump_hooks: [] + encoding: utf-8 + style: + - - qmark + - fg:#ff9d00 bold + - - question + - bold + - - answer + - fg:#ff9d00 bold + - - pointer + - fg:#ff9d00 bold + - - highlighted + - fg:#ff9d00 bold + - - selected + - fg:#cc5454 + - - separator + - fg:#cc5454 + - - instruction + - "" + - - text + - "" + - - disabled + - fg:#858585 italic +``` + +## Configuration Options + +For a complete list of all available configuration options and their descriptions, see the [Configuration Settings](../config/option.md) documentation. + +Key configuration categories include: + +- **Commit Rules**: `name` - Select which commit convention to use +- **Version Management**: `version`, `version_provider`, `version_scheme`, `version_files` +- **Tagging**: `tag_format`, `legacy_tag_formats`, `ignored_tag_formats`, `gpg_sign`, `annotated_tag` +- **Changelog**: `changelog_file`, `changelog_format`, `changelog_incremental`, `update_changelog_on_bump` +- **Bumping**: `bump_message`, `major_version_zero`, `prerelease_offset`, `pre_bump_hooks`, `post_bump_hooks` +- **Commit Validation**: `allowed_prefixes`, `message_length_limit`, `allow_abort`, `retry_after_failure` +- **Customization**: `customize`, `style`, `use_shortcuts`, `template`, `extras` + +## Customization + +For advanced customization, including creating custom commit rules, see the [Customization](../customization/config_file.md) documentation. + +!!! note + The `customize` option is only supported when using TOML configuration files. diff --git a/docs/config/option.md b/docs/config/option.md new file mode 100644 index 0000000000..5b7ce807b3 --- /dev/null +++ b/docs/config/option.md @@ -0,0 +1,38 @@ +# Misc Options + +## `name` + +- Type: `str` +- Default: `"cz_conventional_commits"` + +Name of the committing rules to use. + +## `version` + +- Type: `str` +- Default: `None` + +Current version. Example: `"0.1.2"`. Required if you use `version_provider = "commitizen"`. + +## `style` + +- Type: `list` +- Default: `[]` + +Style for the prompts (It will merge this value with default style.) See [Styling your prompts with your favorite colors](https://github.com/tmbo/questionary#additional-features) for more details. + +## `customize` + +- Type: `dict` +- Default: `None` + +**This is only supported when config through `toml` configuration file.** + +Custom rules for committing and bumping. See [customization](../customization/config_file.md) for more details. + +## `use_shortcuts` + +- Type: `bool` +- Default: `False` + +Show keyboard shortcuts when selecting from a list. Define a `key` for each of your choices to set the key. See [shortcut keys](../customization/config_file.md#shortcut-keys) for more details. diff --git a/docs/config/version_provider.md b/docs/config/version_provider.md new file mode 100644 index 0000000000..4f070b2fd3 --- /dev/null +++ b/docs/config/version_provider.md @@ -0,0 +1,318 @@ +# Version Providers + +Version providers are the mechanism by which Commitizen reads and writes version information in your project. + +They abstract away the details of where and how version numbers are stored, allowing Commitizen to work seamlessly with different project types and package management systems. + +## Overview + +By default, Commitizen uses the `commitizen` provider, which stores the version in your Commitizen configuration file. +However, you can configure Commitizen to use any available provider that matches your project's setup. +This is particularly useful when you want Commitizen to manage versions in the same location as your package manager (e.g., `package.json` for Node.js projects, `pyproject.toml` for Python projects). + +## Built-in Providers + +Commitizen includes several built-in version providers for common package management formats: + +### `commitizen` (Default) + +The default version provider stores and retrieves the version from your Commitizen configuration file (e.g., `pyproject.toml`, `.cz.toml`, etc.). + +**Use when:** +- You want to keep version management separate from your package manager +- Your project doesn't use a standard package manager +- You need maximum flexibility in version management + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "commitizen" +version = "0.1.0" # Required when using this provider +``` + +### `scm` + +Fetches the version from Git tags using `git describe`. This provider **only reads** version information and never writes it back to files. It's designed to work with tools like `setuptools-scm` or other package manager `*-scm` plugins that derive version numbers from Git history. + +**Use when:** +- You're using `setuptools-scm` or similar tools +- You want version numbers derived from Git tags +- You don't want Commitizen to modify any files for version management + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "scm" +# No version field needed - it's read from Git tags +``` + +!!! note + The `scm` provider is read-only. When you run `cz bump`, it will create a Git tag but won't update any files. This is intentional and works well with tools that derive versions from Git tags. + +### `pep621` + +Manages version in `pyproject.toml` under the `project.version` field, following [PEP 621](https://peps.python.org/pep-0621/) standards. + +**Use when:** +- You're using a modern Python project with PEP 621-compliant `pyproject.toml` +- You want version management integrated with your Python project metadata + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "pep621" +``` + +**Example `pyproject.toml`:** +```toml +[project] +name = "my-package" +version = "0.1.0" # Managed by Commitizen +``` + +### `poetry` + +Manages version in `pyproject.toml` under the `tool.poetry.version` field, which is used by the [Poetry](https://python-poetry.org/) package manager. This approach is recommended only for users running Poetry versions earlier than 2.0 or relying on Poetry-specific features. For most users on Poetry 2.0 or later, it is recommended to use `pep621` instead. [Read More](https://python-poetry.org/docs/main/managing-dependencies/) + +**Use when:** +- You're using Poetry < 2.0 as your Python package manager +- You're using Poetry >= 2.0 as your Python package manager, but don't need poetry-specific features +- You want Commitizen to manage the version that Poetry uses + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "poetry" +``` + +**Example `pyproject.toml`:** +```toml +[tool.poetry] +name = "my-package" +version = "0.1.0" # Managed by Commitizen +``` + +### `uv` + +Manages version in both `pyproject.toml` (`project.version`) and `uv.lock` (`package.version` for the matching package name). This ensures consistency between your project metadata and lock file. + + +!!! note + Even though uv follows PEP 621 format, `pep621` does not manage the version in `uv.lock`. `uv` is still suggested for uv users. + +**Use when:** +- You're using `uv` as your Python package manager +- You want version synchronization between `pyproject.toml` and `uv.lock` + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "uv" +``` + +### `cargo` + +Manages version in both `Cargo.toml` (`package.version`) and `Cargo.lock` (`package.version` for the matching package name). This ensures consistency between your Rust project's manifest and lock file. + +**Use when:** +- You're working with a Rust project using Cargo +- You want Commitizen to manage Rust package versions + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "cargo" +``` + +**Example `Cargo.toml`:** +```toml +[package] +name = "my-crate" +version = "0.1.0" # Managed by Commitizen +``` + +### `npm` + +Manages version in `package.json` and optionally synchronizes with `package-lock.json` and `npm-shrinkwrap.json` if they exist. + +**Use when:** +- You're working with a Node.js/JavaScript project +- You want Commitizen to manage npm package versions + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "npm" +``` + +**Example `package.json`:** +```json +{ + "name": "my-package", + "version": "0.1.0" +} +``` + +### `composer` + +Manages version in `composer.json` under the `version` field, used by PHP's Composer package manager. + +**Use when:** +- You're working with a PHP project using Composer +- You want Commitizen to manage Composer package versions + +**Configuration:** +```toml +[tool.commitizen] +version_provider = "composer" +``` + +**Example `composer.json`:** +```json +{ + "name": "vendor/package", + "version": "0.1.0" +} +``` + +## Provider Comparison Table + +| Provider | File(s) Modified | Read-Only | Best For | +| ------------ | ----------------------------------- | --------- | --------------------------------- | +| `commitizen` | Commitizen config file | No | General use, flexible projects | +| `scm` | None (reads from Git tags) | Yes | `setuptools-scm` users | +| `pep621` | `pyproject.toml` (`project.version`) | No | Modern Python (PEP 621) | +| `poetry` | `pyproject.toml` (`tool.poetry.version`) | No | Poetry projects | +| `uv` | `pyproject.toml` + `uv.lock` | No | uv package manager | +| `cargo` | `Cargo.toml` + `Cargo.lock` | No | Rust/Cargo projects | +| `npm` | `package.json` (+ lock files) | No | Node.js/npm projects | +| `composer` | `composer.json` | No | PHP/Composer projects | + +## Creating Custom Version Providers + +If none of the built-in providers meet your needs, you can create a custom version provider by extending the `VersionProvider` base class and registering it as a plugin. + +### Step 1: Create Your Provider Class + +Create a Python file (e.g., `my_provider.py`) that extends `VersionProvider`: + +```python title="my_provider.py" +from pathlib import Path +from commitizen.providers import VersionProvider + + +class MyProvider(VersionProvider): + """ + Custom version provider that reads/writes from a VERSION file. + """ + + def get_version(self) -> str: + """Read version from VERSION file.""" + version_file = Path("VERSION") + if not version_file.exists(): + return "0.0.0" + return version_file.read_text().strip() + + def set_version(self, version: str) -> None: + """Write version to VERSION file.""" + version_file = Path("VERSION") + version_file.write_text(f"{version}\n") +``` + +### Step 2: Register as an Entry Point + +Register your provider using the `commitizen.provider` entry point. You can do this in your `setup.py`, `setup.cfg`, or `pyproject.toml`: + +**Using `pyproject.toml` (recommended):** + +```toml title="pyproject.toml" +[project] +name = "my-commitizen-provider" +version = "0.1.0" +dependencies = ["commitizen"] + +[project.entry-points."commitizen.provider"] +my-provider = "my_provider:MyProvider" +``` + +**Using `setup.py` (for legacy setup):** + +```python title="setup.py" +from setuptools import setup + +setup( + name="my-commitizen-provider", + version="0.1.0", + py_modules=["my_provider"], + install_requires=["commitizen"], + entry_points={ + "commitizen.provider": [ + "my-provider = my_provider:MyProvider", + ] + }, +) +``` + +### Step 3: Install and Use + +1. Install your provider package: + ```bash + pip install -e . + ``` + +2. Configure Commitizen to use your provider: + ```toml + [tool.commitizen] + version_provider = "my-provider" + ``` + +### Provider Implementation Guidelines + +When creating a custom provider, keep these guidelines in mind: + +- **`get_version()`** should return a string representing the current version. If no version is found, you can return `"0.0.0"` or raise an appropriate exception. +- **`set_version(version: str)`** should write the version to your chosen storage location. The version string will be properly formatted according to your `version_scheme` setting. +- The provider has access to `self.config`, which is a `BaseConfig` instance containing all Commitizen settings. +- For file-based providers, consider using the `FileProvider` or `JsonProvider`/`TomlProvider` base classes from `commitizen.providers.base_provider` to simplify implementation. + +### Example: JSON-based Provider + +Here's a more complete example using the `JsonProvider` base class: + +```python title="json_version_provider.py" +from commitizen.providers.base_provider import JsonProvider + + +class JsonVersionProvider(JsonProvider): + """ + Version provider that uses a custom version.json file. + """ + + filename = "version.json" + + def get(self, document): + """Extract version from JSON document.""" + return document["version"] + + def set(self, document, version): + """Set version in JSON document.""" + document["version"] = version +``` + +This example leverages the `JsonProvider` base class, which handles file reading, writing, and JSON parsing automatically. + +## Choosing the Right Provider + +Select a version provider based on your project's characteristics: + +- **Python projects** + - **with `uv`**: Use `uv` + - **with `pyproject.toml` that follows PEP 621**: Use `pep621` + - **with Poetry**: Use `poetry` + - **setuptools-scm**: Use `scm` +- **Rust projects**: Use `cargo` +- **Node.js projects**: Use `npm` +- **PHP projects**: Use `composer` +- **Other cases or custom needs**: Use `commitizen` (default) or create a custom provider + +Remember that you can always use `version_files` in combination with any provider to update additional files during version bumps, regardless of which provider you choose for reading/writing the primary version. diff --git a/docs/customization.md b/docs/customization.md deleted file mode 100644 index 50bb0c8fbb..0000000000 --- a/docs/customization.md +++ /dev/null @@ -1,529 +0,0 @@ -Customizing Commitizen is not hard at all. -We have two different ways to do so. - -## 1. Customize in configuration file - -The basic steps are: - -1. Define your custom committing or bumping rules in the configuration file. -2. Declare `name = "cz_customize"` in your configuration file, or add `-n cz_customize` when running Commitizen. - -Example: - -```toml title="pyproject.toml" -[tool.commitizen] -name = "cz_customize" - -[tool.commitizen.customize] -message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}" -example = "feature: this feature enable customize through config file" -schema = ": " -schema_pattern = "(feature|bug fix):(\\s.*)" -bump_pattern = "^(break|new|fix|hotfix)" -bump_map = {"break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH"} -change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"] -info_path = "cz_customize_info.txt" -info = """ -This is customized info -""" -commit_parser = "^(?Pfeature|bug fix):\\s(?P.*)?" -changelog_pattern = "^(feature|bug fix)?(!)?" -change_type_map = {"feature" = "Feat", "bug fix" = "Fix"} - -[[tool.commitizen.customize.questions]] -type = "list" -name = "change_type" -choices = [{value = "feature", name = "feature: A new feature."}, {value = "bug fix", name = "bug fix: A bug fix."}] -# choices = ["feature", "fix"] # short version -message = "Select the type of change you are committing" - -[[tool.commitizen.customize.questions]] -type = "input" -name = "message" -message = "Body." - -[[tool.commitizen.customize.questions]] -type = "confirm" -name = "show_message" -message = "Do you want to add body message in commit?" -``` - -The equivalent example for a json config file: - -```json title=".cz.json" -{ - "commitizen": { - "name": "cz_customize", - "customize": { - "message_template": "{{change_type}}:{% if show_message %} {{message}}{% endif %}", - "example": "feature: this feature enable customize through config file", - "schema": ": ", - "schema_pattern": "(feature|bug fix):(\\s.*)", - "bump_pattern": "^(break|new|fix|hotfix)", - "bump_map": { - "break": "MAJOR", - "new": "MINOR", - "fix": "PATCH", - "hotfix": "PATCH" - }, - "change_type_order": ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"], - "info_path": "cz_customize_info.txt", - "info": "This is customized info", - "commit_parser": "^(?Pfeature|bug fix):\\s(?P.*)?", - "changelog_pattern": "^(feature|bug fix)?(!)?", - "change_type_map": {"feature": "Feat", "bug fix": "Fix"}, - "questions": [ - { - "type": "list", - "name": "change_type", - "choices": [ - { - "value": "feature", - "name": "feature: A new feature." - }, - { - "value": "bug fix", - "name": "bug fix: A bug fix." - } - ], - "message": "Select the type of change you are committing" - }, - { - "type": "input", - "name": "message", - "message": "Body." - }, - { - "type": "confirm", - "name": "show_message", - "message": "Do you want to add body message in commit?" - } - ] - } - } -} -``` - -And the correspondent example for a yaml file: - -```yaml title=".cz.yaml" -commitizen: - name: cz_customize - customize: - message_template: '{{change_type}}:{% if show_message %} {{message}}{% endif %}' - example: 'feature: this feature enable customize through config file' - schema: ': ' - schema_pattern: '(feature|bug fix):(\\s.*)' - bump_pattern: '^(break|new|fix|hotfix)' - commit_parser: '^(?Pfeature|bug fix):\\s(?P.*)?' - changelog_pattern: '^(feature|bug fix)?(!)?' - change_type_map: - feature: Feat - bug fix: Fix - bump_map: - break: MAJOR - new: MINOR - fix: PATCH - hotfix: PATCH - change_type_order: ['BREAKING CHANGE', 'feat', 'fix', 'refactor', 'perf'] - info_path: cz_customize_info.txt - info: This is customized info - questions: - - type: list - name: change_type - choices: - - value: feature - name: 'feature: A new feature.' - - value: bug fix - name: 'bug fix: A bug fix.' - message: Select the type of change you are committing - - type: input - name: message - message: 'Body.' - - type: confirm - name: show_message - message: 'Do you want to add body message in commit?' -``` - -### Customize configuration - -| Parameter | Type | Default | Description | -| ------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `questions` | `Questions` | `None` | Questions regarding the commit message. Detailed below. The type `Questions` is an alias to `Iterable[MutableMapping[str, Any]]` which is defined in `commitizen.defaults`. It expects a list of dictionaries. | -| `message_template` | `str` | `None` | The template for generating message from the given answers. `message_template` should either follow [Jinja2][jinja2] formatting specification, and all the variables in this template should be defined in `name` in `questions` | -| `example` | `str` | `""` | (OPTIONAL) Provide an example to help understand the style. Used by `cz example`. | -| `schema` | `str` | `""` | (OPTIONAL) Show the schema used. Used by `cz schema`. | -| `schema_pattern` | `str` | `""` | (OPTIONAL) The regular expression used to do commit message validation. Used by `cz check`. | -| `info_path` | `str` | `""` | (OPTIONAL) The path to the file that contains explanation of the commit rules. Used by `cz info`. If not provided `cz info`, will load `info` instead. | -| `info` | `str` | `""` | (OPTIONAL) Explanation of the commit rules. Used by `cz info`. | -| `bump_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | -| `bump_pattern` | `str` | `None` | (OPTIONAL) Regex to extract information from commit (subject and body) | -| `change_type_order` | `str` | `None` | (OPTIONAL) List of strings used to order the Changelog. All other types will be sorted alphabetically. Default is `["BREAKING CHANGE", "Feat", "Fix", "Refactor", "Perf"]` | -| `commit_parser` | `str` | `None` | (OPTIONAL) Regex to extract information used in creating changelog. [See more][changelog-spec] | -| `changelog_pattern` | `str` | `None` | (OPTIONAL) Regex to understand which commits to include in the changelog | -| `change_type_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the type of the commit to a changelog entry | - -[jinja2]: https://jinja.palletsprojects.com/en/2.10.x/ -[changelog-spec]: https://commitizen-tools.github.io/commitizen/commands/changelog/ - -#### Detailed `questions` content - -| Parameter | Type | Default | Description | -| ----------- | ------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `type` | `str` | `None` | The type of questions. Valid types: `list`, `select`, `input`, etc. The `select` type provides an interactive searchable list interface. [See More][different-question-types] | -| `name` | `str` | `None` | The key for the value answered by user. It's used in `message_template` | -| `message` | `str` | `None` | Detail description for the question. | -| `choices` | `list` | `None` | (OPTIONAL) The choices when `type = list` or `type = select`. Either use a list of values or a list of dictionaries with `name` and `value` keys. Keyboard shortcuts can be defined via `key`. See examples above. | -| `default` | `Any` | `None` | (OPTIONAL) The default value for this question. | -| `filter` | `str` | `None` | (OPTIONAL) Validator for user's answer. **(Work in Progress)** | -| `multiline` | `bool` | `False` | (OPTIONAL) Enable multiline support when `type = input`. | -| `use_search_filter` | `bool` | `False` | (OPTIONAL) Enable search/filter functionality for list/select type questions. This allows users to type and filter through the choices. | -| `use_jk_keys` | `bool` | `True` | (OPTIONAL) Enable/disable j/k keys for navigation in list/select type questions. Set to false if you prefer arrow keys only. | - -[different-question-types]: https://github.com/tmbo/questionary#different-question-types - -#### Shortcut keys - -When the [`use_shortcuts`](config.md#settings) config option is enabled, Commitizen can show and use keyboard shortcuts to select items from lists directly. -For example, when using the `cz_conventional_commits` Commitizen template, shortcut keys are shown when selecting the commit type. Unless otherwise defined, keyboard shortcuts will be numbered automatically. -To specify keyboard shortcuts for your custom choices, provide the shortcut using the `key` parameter in dictionary form for each choice you would like to customize. - -## 2. Customize through customizing a class - -The basic steps are: - -1. Inheriting from `BaseCommitizen`. -2. Give a name to your rules. -3. Create a python package using `setup.py`, `poetry`, etc. -4. Expose the class as a `commitizen.plugin` entrypoint. - -Check an [example][convcomms] on how to configure `BaseCommitizen`. - -You can also automate the steps above through [cookiecutter](https://cookiecutter.readthedocs.io/en/1.7.0/). - -```sh -cookiecutter gh:commitizen-tools/commitizen_cz_template -``` - -See [commitizen_cz_template](https://github.com/commitizen-tools/commitizen_cz_template) for details. - -Once you publish your rules, you can send us a PR to the [Third-party section](./third-party-plugins/about.md). - -### Custom commit rules - -Create a Python module, for example `cz_jira.py`. - -Inherit from `BaseCommitizen`, and you must define `questions` and `message`. The others are optional. - -```python title="cz_jira.py" -from commitizen.cz.base import BaseCommitizen -from commitizen.defaults import Questions - - -class JiraCz(BaseCommitizen): - # Questions = Iterable[MutableMapping[str, Any]] - # It expects a list with dictionaries. - def questions(self) -> Questions: - """Questions regarding the commit message.""" - questions = [ - {"type": "input", "name": "title", "message": "Commit title"}, - {"type": "input", "name": "issue", "message": "Jira Issue number:"}, - ] - return questions - - def message(self, answers: dict) -> str: - """Generate the message with the given answers.""" - return "{0} (#{1})".format(answers["title"], answers["issue"]) - - def example(self) -> str: - """Provide an example to help understand the style (OPTIONAL) - - Used by `cz example`. - """ - return "Problem with user (#321)" - - def schema(self) -> str: - """Show the schema used (OPTIONAL) - - Used by `cz schema`. - """ - return " (<issue>)" - - def info(self) -> str: - """Explanation of the commit rules. (OPTIONAL) - - Used by `cz info`. - """ - return "We use this because is useful" -``` - -The next file required is `setup.py` modified from flask version. - -```python title="setup.py" -from setuptools import setup - -setup( - name="JiraCommitizen", - version="0.1.0", - py_modules=["cz_jira"], - license="MIT", - long_description="this is a long description", - install_requires=["commitizen"], - entry_points={"commitizen.plugin": ["cz_jira = cz_jira:JiraCz"]}, -) -``` - -So in the end, we would have - - . - ├── cz_jira.py - └── setup.py - -And that's it. You can install it without uploading to pypi by simply -doing `pip install .` - -If you feel like it should be part of this repo, create a PR. - -### Custom bump rules - -You need to define 2 parameters inside your custom `BaseCommitizen`. - -| Parameter | Type | Default | Description | -| -------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | -| `bump_pattern` | `str` | `None` | Regex to extract information from commit (subject and body) | -| `bump_map` | `dict` | `None` | Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | - -Let's see an example. - -```python title="cz_strange.py" -from commitizen.cz.base import BaseCommitizen - - -class StrangeCommitizen(BaseCommitizen): - bump_pattern = r"^(break|new|fix|hotfix)" - bump_map = {"break": "MAJOR", "new": "MINOR", "fix": "PATCH", "hotfix": "PATCH"} -``` - -That's it, your Commitizen now supports custom rules, and you can run. - -```bash -cz -n cz_strange bump -``` - -[convcomms]: https://github.com/commitizen-tools/commitizen/blob/master/commitizen/cz/conventional_commits/conventional_commits.py - -### Custom changelog generator - -The changelog generator should just work in a very basic manner without touching anything. -You can customize it of course, and the following variables are the ones you need to add to your custom `BaseCommitizen`. - -| Parameter | Type | Required | Description | -| -------------------------------- | ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `commit_parser` | `str` | NO | Regex which should provide the variables explained in the [changelog description][changelog-des] | -| `changelog_pattern` | `str` | NO | Regex to validate the commits, this is useful to skip commits that don't meet your ruling standards like a Merge. Usually the same as bump_pattern | -| `change_type_map` | `dict` | NO | Convert the title of the change type that will appear in the changelog, if a value is not found, the original will be provided | -| `changelog_message_builder_hook` | `method: (dict, git.GitCommit) -> dict | list | None` | NO | Customize with extra information your message output, like adding links, this function is executed per parsed commit. Each GitCommit contains the following attrs: `rev`, `title`, `body`, `author`, `author_email`. Returning a falsy value ignore the commit. | -| `changelog_hook` | `method: (full_changelog: str, partial_changelog: Optional[str]) -> str` | NO | Receives the whole and partial (if used incremental) changelog. Useful to send slack messages or notify a compliance department. Must return the full_changelog | -| `changelog_release_hook` | `method: (release: dict, tag: git.GitTag) -> dict` | NO | Receives each generated changelog release and its associated tag. Useful to enrich releases before they are rendered. Must return the update release - -```python title="cz_strange.py" -from commitizen.cz.base import BaseCommitizen -import chat -import compliance - - -class StrangeCommitizen(BaseCommitizen): - changelog_pattern = r"^(break|new|fix|hotfix)" - commit_parser = r"^(?P<change_type>feat|fix|refactor|perf|BREAKING CHANGE)(?:\((?P<scope>[^()\r\n]*)\)|\()?(?P<breaking>!)?:\s(?P<message>.*)?" - change_type_map = { - "feat": "Features", - "fix": "Bug Fixes", - "refactor": "Code Refactor", - "perf": "Performance improvements", - } - - def changelog_message_builder_hook( - self, parsed_message: dict, commit: git.GitCommit - ) -> dict | list | None: - rev = commit.rev - m = parsed_message["message"] - parsed_message[ - "message" - ] = f"{m} {rev} [{commit.author}]({commit.author_email})" - return parsed_message - - def changelog_release_hook(self, release: dict, tag: git.GitTag) -> dict: - release["author"] = tag.author - return release - - def changelog_hook( - self, full_changelog: str, partial_changelog: Optional[str] - ) -> str: - """Executed at the end of the changelog generation - - full_changelog: it's the output about to being written into the file - partial_changelog: it's the new stuff, this is useful to send slack messages or - similar - - Return: - the new updated full_changelog - """ - if partial_changelog: - chat.room("#committers").notify(partial_changelog) - if full_changelog: - compliance.send(full_changelog) - full_changelog.replace(" fix ", " **fix** ") - return full_changelog -``` - -### Raise Customize Exception - -If you want `commitizen` to catch your exception and print the message, you'll have to inherit `CzException`. - -```python -from commitizen.cz.exception import CzException - - -class NoSubjectProvidedException(CzException): - ... -``` - -### Migrating from legacy plugin format - -Commitizen migrated to a new plugin format relying on `importlib.metadata.EntryPoint`. -Migration should be straight-forward for legacy plugins: - -- Remove the `discover_this` line from your plugin module -- Expose the plugin class under as a `commitizen.plugin` entrypoint. - -The name of the plugin is now determined by the name of the entrypoint. - -#### Example - -If you were having a `CzPlugin` class in a `cz_plugin.py` module like this: - -```python -from commitizen.cz.base import BaseCommitizen - - -class PluginCz(BaseCommitizen): - ... - - -discover_this = PluginCz -``` - -Then remove the `discover_this` line: - -```python -from commitizen.cz.base import BaseCommitizen - - -class PluginCz(BaseCommitizen): - ... -``` - -and expose the class as entrypoint in you setuptools: - -```python -from setuptools import setup - -setup( - name="MyPlugin", - version="0.1.0", - py_modules=["cz_plugin"], - entry_points={"commitizen.plugin": ["plugin = cz_plugin:PluginCz"]}, - ..., -) -``` - -Then your plugin will be available under the name `plugin`. - -## Customizing the changelog template - -Commitizen gives you the possibility to provide your own changelog template, by: - -- providing one with your customization class -- providing one from the current working directory and setting it: - - as [configuration][template-config] - - as `--template` parameter to both `bump` and `changelog` commands -- either by providing a template with the same name as the default template - -By default, the template used is the `CHANGELOG.md.j2` file from the Commitizen repository. - -### Providing a template with your customization class - -There are 3 parameters available to change the template rendering from your custom `BaseCommitizen`. - -| Parameter | Type | Default | Description | -| ----------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | -| `template` | `str` | `None` | Provide your own template name (default to `CHANGELOG.md.j2`) | -| `template_loader` | `str` | `None` | Override the default template loader (so you can provide template from your customization class) | -| `template_extras` | `dict` | `None` | Provide some extra template parameters | - -Let's see an example. - -```python -from commitizen.cz.base import BaseCommitizen -from jinja2 import PackageLoader - - -class MyPlugin(BaseCommitizen): - template = "CHANGELOG.md.jinja" - template_loader = PackageLoader("my_plugin", "templates") - template_extras = {"key": "value"} -``` - -This snippet will: - -- use `CHANGELOG.md.jinja` as template name -- search for it in the `templates` directory for `my_plugin` package -- add the `key=value` variable in the template - -### Providing a template from the current working directory - -Users can provide their own template from their current working directory (your project root) by: - -- providing a template with the same name (`CHANGELOG.md.j2` unless overridden by your custom class) -- setting your template path as `template` configuration -- giving your template path as `--template` parameter to `bump` and `changelog` commands - -!!! note - The path is relative to the current working directory, aka your project root most of the time. - -### Template variables - -The default template use a single `tree` variable which is a list of entries (a release) with the following format: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| version | `str` | The release version | -| date | `datetime` | The release date | -| changes | `list[tuple[str, list[Change]]]` | The release sorted changes list in the form `(type, changes)` | - -Each `Change` has the following fields: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| scope | `str | None` | An optional scope | -| message | `str` | The commit message body | -| sha1 | `str` | The commit `sha1` | -| parents | `list[str]` | The parent commit(s) `sha1`(s) | -| author | `str` | The commit author name | -| author_email | `str` | The commit author email | - -!!! note - The field values depend on the customization class and/or the settings you provide - -The `parents` field can be used to identify merge commits and generate a changelog based on those. Another use case -is listing commits that belong to the same pull request. - -When using another template (either provided by a plugin or by yourself), you can also pass extra template variables -by: - -- defining them in your configuration with the [`extras` settings][extras-config] -- providing them on the command line with the `--extra/-e` parameter to `bump` and `changelog` commands - -[template-config]: config.md#template -[extras-config]: config.md#extras -[changelog-des]: ./commands/changelog.md#description diff --git a/docs/customization/changelog_template.md b/docs/customization/changelog_template.md new file mode 100644 index 0000000000..60f40ebea7 --- /dev/null +++ b/docs/customization/changelog_template.md @@ -0,0 +1,85 @@ + +# Customizing the changelog template + +Commitizen gives you the possibility to provide your own changelog template, by: + +- providing one with your customization class +- providing one from the current working directory and setting it: + - Through the configuration file + - as `--template` parameter to both `bump` and `changelog` commands +- either by providing a template with the same name as the default template + +By default, the template used is the `CHANGELOG.md.j2` file from the Commitizen repository. + +## Providing a template with your customization class + +There are 3 parameters available to change the template rendering from your custom `BaseCommitizen`. + +| Parameter | Type | Default | Description | +| ----------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | +| `template` | `str` | `None` | Provide your own template name (default to `CHANGELOG.md.j2`) | +| `template_loader` | `str` | `None` | Override the default template loader (so you can provide template from your customization class) | +| `template_extras` | `dict` | `None` | Provide some extra template parameters | + +Let's see an example. + +```python +from commitizen.cz.base import BaseCommitizen +from jinja2 import PackageLoader + + +class MyPlugin(BaseCommitizen): + template = "CHANGELOG.md.jinja" + template_loader = PackageLoader("my_plugin", "templates") + template_extras = {"key": "value"} +``` + +This snippet will: + +- use `CHANGELOG.md.jinja` as template name +- search for it in the `templates` directory for `my_plugin` package +- add the `key=value` variable in the template + +## Providing a template from the current working directory + +Users can provide their own template from their current working directory (your project root) by: + +- providing a template with the same name (`CHANGELOG.md.j2` unless overridden by your custom class) +- setting your template path as `template` configuration +- giving your template path as `--template` parameter to `bump` and `changelog` commands + +!!! note + The path is relative to the current working directory, aka your project root most of the time. + +## Template variables + +The default template use a single `tree` variable which is a list of entries (a release) with the following format: + +| Name | Type | Description | +| ---- | ---- | ----------- | +| version | `str` | The release version | +| date | `datetime` | The release date | +| changes | `list[tuple[str, list[Change]]]` | The release sorted changes list in the form `(type, changes)` | + +Each `Change` has the following fields: + +| Name | Type | Description | +| ---- | ---- | ----------- | +| scope | `str | None` | An optional scope | +| message | `str` | The commit message body | +| sha1 | `str` | The commit `sha1` | +| parents | `list[str]` | The parent commit(s) `sha1`(s) | +| author | `str` | The commit author name | +| author_email | `str` | The commit author email | + +!!! note + The field values depend on the customization class and/or the settings you provide + +The `parents` field can be used to identify merge commits and generate a changelog based on those. Another use case +is listing commits that belong to the same pull request. + +When using another template (either provided by a plugin or by yourself), you can also pass extra template variables +by: + +- defining them in your configuration with the `extras` settings +- providing them on the command line with the `--extra/-e` parameter to `bump` and `changelog` commands diff --git a/docs/customization/config_file.md b/docs/customization/config_file.md new file mode 100644 index 0000000000..a5440342bf --- /dev/null +++ b/docs/customization/config_file.md @@ -0,0 +1,187 @@ +# Customize in configuration file + +The basic steps are: + +1. Define your custom committing or bumping rules in the configuration file. +2. Declare `name = "cz_customize"` in your configuration file, or add `-n cz_customize` when running Commitizen. + +Example: + +```toml title="pyproject.toml" +[tool.commitizen] +name = "cz_customize" + +[tool.commitizen.customize] +message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}" +example = "feature: this feature enable customize through config file" +schema = "<type>: <body>" +schema_pattern = "(feature|bug fix):(\\s.*)" +bump_pattern = "^(break|new|fix|hotfix)" +bump_map = {"break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH"} +change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"] +info_path = "cz_customize_info.txt" +info = """ +This is customized info +""" +commit_parser = "^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?" +changelog_pattern = "^(feature|bug fix)?(!)?" +change_type_map = {"feature" = "Feat", "bug fix" = "Fix"} + +[[tool.commitizen.customize.questions]] +type = "list" +name = "change_type" +choices = [{value = "feature", name = "feature: A new feature."}, {value = "bug fix", name = "bug fix: A bug fix."}] +# choices = ["feature", "fix"] # short version +message = "Select the type of change you are committing" + +[[tool.commitizen.customize.questions]] +type = "input" +name = "message" +message = "Body." + +[[tool.commitizen.customize.questions]] +type = "confirm" +name = "show_message" +message = "Do you want to add body message in commit?" +``` + +The equivalent example for a json config file: + +```json title=".cz.json" +{ + "commitizen": { + "name": "cz_customize", + "customize": { + "message_template": "{{change_type}}:{% if show_message %} {{message}}{% endif %}", + "example": "feature: this feature enable customize through config file", + "schema": "<type>: <body>", + "schema_pattern": "(feature|bug fix):(\\s.*)", + "bump_pattern": "^(break|new|fix|hotfix)", + "bump_map": { + "break": "MAJOR", + "new": "MINOR", + "fix": "PATCH", + "hotfix": "PATCH" + }, + "change_type_order": ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"], + "info_path": "cz_customize_info.txt", + "info": "This is customized info", + "commit_parser": "^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?", + "changelog_pattern": "^(feature|bug fix)?(!)?", + "change_type_map": {"feature": "Feat", "bug fix": "Fix"}, + "questions": [ + { + "type": "list", + "name": "change_type", + "choices": [ + { + "value": "feature", + "name": "feature: A new feature." + }, + { + "value": "bug fix", + "name": "bug fix: A bug fix." + } + ], + "message": "Select the type of change you are committing" + }, + { + "type": "input", + "name": "message", + "message": "Body." + }, + { + "type": "confirm", + "name": "show_message", + "message": "Do you want to add body message in commit?" + } + ] + } + } +} +``` + +And the correspondent example for a yaml file: + +```yaml title=".cz.yaml" +commitizen: + name: cz_customize + customize: + message_template: '{{change_type}}:{% if show_message %} {{message}}{% endif %}' + example: 'feature: this feature enable customize through config file' + schema: '<type>: <body>' + schema_pattern: '(feature|bug fix):(\\s.*)' + bump_pattern: '^(break|new|fix|hotfix)' + commit_parser: '^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?' + changelog_pattern: '^(feature|bug fix)?(!)?' + change_type_map: + feature: Feat + bug fix: Fix + bump_map: + break: MAJOR + new: MINOR + fix: PATCH + hotfix: PATCH + change_type_order: ['BREAKING CHANGE', 'feat', 'fix', 'refactor', 'perf'] + info_path: cz_customize_info.txt + info: This is customized info + questions: + - type: list + name: change_type + choices: + - value: feature + name: 'feature: A new feature.' + - value: bug fix + name: 'bug fix: A bug fix.' + message: Select the type of change you are committing + - type: input + name: message + message: 'Body.' + - type: confirm + name: show_message + message: 'Do you want to add body message in commit?' +``` + +## Configuration File Options + +| Parameter | Type | Default | Description | +| ------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `questions` | `Questions` | `None` | Questions regarding the commit message. Detailed below. The type `Questions` is an alias to `Iterable[MutableMapping[str, Any]]` which is defined in `commitizen.defaults`. It expects a list of dictionaries. | +| `message_template` | `str` | `None` | The template for generating message from the given answers. `message_template` should either follow [Jinja2][jinja2] formatting specification, and all the variables in this template should be defined in `name` in `questions` | +| `example` | `str` | `""` | (OPTIONAL) Provide an example to help understand the style. Used by `cz example`. | +| `schema` | `str` | `""` | (OPTIONAL) Show the schema used. Used by `cz schema`. | +| `schema_pattern` | `str` | `""` | (OPTIONAL) The regular expression used to do commit message validation. Used by `cz check`. | +| `info_path` | `str` | `""` | (OPTIONAL) The path to the file that contains explanation of the commit rules. Used by `cz info`. If not provided `cz info`, will load `info` instead. | +| `info` | `str` | `""` | (OPTIONAL) Explanation of the commit rules. Used by `cz info`. | +| `bump_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | +| `bump_pattern` | `str` | `None` | (OPTIONAL) Regex to extract information from commit (subject and body) | +| `change_type_order` | `str` | `None` | (OPTIONAL) List of strings used to order the Changelog. All other types will be sorted alphabetically. Default is `["BREAKING CHANGE", "Feat", "Fix", "Refactor", "Perf"]` | +| `commit_parser` | `str` | `None` | (OPTIONAL) Regex to extract information used in creating changelog. [See more][changelog-spec] | +| `changelog_pattern` | `str` | `None` | (OPTIONAL) Regex to understand which commits to include in the changelog | +| `change_type_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the type of the commit to a changelog entry | + +[jinja2]: https://jinja.palletsprojects.com/en/2.10.x/ +[changelog-spec]: https://commitizen-tools.github.io/commitizen/commands/changelog/ + +### Detailed `questions` content + +| Parameter | Type | Default | Description | +| ----------- | ------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `type` | `str` | `None` | The type of questions. Valid types: `list`, `select`, `input`, etc. The `select` type provides an interactive searchable list interface. [See More][different-question-types] | +| `name` | `str` | `None` | The key for the value answered by user. It's used in `message_template` | +| `message` | `str` | `None` | Detail description for the question. | +| `choices` | `list` | `None` | (OPTIONAL) The choices when `type = list` or `type = select`. Either use a list of values or a list of dictionaries with `name` and `value` keys. Keyboard shortcuts can be defined via `key`. See examples above. | +| `default` | `Any` | `None` | (OPTIONAL) The default value for this question. | +| `filter` | `str` | `None` | (OPTIONAL) Validator for user's answer. **(Work in Progress)** | +| `multiline` | `bool` | `False` | (OPTIONAL) Enable multiline support when `type = input`. | +| `use_search_filter` | `bool` | `False` | (OPTIONAL) Enable search/filter functionality for list/select type questions. This allows users to type and filter through the choices. | +| `use_jk_keys` | `bool` | `True` | (OPTIONAL) Enable/disable j/k keys for navigation in list/select type questions. Set to false if you prefer arrow keys only. | + +[different-question-types]: https://github.com/tmbo/questionary#different-question-types + +### Shortcut keys + +When the `use_shortcuts` config option is enabled, Commitizen can show and use keyboard shortcuts to select items from lists directly. +For example, when using the `cz_conventional_commits` Commitizen template, shortcut keys are shown when selecting the commit type. +Unless otherwise defined, keyboard shortcuts will be numbered automatically. +To specify keyboard shortcuts for your custom choices, provide the shortcut using the `key` parameter in dictionary form for each choice you would like to customize. diff --git a/docs/customization/python_class.md b/docs/customization/python_class.md new file mode 100644 index 0000000000..c698b03dee --- /dev/null +++ b/docs/customization/python_class.md @@ -0,0 +1,310 @@ +# Customizing through a python class + +The basic steps are: + +1. Inheriting from `BaseCommitizen`. +2. Give a name to your rules. +3. Create a Python package using proper [build backend](https://packaging.python.org/en/latest/glossary/#term-Build-Backend) +4. Expose the class as a `commitizen.plugin` entrypoint. + +Check an [example][convcomms] on how to configure `BaseCommitizen`. + +You can also automate the steps above through [cookiecutter](https://cookiecutter.readthedocs.io/en/1.7.0/). + +```sh +cookiecutter gh:commitizen-tools/commitizen_cz_template +``` + +See [commitizen_cz_template](https://github.com/commitizen-tools/commitizen_cz_template) for details. + +See [Third-party plugins](../third-party-plugins/about.md) for more details on how to create a third-party Commitizen plugin. + +## Custom commit rules + +Create a Python module, for example `cz_jira.py`. + +Inherit from `BaseCommitizen`, and you must define `questions` and `message`. The others are optional. + +```python title="cz_jira.py" +from commitizen.cz.base import BaseCommitizen +from commitizen.defaults import Questions + + +class JiraCz(BaseCommitizen): + # Questions = Iterable[MutableMapping[str, Any]] + # It expects a list with dictionaries. + def questions(self) -> Questions: + """Questions regarding the commit message.""" + questions = [ + {"type": "input", "name": "title", "message": "Commit title"}, + {"type": "input", "name": "issue", "message": "Jira Issue number:"}, + ] + return questions + + def message(self, answers: dict) -> str: + """Generate the message with the given answers.""" + return f"answers['title'] (#answers['issue'])" + + def example(self) -> str: + """Provide an example to help understand the style (OPTIONAL) + + Used by `cz example`. + """ + return "Problem with user (#321)" + + def schema(self) -> str: + """Show the schema used (OPTIONAL) + + Used by `cz schema`. + """ + return "<title> (<issue>)" + + def info(self) -> str: + """Explanation of the commit rules. (OPTIONAL) + + Used by `cz info`. + """ + return "We use this because is useful" +``` + +The next file required is `setup.py` modified from flask version. + +```python title="setup.py" +from setuptools import setup + +setup( + name="JiraCommitizen", + version="0.1.0", + py_modules=["cz_jira"], + license="MIT", + long_description="this is a long description", + install_requires=["commitizen"], + entry_points={"commitizen.plugin": ["cz_jira = cz_jira:JiraCz"]}, +) +``` + +So in the end, we would have + + . + ├── cz_jira.py + └── setup.py + +And that's it. You can install it without uploading to PyPI by simply +doing `pip install .` + +## Custom bump rules + +You need to define 2 parameters inside your custom `BaseCommitizen`. + +| Parameter | Type | Default | Description | +| -------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | +| `bump_pattern` | `str` | `None` | Regex to extract information from commit (subject and body) | +| `bump_map` | `dict` | `None` | Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | + +Let's see an example. + +```python title="cz_strange.py" +from commitizen.cz.base import BaseCommitizen + + +class StrangeCommitizen(BaseCommitizen): + bump_pattern = r"^(break|new|fix|hotfix)" + bump_map = {"break": "MAJOR", "new": "MINOR", "fix": "PATCH", "hotfix": "PATCH"} +``` + +That's it, your Commitizen now supports custom rules, and you can run. + +```bash +cz -n cz_strange bump +``` + +[convcomms]: https://github.com/commitizen-tools/commitizen/blob/master/commitizen/cz/conventional_commits/conventional_commits.py + +### Custom commit validation and error message + +The commit message validation can be customized by overriding the `validate_commit_message` and `format_error_message` +methods from `BaseCommitizen`. This allows for a more detailed feedback to the user where the error originates from. + +```python +import re +from commitizen.cz.base import BaseCommitizen, ValidationResult +from commitizen import git + + +class CustomValidationCz(BaseCommitizen): + def validate_commit_message( + self, + *, + commit_msg: str, + pattern: str | None, + allow_abort: bool, + allowed_prefixes: list[str], + max_msg_length: int, + ) -> ValidationResult: + """Validate commit message against the pattern.""" + if not commit_msg: + return allow_abort, [] if allow_abort else [f"commit message is empty"] + if pattern is None: + return True, [] + if any(map(commit_msg.startswith, allowed_prefixes)): + return True, [] + if max_msg_length: + msg_len = len(commit_msg.partition("\n")[0].strip()) + if msg_len > max_msg_length: + return False, [ + f"commit message is too long. Max length is {max_msg_length}" + ] + pattern_match = re.match(pattern, commit_msg) + if pattern_match: + return True, [] + else: + # Perform additional validation of the commit message format + # and add custom error messages as needed + return False, ["commit message does not match the pattern"] + + def format_exception_message( + self, ill_formatted_commits: list[tuple[git.GitCommit, list]] + ) -> str: + """Format commit errors.""" + displayed_msgs_content = "\n".join( + ( + f'commit "{commit.rev}": "{commit.message}"' + f"errors:\n" + "\n".join((f"- {error}" for error in errors)) + ) + for commit, errors in ill_formatted_commits + ) + return ( + "commit validation: failed!\n" + "please enter a commit message in the commitizen format.\n" + f"{displayed_msgs_content}\n" + f"pattern: {self.schema_pattern()}" + ) +``` + +## Custom changelog generator + +The changelog generator should just work in a very basic manner without touching anything. +You can customize it of course, and the following variables are the ones you need to add to your custom `BaseCommitizen`. + +| Parameter | Type | Required | Description | +| -------------------------------- | ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `commit_parser` | `str` | NO | Regex which should provide the variables explained in the [changelog description][changelog-des] | +| `changelog_pattern` | `str` | NO | Regex to validate the commits, this is useful to skip commits that don't meet your ruling standards like a Merge. Usually the same as bump_pattern | +| `change_type_map` | `dict` | NO | Convert the title of the change type that will appear in the changelog, if a value is not found, the original will be provided | +| `changelog_message_builder_hook` | `method: (dict, git.GitCommit) -> dict | list | None` | NO | Customize with extra information your message output, like adding links, this function is executed per parsed commit. Each GitCommit contains the following attrs: `rev`, `title`, `body`, `author`, `author_email`. Returning a falsy value ignore the commit. | +| `changelog_hook` | `method: (full_changelog: str, partial_changelog: Optional[str]) -> str` | NO | Receives the whole and partial (if used incremental) changelog. Useful to send slack messages or notify a compliance department. Must return the full_changelog | +| `changelog_release_hook` | `method: (release: dict, tag: git.GitTag) -> dict` | NO | Receives each generated changelog release and its associated tag. Useful to enrich releases before they are rendered. Must return the update release + +```python title="cz_strange.py" +from commitizen.cz.base import BaseCommitizen +import chat +import compliance + + +class StrangeCommitizen(BaseCommitizen): + changelog_pattern = r"^(break|new|fix|hotfix)" + commit_parser = r"^(?P<change_type>feat|fix|refactor|perf|BREAKING CHANGE)(?:\((?P<scope>[^()\r\n]*)\)|\()?(?P<breaking>!)?:\s(?P<message>.*)?" + change_type_map = { + "feat": "Features", + "fix": "Bug Fixes", + "refactor": "Code Refactor", + "perf": "Performance improvements", + } + + def changelog_message_builder_hook( + self, parsed_message: dict, commit: git.GitCommit + ) -> dict | list | None: + rev = commit.rev + m = parsed_message["message"] + parsed_message[ + "message" + ] = f"{m} {rev} [{commit.author}]({commit.author_email})" + return parsed_message + + def changelog_release_hook(self, release: dict, tag: git.GitTag) -> dict: + release["author"] = tag.author + return release + + def changelog_hook( + self, full_changelog: str, partial_changelog: Optional[str] + ) -> str: + """Executed at the end of the changelog generation + + full_changelog: it's the output about to being written into the file + partial_changelog: it's the new stuff, this is useful to send slack messages or + similar + + Return: + the new updated full_changelog + """ + if partial_changelog: + chat.room("#committers").notify(partial_changelog) + if full_changelog: + compliance.send(full_changelog) + full_changelog.replace(" fix ", " **fix** ") + return full_changelog +``` + +## Raise Customize Exception + +If you want `commitizen` to catch your exception and print the message, you'll have to inherit `CzException`. + +```python +from commitizen.cz.exception import CzException + + +class NoSubjectProvidedException(CzException): + ... +``` + +## Migrating from legacy plugin format + +Commitizen migrated to a new plugin format relying on `importlib.metadata.EntryPoint`. +Migration should be straight-forward for legacy plugins: + +- Remove the `discover_this` line from your plugin module +- Expose the plugin class under as a `commitizen.plugin` entrypoint. + +The name of the plugin is now determined by the name of the entrypoint. + +### Example + +If you were having a `CzPlugin` class in a `cz_plugin.py` module like this: + +```python +from commitizen.cz.base import BaseCommitizen + + +class PluginCz(BaseCommitizen): + ... + + +discover_this = PluginCz +``` + +Then remove the `discover_this` line: + +```python +from commitizen.cz.base import BaseCommitizen + + +class PluginCz(BaseCommitizen): + ... +``` + +and expose the class as entrypoint in your `setuptools`: + +```python +from setuptools import setup + +setup( + name="MyPlugin", + version="0.1.0", + py_modules=["cz_plugin"], + entry_points={"commitizen.plugin": ["plugin = cz_plugin:PluginCz"]}, + ..., +) +``` + +Then your plugin will be available under the name `plugin`. diff --git a/docs/faq.md b/docs/faq.md index 22cd9e8d6c..9de0c43e41 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -10,7 +10,8 @@ name = "spam" version = "2.5.1" ``` -Commitizen provides a `PEP621` [version provider](config.md#version-providers) to get and set version from this field. +Commitizen provides a [`PEP621` version provider](config/version_provider.md) to get and set version from this field. + You just need to set the proper `version_provider` setting: ```toml @@ -24,8 +25,8 @@ version_provider = "pep621" ## Why are `revert` and `chore` valid types in the check pattern of `cz_conventional_commits` but not types we can select? -`revert` and `chore` are added to `pattern` in `cz check` in order to prevent backward errors, but officially they are not part of conventional commits, we are using the latest [types from Angular](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type) (they used to but were removed). -However, you can create a customized `cz` with those extra types. See [Customization](customization.md) for more details. +`revert` and `chore` are added to the `pattern` in `cz check` in order to prevent backward errors, but officially they are not part of conventional commits, we are using the latest [types from Angular](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type) (they used to but were removed). +However, you can create a customized `cz` with those extra types. (See [Customization](customization/config_file.md)). See more discussion in - [issue #142](https://github.com/commitizen-tools/commitizen/issues/142) @@ -128,7 +129,7 @@ If you would like to learn more about both schemes, there are plenty of good res ## How to change the tag format ? -You can use the [`legacy_tag_formats`](config.md#legacy_tag_formats) to list old tag formats. +You can use the [`legacy_tag_formats`](config/bump.md#legacy_tag_formats) to list old tag formats. New bumped tags will be in the new format but old ones will still work for: - changelog generation (full, incremental and version range) - bump new version computation (automatically guessed or increment given) @@ -147,7 +148,7 @@ legacy_tag_formats = [ ## How to avoid warnings for expected non-version tags -You can explicitly ignore them with [`ignored_tag_formats`](config.md#ignored_tag_formats). +You can explicitly ignore them with [`ignored_tag_formats`](config/bump.md#ignored_tag_formats). ```toml tag_format = "v${version}" diff --git a/docs/tutorials/tag_format.md b/docs/tutorials/tag_format.md index 8408b4c801..2d439e38ca 100644 --- a/docs/tutorials/tag_format.md +++ b/docs/tutorials/tag_format.md @@ -42,8 +42,7 @@ As a result, the tag generated on bump will have this format: `v1.0.0` and the v !!! note Both `$version` and `${version}` syntaxes are strictly equivalent. You can use the one you prefer. -See [the `version_scheme` section in `bump` command documentation](../commands/bump.md#version_scheme) for more details on version schemes and how to define your own. -See [`tag_format`](../config.md#tag_format) and [`version_scheme`](../config.md#version_scheme) settings in [Configuration reference](../config.md) for more details on these settings. +See [`tag_format`](../commands/bump.md#-tag-format) and [`version_scheme`](../commands/bump.md#-version-scheme) settings for more details. ## Changing convention @@ -71,7 +70,7 @@ Your new tag will be in the form `component-${version}`. Now let's say you have some known tags you want to ignore, either because they are not versions, or because they are not versions of the component you are dealing with. As a consequence, you don't want them to trigger a warning because Commitizen detected an unknown tag format. -Then you can tell Commitizen about it using the [`ignored_tag_formats`](../config.md#ignored_tag_formats) setting: +Then you can tell Commitizen about it using the [`ignored_tag_formats`](../config/bump.md#ignored_tag_formats) setting: ```yaml [tool.commitizen] diff --git a/docs/tutorials/writing_commits.md b/docs/tutorials/writing_commits.md index a64480874a..a56d6494d4 100644 --- a/docs/tutorials/writing_commits.md +++ b/docs/tutorials/writing_commits.md @@ -44,8 +44,8 @@ Emojis may be added as well (e.g., see [cz-emoji][cz_emoji]), which requires the | `fix(commands): bump error when no user provided` | `fix: stuff` | | `feat: add new commit command` | `feat: commit command introduced` | -[customization]: ../customization.md +[customization]: ../customization/config_file.md [conventional_commits]: https://www.conventionalcommits.org [cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-commitizen/#cz-emoji -[configuration]: ../config.md#encoding -[breaking-change-config]: ../config.md#breaking_change_exclamation_in_title +[configuration]: ../config/commit.md#encoding +[breaking-change-config]: ../config/commit.md#breaking_change_exclamation_in_title diff --git a/mkdocs.yml b/mkdocs.yml index 8a55bb23fa..ac1fbfa097 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -42,8 +42,18 @@ nav: - ls: "commands/ls.md" - schema: "commands/schema.md" - version: "commands/version.md" - - Configuration: "config.md" - - Customization: "customization.md" + - Configuration: + - Configuration File: "config/configuration_file.md" + - Version Provider: "config/version_provider.md" + - bump: "config/bump.md" + - commit: "config/commit.md" + - check: "config/check.md" + - changelog: "config/changelog.md" + - Misc Options: "config/option.md" + - Advanced Customization: + - Configuration File: "customization/config_file.md" + - Customized Python Class: "customization/python_class.md" + - Changelog Template: "customization/changelog_template.md" - Tutorials: - Writing commits: "tutorials/writing_commits.md" - Managing tags formats: "tutorials/tag_format.md" From 3cb9b2ce0abbd4889d5c8a5f6bb958828fbe97f1 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 10 Dec 2025 22:53:22 +0800 Subject: [PATCH 104/221] docs(exit_codes.md): move "ignoring errors" from bump doc to exit_code doc --- docs/commands/bump.md | 65 +--------------- docs/exit_codes.md | 169 +++++++++++++++++++++++++++++++++--------- 2 files changed, 137 insertions(+), 97 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index 78ff9777cf..7bbc9b6c91 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -431,7 +431,7 @@ Useful for determining the next version based on CI for non-production environme !!! warning The `--get-next` flag will raise a `NoneIncrementExit` if the found commits are not eligible for a version bump. - For information on how to suppress this exit, see [avoid raising errors](#avoid-raising-errors). + For information on how to suppress this exit, see [Ignoring Exit Codes](../exit_codes.md#ignoring-exit-codes). ### `--allow-no-commit` @@ -505,69 +505,6 @@ Supported variables: | `$prerelease`, `${prerelease}` | Prerelease (alpha, beta, release candidate) | | `$devrelease`, `${devrelease}` | Development release | -## Avoid raising errors - -Some situations from Commitizen raise an exit code different from 0. -If the error code is different from 0, any CI or script running Commitizen might be interrupted. - -If you have a special use case, where you don't want to raise one of these error codes, you can -tell Commitizen to not raise them. - -### Recommended use case - -At the moment, we've identified that the most common error code to skip is - -| Error name | Exit code | -| ----------------- | --------- | -| NoneIncrementExit | 21 | - -There are some situations where you don't want to get an error code when some -commits do not match your rules, you just want those commits to be skipped. - -```sh -cz -nr 21 bump -``` - -### Easy way - -Check which error code was raised by Commitizen by running in the terminal - -```sh -echo $? -``` - -The output should be an integer like this - -```sh -3 -``` - -And then you can tell Commitizen to ignore it: - -```sh -cz --no-raise 3 -``` - -You can tell Commitizen to skip more than one if needed: - -```sh -cz --no-raise 3,4,5 -``` - -### Longer way - -Check the list of [exit_codes](../exit_codes.md) and understand which one you have -to skip and why. - -Remember to document somewhere this, because you'll forget. - -For example if the system raises a `NoneIncrementExit` error, you look it up -on the list, and then you can use the exit code: - -```sh -cz -nr 21 bump -``` - [pep440]: https://www.python.org/dev/peps/pep-0440/ [semver]: https://semver.org/ [version_files]: ../config/bump.md#version_files diff --git a/docs/exit_codes.md b/docs/exit_codes.md index fd92961d38..1a214e2832 100644 --- a/docs/exit_codes.md +++ b/docs/exit_codes.md @@ -1,39 +1,142 @@ # Exit Codes -Commitizen handles expected exceptions through `CommitizenException` and returns different exit codes for different situations. They could be useful if you want to ignore specific errors in your pipeline. +Commitizen handles expected exceptions through `CommitizenException` and returns different exit codes for different situations. This reference is useful when you need to ignore specific errors in your CI/CD pipeline or automation scripts. -These exit codes can be found in `commitizen/exceptions.py::ExitCode`. +All exit codes are defined in [commitizen/exceptions.py](https://github.com/commitizen-tools/commitizen/blob/master/commitizen/exceptions.py). + +## Exit Code Reference | Exception | Exit Code | Description | | --------------------------- | --------- | ----------------------------------------------------------------------------------------------------------- | -| ExpectedExit | 0 | Expected exit | -| DryRunExit | 0 | Exit due to passing `--dry-run` option | -| NoCommitizenFoundException | 1 | Using a cz (e.g., `cz_jira`) that cannot be found in your system | -| NotAGitProjectError | 2 | Not in a git project | -| NoCommitsFoundError | 3 | No commit found | -| NoVersionSpecifiedError | 4 | Version can not be found in configuration file | -| NoPatternMapError | 5 | bump / changelog pattern or map can not be found in configuration file | -| BumpCommitFailedError | 6 | Commit error when bumping version | -| BumpTagFailedError | 7 | Tag error when bumping version | -| NoAnswersError | 8 | No user response given | -| CommitError | 9 | git commit error | -| NoCommitBackupError | 10 | Commit back up file cannot be found | -| NothingToCommitError | 11 | Nothing in staging to be committed | -| CustomError | 12 | `CzException` raised | -| NoCommandFoundError | 13 | No command found when running Commitizen cli (e.g., `cz --debug`) | -| InvalidCommitMessageError | 14 | The commit message does not pass `cz check` | -| MissingConfigError | 15 | Configuration missed for `cz_customize` | -| NoRevisionError | 16 | No revision found | -| CurrentVersionNotFoundError | 17 | current version cannot be found in _version_files_ | -| InvalidCommandArgumentError | 18 | The argument provide to command is invalid (e.g. `cz check -commit-msg-file filename --rev-range master..`) | -| InvalidConfigurationError | 19 | An error was found in the Commitizen Configuration, such as duplicates in `change_type_order` | -| NotAllowed | 20 | `--incremental` cannot be combined with a `rev_range` | -| NoneIncrementExit | 21 | The commits found are not eligible to be bumped | -| CharacterSetDecodeError | 22 | The character encoding of the command output could not be determined | -| GitCommandError | 23 | Unexpected failure while calling a git command | -| InvalidManualVersion | 24 | Manually provided version is invalid | -| InitFailedError | 25 | Failed to initialize pre-commit | -| RunHookError | 26 | An error occurred during a hook execution | -| VersionProviderUnknown | 27 | `version_provider` setting is set to an unknown version provider identifier | -| VersionSchemeUnknown | 28 | `version_scheme` setting is set to an unknown version scheme identifier | -| ChangelogFormatUnknown | 29 | `changelog_format` setting is set to an unknown version scheme identifier or could not be guessed | +| `ExpectedExit` | 0 | Expected exit | +| `DryRunExit` | 0 | Exit due to passing `--dry-run` option | +| `NoCommitizenFoundException` | 1 | Using a cz (e.g., `cz_jira`) that cannot be found in your system | +| `NotAGitProjectError` | 2 | Not in a git project | +| `NoCommitsFoundError` | 3 | No commits found | +| `NoVersionSpecifiedError` | 4 | Version is not specified in configuration file | +| `NoPatternMapError` | 5 | bump / changelog pattern or map can not be found in configuration file | +| `BumpCommitFailedError` | 6 | Commit failed when bumping version | +| `BumpTagFailedError` | 7 | Tag failed when bumping version | +| `NoAnswersError` | 8 | No user response given | +| `CommitError` | 9 | git commit error | +| `NoCommitBackupError` | 10 | Commit backup file is not found | +| `NothingToCommitError` | 11 | Nothing in staging to be committed | +| `CustomError` | 12 | `CzException` raised | +| `NoCommandFoundError` | 13 | No command found when running Commitizen cli (e.g., `cz --debug`) | +| `InvalidCommitMessageError` | 14 | The commit message does not pass `cz check` | +| `MissingConfigError` | 15 | Configuration is missing for `cz_customize` | +| `NoRevisionError` | 16 | No revision found | +| `CurrentVersionNotFoundError`| 17 | Current version cannot be found in `version_files` | +| `InvalidCommandArgumentError`| 18 | The argument provided to the command is invalid (e.g. `cz check -commit-msg-file filename --rev-range master..`) | +| `InvalidConfigurationError` | 19 | An error was found in the Commitizen Configuration, such as duplicates in `change_type_order` | +| `NotAllowed` | 20 | Invalid combination of command line / configuration file options | +| `NoneIncrementExit` | 21 | The commits found are not eligible to be bumped | +| `CharacterSetDecodeError` | 22 | The character encoding of the command output could not be determined | +| `GitCommandError` | 23 | Unexpected failure while calling a git command | +| `InvalidManualVersion` | 24 | Manually provided version is invalid | +| `InitFailedError` | 25 | Failed to initialize pre-commit | +| `RunHookError` | 26 | An error occurred during a hook execution | +| `VersionProviderUnknown` | 27 | Unknown `version_provider` | +| `VersionSchemeUnknown` | 28 | Unknown `version_scheme` | +| `ChangelogFormatUnknown` | 29 | Unknown `changelog_format` or cannot be determined by the file extension | +| `ConfigFileNotFound` | 30 | The configuration file is not found | +| `ConfigFileIsEmpty` | 31 | The configuration file is empty | +| `CommitMessageLengthLimitExceededError`| 32 | The commit message length exceeds the given limit. | + +## Ignoring Exit Codes + +In some scenarios, you may want Commitizen to continue execution even when certain errors occur. This is particularly useful in CI/CD pipelines where you want to handle specific errors gracefully. + +### Using `--no-raise` Flag + +The `--no-raise` (or `-nr`) flag allows you to specify exit codes that should not cause Commitizen to exit with an error. You can use either: + +- **Exit code numbers**: `21`, `3`, `4` +- **Exit code names**: `NO_INCREMENT`, `NO_COMMITS_FOUND`, `NO_VERSION_SPECIFIED` +- **Mixed format**: `21,NO_COMMITS_FOUND,4` + +Multiple exit codes can be specified as a comma-separated list. + +### Common Use Cases + +#### Ignoring No Increment Errors + +The most common use case is to ignore `NoneIncrementExit` (exit code 21) when running `cz bump`. This allows the command to succeed even when no commits are eligible for a version bump: + +```sh +cz -nr 21 bump +``` + +Or using the exit code name: + +```sh +cz -nr NO_INCREMENT bump +``` + +This is useful in CI pipelines where you want to run `cz bump` regularly, but don't want the pipeline to fail when there are no version-worthy commits. + +#### Ignoring Multiple Exit Codes + +You can ignore multiple exit codes at once: + +```sh +cz --no-raise 21,3,4 bump +``` + +This example ignores: + +- `21` (`NoneIncrementExit`) - No eligible commits for bump +- `3` (`NoCommitsFoundError`) - No commits found +- `4` (`NoVersionSpecifiedError`) - Version not specified + +### Finding the Exit Code + +If you encounter an error and want to ignore it, you can find the exit code in two ways: + +#### Method 1: Check the Exit Code After Running + +After running a Commitizen command that fails, check the exit code: + +```sh +cz bump +echo $? # Prints the exit code (e.g., 21) +``` + +Then use that exit code with `--no-raise`: + +```sh +cz -nr 21 bump +``` + +#### Method 2: Look Up the Exception + +1. Check the error message to identify the exception type +2. Find the corresponding exit code in the table above +3. Use that exit code with `--no-raise` + +For example, if you see `NoneIncrementExit` in the error, look it up in the table to find it's exit code 21, then use: + +```sh +cz -nr 21 bump +``` + +### Best Practices + +- **Document your usage**: If you use `--no-raise` in scripts or CI/CD, document why specific exit codes are ignored +- **Be specific**: Only ignore exit codes you understand and have a reason to ignore +- **Test thoroughly**: Ensure that ignoring certain exit codes doesn't mask real problems in your workflow +- **Use exit code names**: When possible, use exit code names (e.g., `NO_INCREMENT`) instead of numbers for better readability + +### Example: CI/CD Pipeline + +Here's an example of using `--no-raise` in a CI/CD pipeline: + +```yaml +# .github/workflows/release.yml +- name: Bump version + run: | + cz -nr NO_INCREMENT bump || true + # Continue even if no version bump is needed +``` + +This ensures the pipeline continues even when there are no commits eligible for a version bump. From d7cf81cf7e3bb156900a4ac3ecbd2f5dc0da0bd3 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 10 Dec 2025 22:43:19 +0800 Subject: [PATCH 105/221] docs(bump): fix broken documentation format --- docs/commands/bump.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index 7bbc9b6c91..e20a20d5f7 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -437,15 +437,15 @@ Useful for determining the next version based on CI for non-production environme Allow the project version to be bumped even when there's no eligible version. -!!! note "Example usage" - ```sh - # bump a minor version even when there's only bug fixes, documentation changes or even no commits +Example usage: - cz bump --increment MINOR --allow-no-commit +```sh +# Force to bump a minor version +cz bump --increment MINOR --allow-no-commit - # bump version to 2.0.0 even when there's no breaking changes or even no commits - cz bump --allow-no-commit 2.0.0 - ``` +# bump version to 2.0.0 even when there's no breaking changes or even no commits +cz bump --allow-no-commit 2.0.0 +``` !!! note "Default increment" The increment is overridden to `PATCH` if there is no increment detected or specified. @@ -455,7 +455,6 @@ Allow the project version to be bumped even when there's no eligible version. ```sh # will bump to `1.0.1` if the current version is `1.0.0`. cz bump --allow-no-commit - ``` # bump version to 2.0.0 even when there's no breaking changes or even no commits cz bump --allow-no-commit 2.0.0 From 6e8edcd7f4e5ad7f52f32f921227c2f110d6cac1 Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sun, 16 Nov 2025 22:59:40 +0800 Subject: [PATCH 106/221] ci(github-actions): add python 3.14 to github-actions and tox --- .github/workflows/pythonpackage.yml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 2c332391db..4e4738ac90 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -6,7 +6,7 @@ jobs: python-check: strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] platform: [ubuntu-22.04, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/pyproject.toml b/pyproject.toml index 01b16fec3c..9b15e6e13c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -173,7 +173,7 @@ testpaths = ["tests/"] [tool.tox] requires = ["tox>=4.22"] -env_list = ["3.9", "3.10", "3.11", "3.12", "3.13"] +env_list = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] [tool.tox.env_run_base] description = "Run tests suite against Python {base_python}" From 04d530425367c52edd57fd7c9d31c98296524f68 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Mon, 17 Nov 2025 23:35:59 +0800 Subject: [PATCH 107/221] refactor(bump): rename parameter and variables --- commitizen/bump.py | 4 ++-- commitizen/commands/bump.py | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/commitizen/bump.py b/commitizen/bump.py index 6672c5f509..a955c20b6c 100644 --- a/commitizen/bump.py +++ b/commitizen/bump.py @@ -62,7 +62,7 @@ def find_increment( def update_version_in_files( current_version: str, new_version: str, - files: Iterable[str], + version_files: Iterable[str], *, check_consistency: bool, encoding: str, @@ -77,7 +77,7 @@ def update_version_in_files( """ updated_files = [] - for path, pattern in _resolve_files_and_regexes(files, current_version): + for path, pattern in _resolve_files_and_regexes(version_files, current_version): current_version_found = False bumped_lines = [] diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 3dc678920e..5cad643b81 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -302,10 +302,10 @@ def __call__(self) -> None: "[NO_COMMITS_TO_BUMP]\nThe commits found are not eligible to be bumped" ) - files: list[str] = [] + updated_files: list[str] = [] dry_run = self.arguments["dry_run"] if self.changelog_flag: - args = { + changelog_args = { "unreleased_version": new_tag_version, "template": self.template, "extras": self.extras, @@ -313,22 +313,27 @@ def __call__(self) -> None: "dry_run": dry_run, } if self.changelog_to_stdout: - changelog_cmd = Changelog(self.config, {**args, "dry_run": True}) # type: ignore[typeddict-item] + changelog_cmd = Changelog( + self.config, + {**changelog_args, "dry_run": True}, # type: ignore[typeddict-item] + ) try: changelog_cmd() except DryRunExit: pass - args["file_name"] = self.file_name - changelog_cmd = Changelog(self.config, args) # type: ignore[arg-type] + changelog_cmd = Changelog( + self.config, + {**changelog_args, "file_name": self.file_name}, # type: ignore[typeddict-item] + ) changelog_cmd() - files.append(changelog_cmd.file_name) + updated_files.append(changelog_cmd.file_name) # Do not perform operations over files or git. if dry_run: raise DryRunExit() - files.extend( + updated_files.extend( bump.update_version_in_files( str(current_version), str(new_version), @@ -360,13 +365,13 @@ def __call__(self) -> None: raise ExpectedExit() # FIXME: check if any changes have been staged - git.add(*files) + git.add(*updated_files) c = git.commit(message, args=self._get_commit_args()) if self.retry and c.return_code != 0 and self.changelog_flag: # Maybe pre-commit reformatted some files? Retry once logger.debug("1st git.commit error: %s", c.err) logger.info("1st commit attempt failed; retrying once") - git.add(*files) + git.add(*updated_files) c = git.commit(message, args=self._get_commit_args()) if c.return_code != 0: err = c.err.strip() or c.out From b91ceb1f1770dc3ad4d494a023a151623ab0674c Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sat, 8 Nov 2025 19:10:56 +0800 Subject: [PATCH 108/221] build: update dev dependencies --- poetry.lock | 227 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 157 insertions(+), 70 deletions(-) diff --git a/poetry.lock b/poetry.lock index 80051bf4de..e7600db5d3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -440,15 +440,15 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" groups = ["dev", "test"] markers = "python_version < \"3.11\"" files = [ - {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, - {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] [package.dependencies] @@ -675,6 +675,92 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "librt" +version = "0.7.3" +description = "Mypyc runtime library" +optional = false +python-versions = ">=3.9" +groups = ["linters"] +files = [ + {file = "librt-0.7.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2682162855a708e3270eba4b92026b93f8257c3e65278b456c77631faf0f4f7a"}, + {file = "librt-0.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:440c788f707c061d237c1e83edf6164ff19f5c0f823a3bf054e88804ebf971ec"}, + {file = "librt-0.7.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399938edbd3d78339f797d685142dd8a623dfaded023cf451033c85955e4838a"}, + {file = "librt-0.7.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1975eda520957c6e0eb52d12968dd3609ffb7eef05d4223d097893d6daf1d8a7"}, + {file = "librt-0.7.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9da128d0edf990cf0d2ca011b02cd6f639e79286774bd5b0351245cbb5a6e51"}, + {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19acfde38cb532a560b98f473adc741c941b7a9bc90f7294bc273d08becb58b"}, + {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:7b4f57f7a0c65821c5441d98c47ff7c01d359b1e12328219709bdd97fdd37f90"}, + {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:256793988bff98040de23c57cf36e1f4c2f2dc3dcd17537cdac031d3b681db71"}, + {file = "librt-0.7.3-cp310-cp310-win32.whl", hash = "sha256:fcb72249ac4ea81a7baefcbff74df7029c3cb1cf01a711113fa052d563639c9c"}, + {file = "librt-0.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:4887c29cadbdc50640179e3861c276325ff2986791e6044f73136e6e798ff806"}, + {file = "librt-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:687403cced6a29590e6be6964463835315905221d797bc5c934a98750fe1a9af"}, + {file = "librt-0.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24d70810f6e2ea853ff79338001533716b373cc0f63e2a0be5bc96129edb5fb5"}, + {file = "librt-0.7.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf8c7735fbfc0754111f00edda35cf9e98a8d478de6c47b04eaa9cef4300eaa7"}, + {file = "librt-0.7.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32d43610dff472eab939f4d7fbdd240d1667794192690433672ae22d7af8445"}, + {file = "librt-0.7.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:adeaa886d607fb02563c1f625cf2ee58778a2567c0c109378da8f17ec3076ad7"}, + {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:572a24fc5958c61431da456a0ef1eeea6b4989d81eeb18b8e5f1f3077592200b"}, + {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6488e69d408b492e08bfb68f20c4a899a354b4386a446ecd490baff8d0862720"}, + {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed028fc3d41adda916320712838aec289956c89b4f0a361ceadf83a53b4c047a"}, + {file = "librt-0.7.3-cp311-cp311-win32.whl", hash = "sha256:2cf9d73499486ce39eebbff5f42452518cc1f88d8b7ea4a711ab32962b176ee2"}, + {file = "librt-0.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:35f1609e3484a649bb80431310ddbec81114cd86648f1d9482bc72a3b86ded2e"}, + {file = "librt-0.7.3-cp311-cp311-win_arm64.whl", hash = "sha256:550fdbfbf5bba6a2960b27376ca76d6aaa2bd4b1a06c4255edd8520c306fcfc0"}, + {file = "librt-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fa9ac2e49a6bee56e47573a6786cb635e128a7b12a0dc7851090037c0d397a3"}, + {file = "librt-0.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e980cf1ed1a2420a6424e2ed884629cdead291686f1048810a817de07b5eb18"}, + {file = "librt-0.7.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e094e445c37c57e9ec612847812c301840239d34ccc5d153a982fa9814478c60"}, + {file = "librt-0.7.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aca73d70c3f553552ba9133d4a09e767dcfeee352d8d8d3eb3f77e38a3beb3ed"}, + {file = "librt-0.7.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c634a0a6db395fdaba0361aa78395597ee72c3aad651b9a307a3a7eaf5efd67e"}, + {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a59a69deeb458c858b8fea6acf9e2acd5d755d76cd81a655256bc65c20dfff5b"}, + {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d91e60ac44bbe3a77a67af4a4c13114cbe9f6d540337ce22f2c9eaf7454ca71f"}, + {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:703456146dc2bf430f7832fd1341adac5c893ec3c1430194fdcefba00012555c"}, + {file = "librt-0.7.3-cp312-cp312-win32.whl", hash = "sha256:b7c1239b64b70be7759554ad1a86288220bbb04d68518b527783c4ad3fb4f80b"}, + {file = "librt-0.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef59c938f72bdbc6ab52dc50f81d0637fde0f194b02d636987cea2ab30f8f55a"}, + {file = "librt-0.7.3-cp312-cp312-win_arm64.whl", hash = "sha256:ff21c554304e8226bf80c3a7754be27c6c3549a9fec563a03c06ee8f494da8fc"}, + {file = "librt-0.7.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56f2a47beda8409061bc1c865bef2d4bd9ff9255219402c0817e68ab5ad89aed"}, + {file = "librt-0.7.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14569ac5dd38cfccf0a14597a88038fb16811a6fede25c67b79c6d50fc2c8fdc"}, + {file = "librt-0.7.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6038ccbd5968325a5d6fd393cf6e00b622a8de545f0994b89dd0f748dcf3e19e"}, + {file = "librt-0.7.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d39079379a9a28e74f4d57dc6357fa310a1977b51ff12239d7271ec7e71d67f5"}, + {file = "librt-0.7.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8837d5a52a2d7aa9f4c3220a8484013aed1d8ad75240d9a75ede63709ef89055"}, + {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:399bbd7bcc1633c3e356ae274a1deb8781c7bf84d9c7962cc1ae0c6e87837292"}, + {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8d8cf653e798ee4c4e654062b633db36984a1572f68c3aa25e364a0ddfbbb910"}, + {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2f03484b54bf4ae80ab2e504a8d99d20d551bfe64a7ec91e218010b467d77093"}, + {file = "librt-0.7.3-cp313-cp313-win32.whl", hash = "sha256:44b3689b040df57f492e02cd4f0bacd1b42c5400e4b8048160c9d5e866de8abe"}, + {file = "librt-0.7.3-cp313-cp313-win_amd64.whl", hash = "sha256:6b407c23f16ccc36614c136251d6b32bf30de7a57f8e782378f1107be008ddb0"}, + {file = "librt-0.7.3-cp313-cp313-win_arm64.whl", hash = "sha256:abfc57cab3c53c4546aee31859ef06753bfc136c9d208129bad23e2eca39155a"}, + {file = "librt-0.7.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:120dd21d46ff875e849f1aae19346223cf15656be489242fe884036b23d39e93"}, + {file = "librt-0.7.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1617bea5ab31266e152871208502ee943cb349c224846928a1173c864261375e"}, + {file = "librt-0.7.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93b2a1f325fefa1482516ced160c8c7b4b8d53226763fa6c93d151fa25164207"}, + {file = "librt-0.7.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d4801db8354436fd3936531e7f0e4feb411f62433a6b6cb32bb416e20b529f"}, + {file = "librt-0.7.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11ad45122bbed42cfc8b0597450660126ef28fd2d9ae1a219bc5af8406f95678"}, + {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6b4e7bff1d76dd2b46443078519dc75df1b5e01562345f0bb740cea5266d8218"}, + {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:d86f94743a11873317094326456b23f8a5788bad9161fd2f0e52088c33564620"}, + {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:754a0d09997095ad764ccef050dd5bf26cbf457aab9effcba5890dad081d879e"}, + {file = "librt-0.7.3-cp314-cp314-win32.whl", hash = "sha256:fbd7351d43b80d9c64c3cfcb50008f786cc82cba0450e8599fdd64f264320bd3"}, + {file = "librt-0.7.3-cp314-cp314-win_amd64.whl", hash = "sha256:d376a35c6561e81d2590506804b428fc1075fcc6298fc5bb49b771534c0ba010"}, + {file = "librt-0.7.3-cp314-cp314-win_arm64.whl", hash = "sha256:cbdb3f337c88b43c3b49ca377731912c101178be91cb5071aac48faa898e6f8e"}, + {file = "librt-0.7.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9f0e0927efe87cd42ad600628e595a1a0aa1c64f6d0b55f7e6059079a428641a"}, + {file = "librt-0.7.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:020c6db391268bcc8ce75105cb572df8cb659a43fd347366aaa407c366e5117a"}, + {file = "librt-0.7.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7af7785f5edd1f418da09a8cdb9ec84b0213e23d597413e06525340bcce1ea4f"}, + {file = "librt-0.7.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ccadf260bb46a61b9c7e89e2218f6efea9f3eeaaab4e3d1f58571890e54858e"}, + {file = "librt-0.7.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9883b2d819ce83f87ba82a746c81d14ada78784db431e57cc9719179847376e"}, + {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:59cb0470612d21fa1efddfa0dd710756b50d9c7fb6c1236bbf8ef8529331dc70"}, + {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1fe603877e1865b5fd047a5e40379509a4a60204aa7aa0f72b16f7a41c3f0712"}, + {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5460d99ed30f043595bbdc888f542bad2caeb6226b01c33cda3ae444e8f82d42"}, + {file = "librt-0.7.3-cp314-cp314t-win32.whl", hash = "sha256:d09f677693328503c9e492e33e9601464297c01f9ebd966ea8fc5308f3069bfd"}, + {file = "librt-0.7.3-cp314-cp314t-win_amd64.whl", hash = "sha256:25711f364c64cab2c910a0247e90b51421e45dbc8910ceeb4eac97a9e132fc6f"}, + {file = "librt-0.7.3-cp314-cp314t-win_arm64.whl", hash = "sha256:a9f9b661f82693eb56beb0605156c7fca57f535704ab91837405913417d6990b"}, + {file = "librt-0.7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd8551aa21df6c60baa2624fd086ae7486bdde00c44097b32e1d1b1966e365e0"}, + {file = "librt-0.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6eb9295c730e26b849ed1f4022735f36863eb46b14b6e10604c1c39b8b5efaea"}, + {file = "librt-0.7.3-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3edbf257c40d21a42615e9e332a6b10a8bacaaf58250aed8552a14a70efd0d65"}, + {file = "librt-0.7.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b29e97273bd6999e2bfe9fe3531b1f4f64effd28327bced048a33e49b99674a"}, + {file = "librt-0.7.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e40520c37926166c24d0c2e0f3bc3a5f46646c34bdf7b4ea9747c297d6ee809"}, + {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6bdd9adfca615903578d2060ee8a6eb1c24eaf54919ff0ddc820118e5718931b"}, + {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f57aca20e637750a2c18d979f7096e2c2033cc40cf7ed201494318de1182f135"}, + {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cad9971881e4fec00d96af7eaf4b63aa7a595696fc221808b0d3ce7ca9743258"}, + {file = "librt-0.7.3-cp39-cp39-win32.whl", hash = "sha256:170cdb8436188347af17bf9cccf3249ba581c933ed56d926497119d4cf730cec"}, + {file = "librt-0.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:b278a9248a4e3260fee3db7613772ca9ab6763a129d6d6f29555e2f9b168216d"}, + {file = "librt-0.7.3.tar.gz", hash = "sha256:3ec50cf65235ff5c02c5b747748d9222e564ad48597122a361269dd3aa808798"}, +] + [[package]] name = "markdown" version = "3.9" @@ -954,53 +1040,54 @@ files = [ [[package]] name = "mypy" -version = "1.18.2" +version = "1.19.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" groups = ["linters"] files = [ - {file = "mypy-1.18.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eab0cf6294dafe397c261a75f96dc2c31bffe3b944faa24db5def4e2b0f77c"}, - {file = "mypy-1.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a780ca61fc239e4865968ebc5240bb3bf610ef59ac398de9a7421b54e4a207e"}, - {file = "mypy-1.18.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448acd386266989ef11662ce3c8011fd2a7b632e0ec7d61a98edd8e27472225b"}, - {file = "mypy-1.18.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9e171c465ad3901dc652643ee4bffa8e9fef4d7d0eece23b428908c77a76a66"}, - {file = "mypy-1.18.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:592ec214750bc00741af1f80cbf96b5013d81486b7bb24cb052382c19e40b428"}, - {file = "mypy-1.18.2-cp310-cp310-win_amd64.whl", hash = "sha256:7fb95f97199ea11769ebe3638c29b550b5221e997c63b14ef93d2e971606ebed"}, - {file = "mypy-1.18.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:807d9315ab9d464125aa9fcf6d84fde6e1dc67da0b6f80e7405506b8ac72bc7f"}, - {file = "mypy-1.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:776bb00de1778caf4db739c6e83919c1d85a448f71979b6a0edd774ea8399341"}, - {file = "mypy-1.18.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1379451880512ffce14505493bd9fe469e0697543717298242574882cf8cdb8d"}, - {file = "mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1331eb7fd110d60c24999893320967594ff84c38ac6d19e0a76c5fd809a84c86"}, - {file = "mypy-1.18.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ca30b50a51e7ba93b00422e486cbb124f1c56a535e20eff7b2d6ab72b3b2e37"}, - {file = "mypy-1.18.2-cp311-cp311-win_amd64.whl", hash = "sha256:664dc726e67fa54e14536f6e1224bcfce1d9e5ac02426d2326e2bb4e081d1ce8"}, - {file = "mypy-1.18.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:33eca32dd124b29400c31d7cf784e795b050ace0e1f91b8dc035672725617e34"}, - {file = "mypy-1.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3c47adf30d65e89b2dcd2fa32f3aeb5e94ca970d2c15fcb25e297871c8e4764"}, - {file = "mypy-1.18.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d6c838e831a062f5f29d11c9057c6009f60cb294fea33a98422688181fe2893"}, - {file = "mypy-1.18.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01199871b6110a2ce984bde85acd481232d17413868c9807e95c1b0739a58914"}, - {file = "mypy-1.18.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a2afc0fa0b0e91b4599ddfe0f91e2c26c2b5a5ab263737e998d6817874c5f7c8"}, - {file = "mypy-1.18.2-cp312-cp312-win_amd64.whl", hash = "sha256:d8068d0afe682c7c4897c0f7ce84ea77f6de953262b12d07038f4d296d547074"}, - {file = "mypy-1.18.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:07b8b0f580ca6d289e69209ec9d3911b4a26e5abfde32228a288eb79df129fcc"}, - {file = "mypy-1.18.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ed4482847168439651d3feee5833ccedbf6657e964572706a2adb1f7fa4dfe2e"}, - {file = "mypy-1.18.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3ad2afadd1e9fea5cf99a45a822346971ede8685cc581ed9cd4d42eaf940986"}, - {file = "mypy-1.18.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a431a6f1ef14cf8c144c6b14793a23ec4eae3db28277c358136e79d7d062f62d"}, - {file = "mypy-1.18.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7ab28cc197f1dd77a67e1c6f35cd1f8e8b73ed2217e4fc005f9e6a504e46e7ba"}, - {file = "mypy-1.18.2-cp313-cp313-win_amd64.whl", hash = "sha256:0e2785a84b34a72ba55fb5daf079a1003a34c05b22238da94fcae2bbe46f3544"}, - {file = "mypy-1.18.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:62f0e1e988ad41c2a110edde6c398383a889d95b36b3e60bcf155f5164c4fdce"}, - {file = "mypy-1.18.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8795a039bab805ff0c1dfdb8cd3344642c2b99b8e439d057aba30850b8d3423d"}, - {file = "mypy-1.18.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ca1e64b24a700ab5ce10133f7ccd956a04715463d30498e64ea8715236f9c9c"}, - {file = "mypy-1.18.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d924eef3795cc89fecf6bedc6ed32b33ac13e8321344f6ddbf8ee89f706c05cb"}, - {file = "mypy-1.18.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20c02215a080e3a2be3aa50506c67242df1c151eaba0dcbc1e4e557922a26075"}, - {file = "mypy-1.18.2-cp314-cp314-win_amd64.whl", hash = "sha256:749b5f83198f1ca64345603118a6f01a4e99ad4bf9d103ddc5a3200cc4614adf"}, - {file = "mypy-1.18.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25a9c8fb67b00599f839cf472713f54249a62efd53a54b565eb61956a7e3296b"}, - {file = "mypy-1.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2b9c7e284ee20e7598d6f42e13ca40b4928e6957ed6813d1ab6348aa3f47133"}, - {file = "mypy-1.18.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6985ed057513e344e43a26cc1cd815c7a94602fb6a3130a34798625bc2f07b6"}, - {file = "mypy-1.18.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f27105f1525ec024b5c630c0b9f36d5c1cc4d447d61fe51ff4bd60633f47ac"}, - {file = "mypy-1.18.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:030c52d0ea8144e721e49b1f68391e39553d7451f0c3f8a7565b59e19fcb608b"}, - {file = "mypy-1.18.2-cp39-cp39-win_amd64.whl", hash = "sha256:aa5e07ac1a60a253445797e42b8b2963c9675563a94f11291ab40718b016a7a0"}, - {file = "mypy-1.18.2-py3-none-any.whl", hash = "sha256:22a1748707dd62b58d2ae53562ffc4d7f8bcc727e8ac7cbc69c053ddc874d47e"}, - {file = "mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b"}, + {file = "mypy-1.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6148ede033982a8c5ca1143de34c71836a09f105068aaa8b7d5edab2b053e6c8"}, + {file = "mypy-1.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a9ac09e52bb0f7fb912f5d2a783345c72441a08ef56ce3e17c1752af36340a39"}, + {file = "mypy-1.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f7254c15ab3f8ed68f8e8f5cbe88757848df793e31c36aaa4d4f9783fd08ab"}, + {file = "mypy-1.19.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318ba74f75899b0e78b847d8c50821e4c9637c79d9a59680fc1259f29338cb3e"}, + {file = "mypy-1.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf7d84f497f78b682edd407f14a7b6e1a2212b433eedb054e2081380b7395aa3"}, + {file = "mypy-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:c3385246593ac2b97f155a0e9639be906e73534630f663747c71908dfbf26134"}, + {file = "mypy-1.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a31e4c28e8ddb042c84c5e977e28a21195d086aaffaf08b016b78e19c9ef8106"}, + {file = "mypy-1.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34ec1ac66d31644f194b7c163d7f8b8434f1b49719d403a5d26c87fff7e913f7"}, + {file = "mypy-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb64b0ba5980466a0f3f9990d1c582bcab8db12e29815ecb57f1408d99b4bff7"}, + {file = "mypy-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:120cffe120cca5c23c03c77f84abc0c14c5d2e03736f6c312480020082f1994b"}, + {file = "mypy-1.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a500ab5c444268a70565e374fc803972bfd1f09545b13418a5174e29883dab7"}, + {file = "mypy-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:c14a98bc63fd867530e8ec82f217dae29d0550c86e70debc9667fff1ec83284e"}, + {file = "mypy-1.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fb3115cb8fa7c5f887c8a8d81ccdcb94cff334684980d847e5a62e926910e1d"}, + {file = "mypy-1.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3e19e3b897562276bb331074d64c076dbdd3e79213f36eed4e592272dabd760"}, + {file = "mypy-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9d491295825182fba01b6ffe2c6fe4e5a49dbf4e2bb4d1217b6ced3b4797bc6"}, + {file = "mypy-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6016c52ab209919b46169651b362068f632efcd5eb8ef9d1735f6f86da7853b2"}, + {file = "mypy-1.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f188dcf16483b3e59f9278c4ed939ec0254aa8a60e8fc100648d9ab5ee95a431"}, + {file = "mypy-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:0e3c3d1e1d62e678c339e7ade72746a9e0325de42cd2cccc51616c7b2ed1a018"}, + {file = "mypy-1.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7686ed65dbabd24d20066f3115018d2dce030d8fa9db01aa9f0a59b6813e9f9e"}, + {file = "mypy-1.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fd4a985b2e32f23bead72e2fb4bbe5d6aceee176be471243bd831d5b2644672d"}, + {file = "mypy-1.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc51a5b864f73a3a182584b1ac75c404396a17eced54341629d8bdcb644a5bba"}, + {file = "mypy-1.19.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37af5166f9475872034b56c5efdcf65ee25394e9e1d172907b84577120714364"}, + {file = "mypy-1.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:510c014b722308c9bd377993bcbf9a07d7e0692e5fa8fc70e639c1eb19fc6bee"}, + {file = "mypy-1.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:cabbee74f29aa9cd3b444ec2f1e4fa5a9d0d746ce7567a6a609e224429781f53"}, + {file = "mypy-1.19.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f2e36bed3c6d9b5f35d28b63ca4b727cb0228e480826ffc8953d1892ddc8999d"}, + {file = "mypy-1.19.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a18d8abdda14035c5718acb748faec09571432811af129bf0d9e7b2d6699bf18"}, + {file = "mypy-1.19.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75e60aca3723a23511948539b0d7ed514dda194bc3755eae0bfc7a6b4887aa7"}, + {file = "mypy-1.19.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f44f2ae3c58421ee05fe609160343c25f70e3967f6e32792b5a78006a9d850f"}, + {file = "mypy-1.19.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63ea6a00e4bd6822adbfc75b02ab3653a17c02c4347f5bb0cf1d5b9df3a05835"}, + {file = "mypy-1.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ad925b14a0bb99821ff6f734553294aa6a3440a8cb082fe1f5b84dfb662afb1"}, + {file = "mypy-1.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0dde5cb375cb94deff0d4b548b993bec52859d1651e073d63a1386d392a95495"}, + {file = "mypy-1.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1cf9c59398db1c68a134b0b5354a09a1e124523f00bacd68e553b8bd16ff3299"}, + {file = "mypy-1.19.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3210d87b30e6af9c8faed61be2642fcbe60ef77cec64fa1ef810a630a4cf671c"}, + {file = "mypy-1.19.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2c1101ab41d01303103ab6ef82cbbfedb81c1a060c868fa7cc013d573d37ab5"}, + {file = "mypy-1.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ea4fd21bb48f0da49e6d3b37ef6bd7e8228b9fe41bbf4d80d9364d11adbd43c"}, + {file = "mypy-1.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:16f76ff3f3fd8137aadf593cb4607d82634fca675e8211ad75c43d86033ee6c6"}, + {file = "mypy-1.19.0-py3-none-any.whl", hash = "sha256:0c01c99d626380752e527d5ce8e69ffbba2046eb8a060db0329690849cf9b6f9"}, + {file = "mypy-1.19.0.tar.gz", hash = "sha256:f6b874ca77f733222641e5c46e4711648c4037ea13646fd0cdc814c2eaec2528"}, ] [package.dependencies] +librt = ">=0.6.2" mypy_extensions = ">=1.0.0" pathspec = ">=0.9.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} @@ -1253,14 +1340,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.17.1" +version = "10.18" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "pymdown_extensions-10.17.1-py3-none-any.whl", hash = "sha256:1f160209c82eecbb5d8a0d8f89a4d9bd6bdcbde9a8537761844cfc57ad5cd8a6"}, - {file = "pymdown_extensions-10.17.1.tar.gz", hash = "sha256:60d05fe55e7fb5a1e4740fc575facad20dc6ee3a748e8d3d36ba44142e75ce03"}, + {file = "pymdown_extensions-10.18-py3-none-any.whl", hash = "sha256:090bca72be43f7d3186374e23c782899dbef9dc153ef24c59dcd3c346f9ffcae"}, + {file = "pymdown_extensions-10.18.tar.gz", hash = "sha256:20252abe6367354b24191431617a072ee6be9f68c5afcc74ea5573508a61f9e5"}, ] [package.dependencies] @@ -1602,31 +1689,31 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.14.5" +version = "0.14.8" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["linters"] files = [ - {file = "ruff-0.14.5-py3-none-linux_armv6l.whl", hash = "sha256:f3b8248123b586de44a8018bcc9fefe31d23dda57a34e6f0e1e53bd51fd63594"}, - {file = "ruff-0.14.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f7a75236570318c7a30edd7f5491945f0169de738d945ca8784500b517163a72"}, - {file = "ruff-0.14.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6d146132d1ee115f8802356a2dc9a634dbf58184c51bff21f313e8cd1c74899a"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2380596653dcd20b057794d55681571a257a42327da8894b93bbd6111aa801f"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d1fa985a42b1f075a098fa1ab9d472b712bdb17ad87a8ec86e45e7fa6273e68"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88f0770d42b7fa02bbefddde15d235ca3aa24e2f0137388cc15b2dcbb1f7c7a7"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3676cb02b9061fee7294661071c4709fa21419ea9176087cb77e64410926eb78"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b595bedf6bc9cab647c4a173a61acf4f1ac5f2b545203ba82f30fcb10b0318fb"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f55382725ad0bdb2e8ee2babcbbfb16f124f5a59496a2f6a46f1d9d99d93e6e2"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7497d19dce23976bdaca24345ae131a1d38dcfe1b0850ad8e9e6e4fa321a6e19"}, - {file = "ruff-0.14.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:410e781f1122d6be4f446981dd479470af86537fb0b8857f27a6e872f65a38e4"}, - {file = "ruff-0.14.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c01be527ef4c91a6d55e53b337bfe2c0f82af024cc1a33c44792d6844e2331e1"}, - {file = "ruff-0.14.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f66e9bb762e68d66e48550b59c74314168ebb46199886c5c5aa0b0fbcc81b151"}, - {file = "ruff-0.14.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d93be8f1fa01022337f1f8f3bcaa7ffee2d0b03f00922c45c2207954f351f465"}, - {file = "ruff-0.14.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:c135d4b681f7401fe0e7312017e41aba9b3160861105726b76cfa14bc25aa367"}, - {file = "ruff-0.14.5-py3-none-win32.whl", hash = "sha256:c83642e6fccfb6dea8b785eb9f456800dcd6a63f362238af5fc0c83d027dd08b"}, - {file = "ruff-0.14.5-py3-none-win_amd64.whl", hash = "sha256:9d55d7af7166f143c94eae1db3312f9ea8f95a4defef1979ed516dbb38c27621"}, - {file = "ruff-0.14.5-py3-none-win_arm64.whl", hash = "sha256:4b700459d4649e2594b31f20a9de33bc7c19976d4746d8d0798ad959621d64a4"}, - {file = "ruff-0.14.5.tar.gz", hash = "sha256:8d3b48d7d8aad423d3137af7ab6c8b1e38e4de104800f0d596990f6ada1a9fc1"}, + {file = "ruff-0.14.8-py3-none-linux_armv6l.whl", hash = "sha256:ec071e9c82eca417f6111fd39f7043acb53cd3fde9b1f95bbed745962e345afb"}, + {file = "ruff-0.14.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8cdb162a7159f4ca36ce980a18c43d8f036966e7f73f866ac8f493b75e0c27e9"}, + {file = "ruff-0.14.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e2fcbefe91f9fad0916850edf0854530c15bd1926b6b779de47e9ab619ea38f"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d70721066a296f45786ec31916dc287b44040f553da21564de0ab4d45a869b"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c87e09b3cd9d126fc67a9ecd3b5b1d3ded2b9c7fce3f16e315346b9d05cfb52"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d62cb310c4fbcb9ee4ac023fe17f984ae1e12b8a4a02e3d21489f9a2a5f730c"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1af35c2d62633d4da0521178e8a2641c636d2a7153da0bac1b30cfd4ccd91344"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25add4575ffecc53d60eed3f24b1e934493631b48ebbc6ebaf9d8517924aca4b"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c943d847b7f02f7db4201a0600ea7d244d8a404fbb639b439e987edcf2baf9a"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb6e8bf7b4f627548daa1b69283dac5a296bfe9ce856703b03130732e20ddfe2"}, + {file = "ruff-0.14.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7aaf2974f378e6b01d1e257c6948207aec6a9b5ba53fab23d0182efb887a0e4a"}, + {file = "ruff-0.14.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e5758ca513c43ad8a4ef13f0f081f80f08008f410790f3611a21a92421ab045b"}, + {file = "ruff-0.14.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f74f7ba163b6e85a8d81a590363bf71618847e5078d90827749bfda1d88c9cdf"}, + {file = "ruff-0.14.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:eed28f6fafcc9591994c42254f5a5c5ca40e69a30721d2ab18bb0bb3baac3ab6"}, + {file = "ruff-0.14.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:21d48fa744c9d1cb8d71eb0a740c4dd02751a5de9db9a730a8ef75ca34cf138e"}, + {file = "ruff-0.14.8-py3-none-win32.whl", hash = "sha256:15f04cb45c051159baebb0f0037f404f1dc2f15a927418f29730f411a79bc4e7"}, + {file = "ruff-0.14.8-py3-none-win_amd64.whl", hash = "sha256:9eeb0b24242b5bbff3011409a739929f497f3fb5fe3b5698aba5e77e8c833097"}, + {file = "ruff-0.14.8-py3-none-win_arm64.whl", hash = "sha256:965a582c93c63fe715fd3e3f8aa37c4b776777203d8e1d8aa3cc0c14424a4b99"}, + {file = "ruff-0.14.8.tar.gz", hash = "sha256:774ed0dd87d6ce925e3b8496feb3a00ac564bea52b9feb551ecd17e0a23d1eed"}, ] [[package]] @@ -1857,21 +1944,21 @@ markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"" [[package]] name = "urllib3" -version = "2.5.0" +version = "2.6.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, - {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, + {file = "urllib3-2.6.1-py3-none-any.whl", hash = "sha256:e67d06fe947c36a7ca39f4994b08d73922d40e6cca949907be05efa6fd75110b"}, + {file = "urllib3-2.6.1.tar.gz", hash = "sha256:5379eb6e1aba4088bae84f8242960017ec8d8e3decf30480b3a1abdaa9671a3f"}, ] [package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "virtualenv" From 82caf4b54c8cc45da79b3b05e5c32df09c5c3390 Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sat, 8 Nov 2025 19:17:07 +0800 Subject: [PATCH 109/221] refactor(changelog): raise NotAllow when file_name not passed instead of using assert --- commitizen/commands/changelog.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index 27b8ccb258..805d7472da 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -199,7 +199,8 @@ def __call__(self) -> None: raise NotAllowed("--incremental cannot be combined with a rev_range") # Don't continue if no `file_name` specified. - assert self.file_name + if not self.file_name: + raise NotAllowed("filename is required.") tags = self.tag_rules.get_version_tags(git.get_tags(), warn=True) changelog_meta = changelog.Metadata() From 1960970e6b63938f1a7794c85a8439f8b2204fc6 Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sat, 8 Nov 2025 19:13:51 +0800 Subject: [PATCH 110/221] style(ruff): enable S101 check to avoid assert usage in production code --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9b15e6e13c..097aed9c1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -206,11 +206,13 @@ select = [ "RUF022", # unused-noqa "RUF100", + # Checks for uses of the assert keyword. + "S101", ] ignore = ["E501", "D1", "D415"] [tool.ruff.lint.per-file-ignores] -"tests/*" = ["ANN"] +"tests/*" = ["ANN", "S101"] [tool.ruff.lint.isort] known-first-party = ["commitizen", "tests"] From 7d6ae2d849d3fa21f0509f46311a7b43eefb102a Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Mon, 10 Nov 2025 21:11:35 +0800 Subject: [PATCH 111/221] fix(bump): remove NotAllowed related to --get-next option, other related refactoring --- commitizen/commands/bump.py | 44 +++++++++++++---------------- commitizen/exceptions.py | 4 --- tests/commands/test_bump_command.py | 38 ++----------------------- 3 files changed, 22 insertions(+), 64 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 5cad643b81..7d9241587f 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -16,7 +16,6 @@ BumpTagFailedError, DryRunExit, ExpectedExit, - GetNextExit, InvalidManualVersion, NoCommitsFoundError, NoneIncrementExit, @@ -47,7 +46,7 @@ class BumpArgs(Settings, total=False): dry_run: bool file_name: str files_only: bool | None - get_next: bool + get_next: bool # TODO: maybe rename to `next_version_to_stdout` git_output_to_stderr: bool increment_mode: str increment: Increment | None @@ -94,7 +93,6 @@ def __init__(self, config: BaseConfig, arguments: BumpArgs) -> None: ) self.cz = factory.committer_factory(self.config) self.changelog_flag = arguments["changelog"] - self.changelog_config = self.config.settings.get("update_changelog_on_bump") self.changelog_to_stdout = arguments["changelog_to_stdout"] self.git_output_to_stderr = arguments["git_output_to_stderr"] self.no_verify = arguments["no_verify"] @@ -169,7 +167,9 @@ def __call__(self) -> None: is_local_version = self.arguments["local_version"] manual_version = self.arguments["manual_version"] build_metadata = self.arguments["build_metadata"] - get_next = self.arguments["get_next"] + next_version_to_stdout = self.arguments[ + "get_next" + ] # TODO: maybe rename to `next_version_to_stdout` allow_no_commit = self.arguments["allow_no_commit"] major_version_zero = self.arguments["major_version_zero"] @@ -181,7 +181,6 @@ def __call__(self) -> None: (is_local_version, "--local-version"), (build_metadata, "--build-metadata"), (major_version_zero, "--major-version-zero"), - (get_next, "--get-next"), ): if val: raise NotAllowed(f"{option} cannot be combined with MANUAL_VERSION") @@ -194,24 +193,23 @@ def __call__(self) -> None: if build_metadata and is_local_version: raise NotAllowed("--local-version cannot be combined with --build-metadata") - if get_next: + if next_version_to_stdout: for value, option in ( (self.changelog_flag, "--changelog"), (self.changelog_to_stdout, "--changelog-to-stdout"), ): if value: - raise NotAllowed(f"{option} cannot be combined with --get-next") - - # --get-next is a special case, taking precedence over config for 'update_changelog_on_bump' - self.changelog_config = False - # Setting dry_run to prevent any unwanted changes to the repo or files - self.dry_run = True - else: - # If user specified changelog_to_stdout, they probably want the - # changelog to be generated as well, this is the most intuitive solution - self.changelog_flag = any( - (self.changelog_flag, self.changelog_to_stdout, self.changelog_config) + warnings.warn(f"{option} has no effect when used with --get-next") + + # If user specified changelog_to_stdout, they probably want the + # changelog to be generated as well, this is the most intuitive solution + self.changelog_flag = any( + ( + self.changelog_flag, + self.changelog_to_stdout, + self.config.settings.get("update_changelog_on_bump"), ) + ) rules = TagRules.from_settings(cast(Settings, self.bump_settings)) current_tag = rules.find_tag_for(git.get_tags(), current_version) @@ -270,20 +268,18 @@ def __call__(self) -> None: ) new_tag_version = rules.normalize_tag(new_version) - message = bump.create_commit_message( - current_version, new_version, self.bump_settings["bump_message"] - ) - - if get_next: + if next_version_to_stdout: if increment is None and new_tag_version == current_tag_version: raise NoneIncrementExit( "[NO_COMMITS_TO_BUMP]\n" "The commits found are not eligible to be bumped" ) - out.write(str(new_version)) - raise GetNextExit() + raise DryRunExit() + message = bump.create_commit_message( + current_version, new_version, self.bump_settings["bump_message"] + ) # Report found information information = f"{message}\ntag to create: {new_tag_version}\n" if increment: diff --git a/commitizen/exceptions.py b/commitizen/exceptions.py index 75b0ab2fb7..49cd1832b0 100644 --- a/commitizen/exceptions.py +++ b/commitizen/exceptions.py @@ -75,10 +75,6 @@ class DryRunExit(ExpectedExit): pass -class GetNextExit(ExpectedExit): - pass - - class NoneIncrementExit(CommitizenException): exit_code = ExitCode.NO_INCREMENT diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index 59297b1726..7b9edee82f 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -23,7 +23,6 @@ DryRunExit, ExitCode, ExpectedExit, - GetNextExit, InvalidManualVersion, NoCommitsFoundError, NoneIncrementExit, @@ -1456,7 +1455,7 @@ def test_bump_get_next(mocker: MockFixture, capsys): testargs = ["cz", "bump", "--yes", "--get-next"] mocker.patch.object(sys, "argv", testargs) - with pytest.raises(GetNextExit): + with pytest.raises(DryRunExit): cli.main() out, _ = capsys.readouterr() @@ -1476,7 +1475,7 @@ def test_bump_get_next_update_changelog_on_bump( testargs = ["cz", "bump", "--yes", "--get-next"] mocker.patch.object(sys, "argv", testargs) - with pytest.raises(GetNextExit): + with pytest.raises(DryRunExit): cli.main() out, _ = capsys.readouterr() @@ -1486,39 +1485,6 @@ def test_bump_get_next_update_changelog_on_bump( assert tag_exists is False -@pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next__changelog_is_not_allowed(mocker: MockFixture): - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes", "--get-next", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - - with pytest.raises(NotAllowed): - cli.main() - - -@pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next__changelog_to_stdout_is_not_allowed(mocker: MockFixture): - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes", "--get-next", "--changelog-to-stdout"] - mocker.patch.object(sys, "argv", testargs) - - with pytest.raises(NotAllowed): - cli.main() - - -@pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next__manual_version_is_not_allowed(mocker: MockFixture): - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes", "--get-next", "0.2.1"] - mocker.patch.object(sys, "argv", testargs) - - with pytest.raises(NotAllowed): - cli.main() - - @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_get_next__no_eligible_commits_raises(mocker: MockFixture): create_file_and_commit("chore: new commit") From 34cff20e8503f29fb2eba9da255cd013aa973c45 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Tue, 11 Nov 2025 22:41:49 +0800 Subject: [PATCH 112/221] refactor(bump): extract option validation and new version resolution to new functions --- commitizen/commands/bump.py | 157 +++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 76 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 7d9241587f..acf127fe38 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -29,6 +29,7 @@ Increment, InvalidVersion, Prerelease, + VersionProtocol, get_version_scheme, ) @@ -156,43 +157,91 @@ def _find_increment(self, commits: list[git.GitCommit]) -> Increment | None: ) return bump.find_increment(commits, regex=bump_pattern, increments_map=bump_map) - def __call__(self) -> None: - """Steps executed to bump.""" - provider = get_provider(self.config) - current_version = self.scheme(provider.get_version()) - - increment = self.arguments["increment"] - prerelease = self.arguments["prerelease"] - devrelease = self.arguments["devrelease"] - is_local_version = self.arguments["local_version"] - manual_version = self.arguments["manual_version"] - build_metadata = self.arguments["build_metadata"] - next_version_to_stdout = self.arguments[ - "get_next" - ] # TODO: maybe rename to `next_version_to_stdout` - allow_no_commit = self.arguments["allow_no_commit"] - major_version_zero = self.arguments["major_version_zero"] - - if manual_version: + def _validate_arguments(self, current_version: VersionProtocol) -> None: + errors: list[str] = [] + if self.arguments["manual_version"]: for val, option in ( - (increment, "--increment"), - (prerelease, "--prerelease"), - (devrelease is not None, "--devrelease"), - (is_local_version, "--local-version"), - (build_metadata, "--build-metadata"), - (major_version_zero, "--major-version-zero"), + (self.arguments["increment"], "--increment"), + (self.arguments["prerelease"], "--prerelease"), + (self.arguments["devrelease"] is not None, "--devrelease"), + (self.arguments["local_version"], "--local-version"), + (self.arguments["build_metadata"], "--build-metadata"), + (self.arguments["major_version_zero"], "--major-version-zero"), ): if val: - raise NotAllowed(f"{option} cannot be combined with MANUAL_VERSION") + errors.append(f"{option} cannot be combined with MANUAL_VERSION") - if major_version_zero and current_version.release[0]: - raise NotAllowed( + if self.arguments["major_version_zero"] and current_version.release[0]: + errors.append( f"--major-version-zero is meaningless for current version {current_version}" ) + if self.arguments["build_metadata"] and self.arguments["local_version"]: + errors.append("--local-version cannot be combined with --build-metadata") + + if errors: + raise NotAllowed("\n".join(errors)) + + def _resolve_increment_and_new_version( + self, current_version: VersionProtocol, current_tag: git.GitTag | None + ) -> tuple[Increment | None, VersionProtocol]: + increment = self.arguments["increment"] + if manual_version := self.arguments["manual_version"]: + try: + return increment, self.scheme(manual_version) + except InvalidVersion as exc: + raise InvalidManualVersion( + "[INVALID_MANUAL_VERSION]\n" + f"Invalid manual version: '{manual_version}'" + ) from exc + + if increment is None: + commits = git.get_commits(current_tag.name if current_tag else None) + + # No commits, there is no need to create an empty tag. + # Unless we previously had a prerelease. + if ( + not commits + and not current_version.is_prerelease + and not self.arguments["allow_no_commit"] + ): + raise NoCommitsFoundError("[NO_COMMITS_FOUND]\nNo new commits found.") + + increment = self._find_increment(commits) + + # It may happen that there are commits, but they are not eligible + # for an increment, this generates a problem when using prerelease (#281) + if ( + self.arguments["prerelease"] + and increment is None + and not current_version.is_prerelease + ): + raise NoCommitsFoundError( + "[NO_COMMITS_FOUND]\n" + "No commits found to generate a pre-release.\n" + "To avoid this error, manually specify the type of increment with `--increment`" + ) - if build_metadata and is_local_version: - raise NotAllowed("--local-version cannot be combined with --build-metadata") + # we create an empty PATCH increment for empty tag + if increment is None and self.arguments["allow_no_commit"]: + increment = "PATCH" + + return increment, current_version.bump( + increment, + prerelease=self.arguments["prerelease"], + prerelease_offset=self.bump_settings["prerelease_offset"], + devrelease=self.arguments["devrelease"], + is_local_version=self.arguments["local_version"], + build_metadata=self.arguments["build_metadata"], + exact_increment=self.arguments["increment_mode"] == "exact", + ) + def __call__(self) -> None: + """Steps executed to bump.""" + provider = get_provider(self.config) + current_version = self.scheme(provider.get_version()) + self._validate_arguments(current_version) + + next_version_to_stdout = self.arguments["get_next"] if next_version_to_stdout: for value, option in ( (self.changelog_flag, "--changelog"), @@ -219,53 +268,9 @@ def __call__(self) -> None: is_initial = self._is_initial_tag(current_tag, self.arguments["yes"]) - if manual_version: - try: - new_version = self.scheme(manual_version) - except InvalidVersion as exc: - raise InvalidManualVersion( - "[INVALID_MANUAL_VERSION]\n" - f"Invalid manual version: '{manual_version}'" - ) from exc - else: - if increment is None: - commits = git.get_commits(current_tag.name if current_tag else None) - - # No commits, there is no need to create an empty tag. - # Unless we previously had a prerelease. - if ( - not commits - and not current_version.is_prerelease - and not allow_no_commit - ): - raise NoCommitsFoundError( - "[NO_COMMITS_FOUND]\nNo new commits found." - ) - - increment = self._find_increment(commits) - - # It may happen that there are commits, but they are not eligible - # for an increment, this generates a problem when using prerelease (#281) - if prerelease and increment is None and not current_version.is_prerelease: - raise NoCommitsFoundError( - "[NO_COMMITS_FOUND]\n" - "No commits found to generate a pre-release.\n" - "To avoid this error, manually specify the type of increment with `--increment`" - ) - - # we create an empty PATCH increment for empty tag - if increment is None and allow_no_commit: - increment = "PATCH" - - new_version = current_version.bump( - increment, - prerelease=prerelease, - prerelease_offset=self.bump_settings["prerelease_offset"], - devrelease=devrelease, - is_local_version=is_local_version, - build_metadata=build_metadata, - exact_increment=self.arguments["increment_mode"] == "exact", - ) + increment, new_version = self._resolve_increment_and_new_version( + current_version, current_tag + ) new_tag_version = rules.normalize_tag(new_version) if next_version_to_stdout: From 8421bb16b8175dd357935baaec95286a919f4e64 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 13 Sep 2025 19:18:22 +0800 Subject: [PATCH 113/221] refactor(cargo_provider): cleanup and get rid of potential type errors --- commitizen/providers/cargo_provider.py | 99 +++++++++-------- tests/providers/test_cargo_provider.py | 147 +++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 45 deletions(-) diff --git a/commitizen/providers/cargo_provider.py b/commitizen/providers/cargo_provider.py index 3e8c95e22a..02fdd2cc6d 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -3,19 +3,15 @@ import fnmatch import glob from pathlib import Path +from typing import TYPE_CHECKING -import tomlkit +from tomlkit import TOMLDocument, dumps, parse +from tomlkit.exceptions import NonExistentKey +from tomlkit.items import AoT from commitizen.providers.base_provider import TomlProvider -def matches_exclude(path: str, exclude_patterns: list[str]) -> bool: - for pattern in exclude_patterns: - if fnmatch.fnmatch(path, pattern): - return True - return False - - class CargoProvider(TomlProvider): """ Cargo version management @@ -30,22 +26,14 @@ class CargoProvider(TomlProvider): def lock_file(self) -> Path: return Path() / self.lock_filename - def get(self, document: tomlkit.TOMLDocument) -> str: - # If there is a root package, change its version (but not the workspace version) - try: - return document["package"]["version"] # type: ignore[index,return-value] - # Else, bump the workspace version - except tomlkit.exceptions.NonExistentKey: - ... - return document["workspace"]["package"]["version"] # type: ignore[index,return-value] + def get(self, document: TOMLDocument) -> str: + out = _try_get_workspace(document)["package"]["version"] + if TYPE_CHECKING: + assert isinstance(out, str) + return out - def set(self, document: tomlkit.TOMLDocument, version: str) -> None: - try: - document["workspace"]["package"]["version"] = version # type: ignore[index] - return - except tomlkit.exceptions.NonExistentKey: - ... - document["package"]["version"] = version # type: ignore[index] + def set(self, document: TOMLDocument, version: str) -> None: + _try_get_workspace(document)["package"]["version"] = version def set_version(self, version: str) -> None: super().set_version(version) @@ -53,42 +41,63 @@ def set_version(self, version: str) -> None: self.set_lock_version(version) def set_lock_version(self, version: str) -> None: - cargo_toml_content = tomlkit.parse(self.file.read_text()) - cargo_lock_content = tomlkit.parse(self.lock_file.read_text()) - packages: tomlkit.items.AoT = cargo_lock_content["package"] # type: ignore[assignment] + cargo_toml_content = parse(self.file.read_text()) + cargo_lock_content = parse(self.lock_file.read_text()) + packages = cargo_lock_content["package"] + + if TYPE_CHECKING: + assert isinstance(packages, AoT) + try: - package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + cargo_package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + if TYPE_CHECKING: + assert isinstance(cargo_package_name, str) for i, package in enumerate(packages): - if package["name"] == package_name: + if package["name"] == cargo_package_name: cargo_lock_content["package"][i]["version"] = version # type: ignore[index] break - except tomlkit.exceptions.NonExistentKey: - workspace_members = cargo_toml_content.get("workspace", {}).get( - "members", [] - ) - excluded_workspace_members = cargo_toml_content.get("workspace", {}).get( - "exclude", [] - ) - members_inheriting = [] + except NonExistentKey: + workspace = cargo_toml_content.get("workspace", {}) + if TYPE_CHECKING: + assert isinstance(workspace, dict) + workspace_members = workspace.get("members", []) + excluded_workspace_members = workspace.get("exclude", []) + members_inheriting: list[str] = [] for member in workspace_members: for path in glob.glob(member, recursive=True): - if matches_exclude(path, excluded_workspace_members): + if any( + fnmatch.fnmatch(path, pattern) + for pattern in excluded_workspace_members + ): continue + cargo_file = Path(path) / "Cargo.toml" - cargo_toml_content = tomlkit.parse(cargo_file.read_text()) + package_content = parse(cargo_file.read_text()).get("package", {}) + if TYPE_CHECKING: + assert isinstance(package_content, dict) try: - version_workspace = cargo_toml_content["package"]["version"][ # type: ignore[index] - "workspace" - ] + version_workspace = package_content["version"]["workspace"] if version_workspace is True: - package_name = cargo_toml_content["package"]["name"] # type: ignore[index] + package_name = package_content["name"] + if TYPE_CHECKING: + assert isinstance(package_name, str) members_inheriting.append(package_name) - except tomlkit.exceptions.NonExistentKey: - continue + except NonExistentKey: + pass for i, package in enumerate(packages): if package["name"] in members_inheriting: cargo_lock_content["package"][i]["version"] = version # type: ignore[index] - self.lock_file.write_text(tomlkit.dumps(cargo_lock_content)) + self.lock_file.write_text(dumps(cargo_lock_content)) + + +def _try_get_workspace(document: TOMLDocument) -> dict: + try: + workspace = document["workspace"] + if TYPE_CHECKING: + assert isinstance(workspace, dict) + return workspace + except NonExistentKey: + return document diff --git a/tests/providers/test_cargo_provider.py b/tests/providers/test_cargo_provider.py index 5e7b2d8cb7..b7dc932d38 100644 --- a/tests/providers/test_cargo_provider.py +++ b/tests/providers/test_cargo_provider.py @@ -301,3 +301,150 @@ def test_cargo_provider_with_lock( provider.set_version("42.1") assert file.read_text() == dedent(toml_expected) assert lock_file.read_text() == dedent(lock_expected) + + +def test_cargo_provider_workspace_member_without_version_key( + config: BaseConfig, + chdir: Path, +): + """Test workspace member that has no version key at all (should not crash).""" + workspace_toml = """\ +[workspace] +members = ["member_without_version"] + +[workspace.package] +version = "0.1.0" +""" + + # Create a member that has no version key at all + member_content = """\ +[package] +name = "member_without_version" +# No version key - this should trigger NonExistentKey exception +""" + + lock_content = """\ +[[package]] +name = "member_without_version" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +""" + + expected_workspace_toml = """\ +[workspace] +members = ["member_without_version"] + +[workspace.package] +version = "42.1" +""" + + expected_lock_content = """\ +[[package]] +name = "member_without_version" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +""" + + # Create the workspace file + filename = CargoProvider.filename + file = chdir / filename + file.write_text(dedent(workspace_toml)) + + # Create the member directory and file + os.mkdir(chdir / "member_without_version") + member_file = chdir / "member_without_version" / "Cargo.toml" + member_file.write_text(dedent(member_content)) + + # Create the lock file + lock_filename = CargoProvider.lock_filename + lock_file = chdir / lock_filename + lock_file.write_text(dedent(lock_content)) + + config.settings["version_provider"] = "cargo" + + provider = get_provider(config) + assert isinstance(provider, CargoProvider) + assert provider.get_version() == "0.1.0" + + # This should not crash even though the member has no version key + provider.set_version("42.1") + assert file.read_text() == dedent(expected_workspace_toml) + # The lock file should remain unchanged since the member doesn't inherit workspace version + assert lock_file.read_text() == dedent(expected_lock_content) + + +def test_cargo_provider_workspace_member_without_workspace_key( + config: BaseConfig, + chdir: Path, +): + """Test workspace member that has version key but no workspace subkey.""" + workspace_toml = """\ +[workspace] +members = ["member_without_workspace"] + +[workspace.package] +version = "0.1.0" +""" + + # Create a member that has version as a table but no workspace subkey + # This should trigger NonExistentKey when trying to access version["workspace"] + member_content = """\ +[package] +name = "member_without_workspace" + +[package.version] +# Has version table but no workspace key - should trigger NonExistentKey +""" + + lock_content = """\ +[[package]] +name = "member_without_workspace" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +""" + + expected_workspace_toml = """\ +[workspace] +members = ["member_without_workspace"] + +[workspace.package] +version = "42.1" +""" + + expected_lock_content = """\ +[[package]] +name = "member_without_workspace" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +""" + + # Create the workspace file + filename = CargoProvider.filename + file = chdir / filename + file.write_text(dedent(workspace_toml)) + + # Create the member directory and file + os.mkdir(chdir / "member_without_workspace") + member_file = chdir / "member_without_workspace" / "Cargo.toml" + member_file.write_text(dedent(member_content)) + + # Create the lock file + lock_filename = CargoProvider.lock_filename + lock_file = chdir / lock_filename + lock_file.write_text(dedent(lock_content)) + + config.settings["version_provider"] = "cargo" + + provider = get_provider(config) + assert isinstance(provider, CargoProvider) + assert provider.get_version() == "0.1.0" + + # This should not crash even though the member has no version.workspace key + provider.set_version("42.1") + assert file.read_text() == dedent(expected_workspace_toml) + # The lock file should remain unchanged since the member doesn't inherit workspace version + assert lock_file.read_text() == dedent(expected_lock_content) From 7529611c006a67a0338e53fe2bb3d01ff9eff491 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Thu, 20 Nov 2025 23:49:38 +0800 Subject: [PATCH 114/221] docs(exit-codes): general update docs(exception): add comment for updating exit code doc --- commitizen/exceptions.py | 73 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/commitizen/exceptions.py b/commitizen/exceptions.py index 49cd1832b0..52193e6ccc 100644 --- a/commitizen/exceptions.py +++ b/commitizen/exceptions.py @@ -29,7 +29,7 @@ class ExitCode(IntEnum): INVALID_CONFIGURATION = 19 NOT_ALLOWED = 20 NO_INCREMENT = 21 - UNRECOGNIZED_CHARACTERSET_ENCODING = 22 + CHARACTER_SET_DECODE_ERROR = 22 GIT_COMMAND_ERROR = 23 INVALID_MANUAL_VERSION = 24 INIT_FAILED = 25 @@ -72,32 +72,44 @@ def __init__(self, *args: str, **kwargs: Any) -> None: class DryRunExit(ExpectedExit): - pass + """Exit due to passing `--dry-run` option""" class NoneIncrementExit(CommitizenException): + """The commits found are not eligible to be bumped""" + exit_code = ExitCode.NO_INCREMENT class NoCommitizenFoundException(CommitizenException): + """Using a cz (e.g., `cz_jira`) that cannot be found in your system""" + exit_code = ExitCode.NO_COMMITIZEN_FOUND class NotAGitProjectError(CommitizenException): + """Not in a git project""" + exit_code = ExitCode.NOT_A_GIT_PROJECT message = "fatal: not a git repository (or any of the parent directories): .git" class MissingCzCustomizeConfigError(CommitizenException): + """Configuration is missing for `cz_customize`""" + exit_code = ExitCode.MISSING_CZ_CUSTOMIZE_CONFIG message = "fatal: customize is not set in configuration file." class NoCommitsFoundError(CommitizenException): + """No commits found""" + exit_code = ExitCode.NO_COMMITS_FOUND class NoVersionSpecifiedError(CommitizenException): + """Version is not specified in configuration file""" + exit_code = ExitCode.NO_VERSION_SPECIFIED message = ( "[NO_VERSION_SPECIFIED]\n" @@ -107,111 +119,166 @@ class NoVersionSpecifiedError(CommitizenException): class NoPatternMapError(CommitizenException): + """bump / changelog pattern or map can not be found in configuration file""" + exit_code = ExitCode.NO_PATTERN_MAP class BumpCommitFailedError(CommitizenException): + """Commit failed when bumping version""" + exit_code = ExitCode.BUMP_COMMIT_FAILED class BumpTagFailedError(CommitizenException): + """Tag failed when bumping version""" + exit_code = ExitCode.BUMP_TAG_FAILED class CurrentVersionNotFoundError(CommitizenException): + """Current version cannot be found in `version_files`""" + exit_code = ExitCode.CURRENT_VERSION_NOT_FOUND class NoAnswersError(CommitizenException): + """No user response given""" + exit_code = ExitCode.NO_ANSWERS class CommitError(CommitizenException): + """git commit error""" + exit_code = ExitCode.COMMIT_ERROR class NoCommitBackupError(CommitizenException): + """Commit backup file is not found""" + exit_code = ExitCode.NO_COMMIT_BACKUP message = "No commit backup found" class NothingToCommitError(CommitizenException): + """Nothing in staging to be committed""" + exit_code = ExitCode.NOTHING_TO_COMMIT class CustomError(CommitizenException): + """`CzException` raised""" + exit_code = ExitCode.CUSTOM_ERROR class InvalidCommitMessageError(CommitizenException): + """The commit message does not pass `cz check`""" + exit_code = ExitCode.INVALID_COMMIT_MSG class NoRevisionError(CommitizenException): + """No revision found""" + exit_code = ExitCode.NO_REVISION message = "No tag found to do an incremental changelog" class NoCommandFoundError(CommitizenException): + """No command found when running Commitizen cli (e.g., `cz --debug`)""" + exit_code = ExitCode.NO_COMMAND_FOUND message = "Command is required" class InvalidCommandArgumentError(CommitizenException): + """The argument provided to the command is invalid (e.g. `cz check -commit-msg-file filename --rev-range master..`)""" + exit_code = ExitCode.INVALID_COMMAND_ARGUMENT class InvalidConfigurationError(CommitizenException): + """An error was found in the Commitizen Configuration, such as duplicates in `change_type_order`""" + exit_code = ExitCode.INVALID_CONFIGURATION class NotAllowed(CommitizenException): + """`--incremental` cannot be combined with a `rev_range`""" + exit_code = ExitCode.NOT_ALLOWED class CharacterSetDecodeError(CommitizenException): - exit_code = ExitCode.UNRECOGNIZED_CHARACTERSET_ENCODING + """The character encoding of the command output could not be determined""" + + exit_code = ExitCode.CHARACTER_SET_DECODE_ERROR class GitCommandError(CommitizenException): + """Unexpected failure while calling a git command""" + exit_code = ExitCode.GIT_COMMAND_ERROR class InvalidManualVersion(CommitizenException): + """Manually provided version is invalid""" + exit_code = ExitCode.INVALID_MANUAL_VERSION class InitFailedError(CommitizenException): + """Failed to initialize pre-commit""" + exit_code = ExitCode.INIT_FAILED class RunHookError(CommitizenException): + """An error occurred during a hook execution""" + exit_code = ExitCode.RUN_HOOK_FAILED class VersionProviderUnknown(CommitizenException): + """Unknown `version_provider`""" + exit_code = ExitCode.VERSION_PROVIDER_UNKNOWN class VersionSchemeUnknown(CommitizenException): + """Unknown `version_scheme`""" + exit_code = ExitCode.VERSION_SCHEME_UNKNOWN class ChangelogFormatUnknown(CommitizenException): + """Unknown `changelog_format` or cannot be determined by the file extension""" + exit_code = ExitCode.CHANGELOG_FORMAT_UNKNOWN message = "Unknown changelog format identifier" class ConfigFileNotFound(CommitizenException): + """The configuration file is not found""" + exit_code = ExitCode.CONFIG_FILE_NOT_FOUND message = "Cannot found the config file, please check your file path again." class ConfigFileIsEmpty(CommitizenException): + """The configuration file is empty""" + exit_code = ExitCode.CONFIG_FILE_IS_EMPTY message = "Config file is empty, please check your file path again." class CommitMessageLengthExceededError(CommitizenException): + """The commit message length exceeds the given limit.""" + exit_code = ExitCode.COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED message = "Length of commit message exceeds the given limit." + + +# When adding / updating a new exit code, please update the documentation of the exit codes in docs/exit_codes.md From c8c91f1722399ba8ed862eb70f6129639db0c7e6 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Wed, 3 Dec 2025 22:55:17 +0800 Subject: [PATCH 115/221] test: replace try with pytest.raises (#1654) --- tests/commands/test_bump_command.py | 12 +++++------- tests/commands/test_changelog_command.py | 7 ++++--- tests/test_git.py | 14 +++++++++----- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index 7b9edee82f..8871a6bf0f 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -646,13 +646,11 @@ def test_none_increment_should_not_call_git_tag_and_error_code_is_not_zero( dummy_value = git.tag("0.0.2") git.tag = MagicMock(return_value=dummy_value) - with pytest.raises(NoneIncrementExit): - try: - cli.main() - except NoneIncrementExit as e: - git.tag.assert_not_called() - assert e.exit_code == ExitCode.NO_INCREMENT - raise e + with pytest.raises(NoneIncrementExit) as e: + cli.main() + + git.tag.assert_not_called() + assert e.value.exit_code == ExitCode.NO_INCREMENT # restore pop stashed git.tag = stashed_git_tag diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index f147c419b8..f2e2ecbd38 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -292,10 +292,11 @@ def test_changelog_hook(mocker: MockFixture, config: BaseConfig, dry_run: bool): config, {"unreleased_version": None, "incremental": True, "dry_run": dry_run} ) mocker.patch.object(changelog.cz, "changelog_hook", changelog_hook_mock) - try: + if dry_run: + with pytest.raises(DryRunExit): + changelog() + else: changelog() - except DryRunExit: - pass full_changelog = ( "## Unreleased\n\n### Refactor\n\n- is in changelog\n\n### Feat\n\n- new file\n" diff --git a/tests/test_git.py b/tests/test_git.py index 2a31d9c0b8..f433ed633a 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -8,7 +8,8 @@ import pytest from pytest_mock import MockFixture -from commitizen import cmd, exceptions, git +from commitizen import cmd, git +from commitizen.exceptions import GitCommandError from tests.utils import ( FakeCommand, create_branch, @@ -110,10 +111,13 @@ def test_git_message_with_empty_body(): @pytest.mark.usefixtures("tmp_commitizen_project") def test_get_log_as_str_list_empty(): - """ensure an exception or empty list in an empty project""" + """ + Ensure an exception is raised or empty list in an empty project. + The behavior is different depending on the version of git. + """ try: gitlog = git._get_log_as_str_list(start=None, end="HEAD", args="") - except exceptions.GitCommandError: + except GitCommandError: return assert len(gitlog) == 0, "list should be empty if no assert" @@ -409,7 +413,7 @@ def test_get_filenames_in_commit_error(mocker: MockFixture): "commitizen.cmd.run", return_value=FakeCommand(out="", err="fatal: bad object HEAD", return_code=1), ) - with pytest.raises(exceptions.GitCommandError) as excinfo: + with pytest.raises(GitCommandError) as excinfo: git.get_filenames_in_commit() assert str(excinfo.value) == "fatal: bad object HEAD" @@ -497,5 +501,5 @@ def test_get_default_branch_error(mocker: MockFixture): return_code=1, ), ) - with pytest.raises(exceptions.GitCommandError): + with pytest.raises(GitCommandError): git.get_default_branch() From e2081c8202cc72a02bd6e7f9217a8f59f5dd75c6 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 3 Dec 2025 23:23:36 +0800 Subject: [PATCH 116/221] fix(git): replace lstrip with strip for compatibility issue #1032 --- commitizen/git.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commitizen/git.py b/commitizen/git.py index c124cd9371..e598ff065c 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -237,7 +237,7 @@ def get_tags( ) -> list[GitTag]: inner_delimiter = "---inner_delimiter---" formatter = ( - f'"%(refname:lstrip=2){inner_delimiter}' + f'"%(refname:strip=2){inner_delimiter}' f"%(objectname){inner_delimiter}" f"%(creatordate:format:{dateformat}){inner_delimiter}" f'%(object)"' From 755fd82ee8d9ba7f822833571c3886c2af90262a Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 3 Dec 2025 21:53:58 +0800 Subject: [PATCH 117/221] perf: add TYPE_CHECKING to CzQuestion imports --- commitizen/cz/base.py | 6 ++++-- .../cz/conventional_commits/conventional_commits.py | 8 ++++++-- commitizen/cz/customize/customize.py | 4 ++-- commitizen/cz/jira/jira.py | 7 ++++++- commitizen/defaults.py | 5 +++-- tests/conftest.py | 5 ++++- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index 8466b58bba..f7d6ea24f2 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -2,14 +2,16 @@ from abc import ABCMeta, abstractmethod from collections.abc import Iterable, Mapping -from typing import Any, Callable, Protocol +from typing import TYPE_CHECKING, Any, Callable, Protocol from jinja2 import BaseLoader, PackageLoader from prompt_toolkit.styles import Style from commitizen import git from commitizen.config.base_config import BaseConfig -from commitizen.question import CzQuestion + +if TYPE_CHECKING: + from commitizen.question import CzQuestion class MessageBuilderHook(Protocol): diff --git a/commitizen/cz/conventional_commits/conventional_commits.py b/commitizen/cz/conventional_commits/conventional_commits.py index f0b254eb10..1d1930595b 100644 --- a/commitizen/cz/conventional_commits/conventional_commits.py +++ b/commitizen/cz/conventional_commits/conventional_commits.py @@ -1,10 +1,14 @@ +from __future__ import annotations + import os -from typing import TypedDict +from typing import TYPE_CHECKING, TypedDict from commitizen import defaults from commitizen.cz.base import BaseCommitizen from commitizen.cz.utils import multiple_line_breaker, required_validator -from commitizen.question import CzQuestion + +if TYPE_CHECKING: + from commitizen.question import CzQuestion __all__ = ["ConventionalCommitsCz"] diff --git a/commitizen/cz/customize/customize.py b/commitizen/cz/customize/customize.py index dde2685496..fa774e4202 100644 --- a/commitizen/cz/customize/customize.py +++ b/commitizen/cz/customize/customize.py @@ -3,10 +3,10 @@ from collections.abc import Mapping from typing import TYPE_CHECKING, Any -from commitizen.question import CzQuestion - if TYPE_CHECKING: from jinja2 import Template + + from commitizen.question import CzQuestion else: try: from jinja2 import Template diff --git a/commitizen/cz/jira/jira.py b/commitizen/cz/jira/jira.py index 4e6024ff74..9c9fbf8fa2 100644 --- a/commitizen/cz/jira/jira.py +++ b/commitizen/cz/jira/jira.py @@ -1,8 +1,13 @@ +from __future__ import annotations + import os from collections.abc import Mapping +from typing import TYPE_CHECKING from commitizen.cz.base import BaseCommitizen -from commitizen.question import CzQuestion + +if TYPE_CHECKING: + from commitizen.question import CzQuestion __all__ = ["JiraSmartCz"] diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 9b3b76a686..c78dc18f8c 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -4,9 +4,10 @@ import warnings from collections import OrderedDict from collections.abc import Iterable, MutableMapping, Sequence -from typing import Any, TypedDict +from typing import TYPE_CHECKING, Any, TypedDict -from commitizen.question import CzQuestion +if TYPE_CHECKING: + from commitizen.question import CzQuestion class CzSettings(TypedDict, total=False): diff --git a/tests/conftest.py b/tests/conftest.py index 04a448d99a..95e4a33c65 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ import tempfile from collections.abc import Iterator, Mapping from pathlib import Path +from typing import TYPE_CHECKING import pytest from pytest_mock import MockerFixture @@ -17,7 +18,9 @@ from commitizen.config import BaseConfig from commitizen.cz import registry from commitizen.cz.base import BaseCommitizen -from commitizen.question import CzQuestion + +if TYPE_CHECKING: + from commitizen.question import CzQuestion from tests.utils import create_file_and_commit SIGNER = "GitHub Action" From bc2ba3951db4bac596925ca8bfaea4bfe20d4440 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Thu, 4 Dec 2025 00:35:05 +0800 Subject: [PATCH 118/221] fix(cli): debug and no_raise can be used together in sys.excepthook Closes #1294 --- commitizen/cli.py | 28 ++++++++-------------------- tests/test_cli.py | 14 +++++++------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index c11e9078dc..f4f92cb0a4 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -559,8 +559,6 @@ def __call__( }, } -original_excepthook = sys.excepthook - def commitizen_excepthook( type: type[BaseException], @@ -571,26 +569,19 @@ def commitizen_excepthook( ) -> None: traceback = traceback if isinstance(traceback, TracebackType) else None if not isinstance(value, CommitizenException): - original_excepthook(type, value, traceback) + sys.__excepthook__(type, value, traceback) return - if not no_raise: - no_raise = [] if value.message: value.output_method(value.message) if debug: - original_excepthook(type, value, traceback) + sys.__excepthook__(type, value, traceback) exit_code = value.exit_code - if exit_code in no_raise: - exit_code = ExitCode.EXPECTED_EXIT + if no_raise is not None and exit_code in no_raise: + sys.exit(ExitCode.EXPECTED_EXIT) sys.exit(exit_code) -commitizen_debug_excepthook = partial(commitizen_excepthook, debug=True) - -sys.excepthook = commitizen_excepthook - - def parse_no_raise(comma_separated_no_raise: str) -> list[int]: """Convert the given string to exit codes. @@ -682,15 +673,12 @@ def main() -> None: elif not conf.path: conf.update({"name": "cz_conventional_commits"}) + sys.excepthook = commitizen_excepthook if args.debug: logging.getLogger("commitizen").setLevel(logging.DEBUG) - sys.excepthook = commitizen_debug_excepthook - elif args.no_raise: - no_raise_exit_codes = parse_no_raise(args.no_raise) - no_raise_debug_excepthook = partial( - commitizen_excepthook, no_raise=no_raise_exit_codes - ) - sys.excepthook = no_raise_debug_excepthook + sys.excepthook = partial(sys.excepthook, debug=True) + if args.no_raise: + sys.excepthook = partial(sys.excepthook, no_raise=parse_no_raise(args.no_raise)) args.func(conf, arguments)() # type: ignore[arg-type] diff --git a/tests/test_cli.py b/tests/test_cli.py index 31371caea4..f91a27373a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -186,10 +186,10 @@ def test_unknown_args_before_double_dash_raises(mocker: MockFixture): def test_commitizen_excepthook_non_commitizen_exception(mocker: MockFixture): - """Test that commitizen_excepthook delegates to original_excepthook for non-CommitizenException.""" + """Test that commitizen_excepthook delegates to sys.__excepthook__ for non-CommitizenException.""" # Mock the original excepthook mock_original_excepthook = mocker.Mock() - mocker.patch("commitizen.cli.original_excepthook", mock_original_excepthook) + mocker.patch("commitizen.cli.sys.__excepthook__", mock_original_excepthook) # Create a regular exception test_exception = ValueError("test error") @@ -197,7 +197,7 @@ def test_commitizen_excepthook_non_commitizen_exception(mocker: MockFixture): # Call commitizen_excepthook with the regular exception cli.commitizen_excepthook(ValueError, test_exception, None) - # Verify original_excepthook was called with correct arguments + # Verify sys.__excepthook__ was called with correct arguments mock_original_excepthook.assert_called_once_with(ValueError, test_exception, None) @@ -207,7 +207,7 @@ def test_commitizen_excepthook_non_commitizen_exception_with_traceback( """Test that commitizen_excepthook handles traceback correctly for non-CommitizenException.""" # Mock the original excepthook mock_original_excepthook = mocker.Mock() - mocker.patch("commitizen.cli.original_excepthook", mock_original_excepthook) + mocker.patch("commitizen.cli.sys.__excepthook__", mock_original_excepthook) # Create a regular exception with a traceback test_exception = ValueError("test error") @@ -216,7 +216,7 @@ def test_commitizen_excepthook_non_commitizen_exception_with_traceback( # Call commitizen_excepthook with the regular exception and traceback cli.commitizen_excepthook(ValueError, test_exception, test_traceback) - # Verify original_excepthook was called with correct arguments including traceback + # Verify sys.__excepthook__ was called with correct arguments including traceback mock_original_excepthook.assert_called_once_with( ValueError, test_exception, test_traceback ) @@ -228,7 +228,7 @@ def test_commitizen_excepthook_non_commitizen_exception_with_invalid_traceback( """Test that commitizen_excepthook handles invalid traceback correctly for non-CommitizenException.""" # Mock the original excepthook mock_original_excepthook = mocker.Mock() - mocker.patch("commitizen.cli.original_excepthook", mock_original_excepthook) + mocker.patch("commitizen.cli.sys.__excepthook__", mock_original_excepthook) # Create a regular exception with an invalid traceback test_exception = ValueError("test error") @@ -237,5 +237,5 @@ def test_commitizen_excepthook_non_commitizen_exception_with_invalid_traceback( # Call commitizen_excepthook with the regular exception and invalid traceback cli.commitizen_excepthook(ValueError, test_exception, test_traceback) - # Verify original_excepthook was called with None as traceback + # Verify sys.__excepthook__ was called with None as traceback mock_original_excepthook.assert_called_once_with(ValueError, test_exception, None) From 1441c3d4b128eb6f11818730b94692dd7496c5dc Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Thu, 4 Dec 2025 21:42:28 +0800 Subject: [PATCH 119/221] perf(ruff): enable ruff rules TC001~TC006 --- commitizen/bump.py | 11 +++++++---- commitizen/changelog.py | 8 ++++---- commitizen/changelog_formats/__init__.py | 8 +++++--- commitizen/changelog_formats/base.py | 6 ++++-- commitizen/cmd.py | 6 ++++-- commitizen/commands/bump.py | 10 ++++++---- commitizen/commands/changelog.py | 11 +++++++---- commitizen/commands/check.py | 6 ++++-- commitizen/commands/commit.py | 9 ++++++--- commitizen/commands/init.py | 10 ++++++---- commitizen/config/__init__.py | 5 ++++- commitizen/config/factory.py | 8 ++++++-- commitizen/config/json_config.py | 2 +- commitizen/config/toml_config.py | 2 +- commitizen/config/yaml_config.py | 2 +- commitizen/cz/__init__.py | 8 ++++++-- commitizen/cz/base.py | 8 ++++---- commitizen/cz/customize/customize.py | 5 +++-- commitizen/cz/jira/jira.py | 3 ++- commitizen/defaults.py | 3 ++- commitizen/hooks.py | 5 ++++- commitizen/providers/__init__.py | 10 ++++++---- commitizen/providers/base_provider.py | 8 +++++--- commitizen/providers/cargo_provider.py | 4 +++- commitizen/providers/npm_provider.py | 6 ++++-- commitizen/providers/poetry_provider.py | 5 ++++- commitizen/providers/uv_provider.py | 5 +---- commitizen/tags.py | 2 +- commitizen/version_schemes.py | 4 ++-- pyproject.toml | 7 +++++++ tests/commands/test_bump_command.py | 12 ++++++++---- tests/commands/test_check_command.py | 5 ++++- tests/commands/test_init_command.py | 9 ++++++--- tests/conftest.py | 8 +++++--- tests/providers/conftest.py | 5 ++++- tests/providers/test_base_provider.py | 6 +++++- tests/providers/test_cargo_provider.py | 5 ++++- tests/providers/test_commitizen_provider.py | 3 ++- tests/providers/test_composer_provider.py | 8 ++++++-- tests/providers/test_npm_provider.py | 8 ++++++-- tests/providers/test_pep621_provider.py | 8 ++++++-- tests/providers/test_poetry_provider.py | 8 ++++++-- tests/providers/test_scm_provider.py | 6 +++++- tests/providers/test_uv_provider.py | 3 ++- tests/test_changelog.py | 6 ++++-- tests/test_changelog_format_asciidoc.py | 8 ++++++-- tests/test_changelog_format_markdown.py | 8 ++++++-- tests/test_changelog_format_restructuredtext.py | 6 ++++-- tests/test_changelog_format_textile.py | 8 ++++++-- tests/test_changelog_formats.py | 6 +++++- tests/test_git.py | 5 ++++- tests/test_version_schemes.py | 9 +++++++-- tests/utils.py | 6 ++++-- 53 files changed, 235 insertions(+), 108 deletions(-) diff --git a/commitizen/bump.py b/commitizen/bump.py index a955c20b6c..cb572d3612 100644 --- a/commitizen/bump.py +++ b/commitizen/bump.py @@ -3,16 +3,19 @@ import os import re from collections import OrderedDict -from collections.abc import Generator, Iterable from glob import iglob from logging import getLogger from string import Template -from typing import cast +from typing import TYPE_CHECKING, cast from commitizen.defaults import BUMP_MESSAGE, MAJOR, MINOR, PATCH from commitizen.exceptions import CurrentVersionNotFoundError from commitizen.git import GitCommit, smart_open -from commitizen.version_schemes import Increment, Version + +if TYPE_CHECKING: + from collections.abc import Generator, Iterable + + from commitizen.version_schemes import Increment, Version VERSION_TYPES = [None, PATCH, MINOR, MAJOR] @@ -56,7 +59,7 @@ def find_increment( if increment == MAJOR: break - return cast(Increment, increment) + return cast("Increment", increment) def update_version_in_files( diff --git a/commitizen/changelog.py b/commitizen/changelog.py index bdf11326be..dfc4157725 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -29,7 +29,6 @@ import re from collections import OrderedDict, defaultdict -from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence from dataclasses import dataclass from datetime import date from itertools import chain @@ -44,13 +43,14 @@ Template, ) -from commitizen.cz.base import ChangelogReleaseHook from commitizen.exceptions import InvalidConfigurationError, NoCommitsFoundError -from commitizen.git import GitCommit, GitTag from commitizen.tags import TagRules if TYPE_CHECKING: - from commitizen.cz.base import MessageBuilderHook + from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence + + from commitizen.cz.base import ChangelogReleaseHook, MessageBuilderHook + from commitizen.git import GitCommit, GitTag @dataclass diff --git a/commitizen/changelog_formats/__init__.py b/commitizen/changelog_formats/__init__.py index 9a5eea7ab2..e4eb5e0a59 100644 --- a/commitizen/changelog_formats/__init__.py +++ b/commitizen/changelog_formats/__init__.py @@ -1,17 +1,19 @@ from __future__ import annotations import sys -from typing import Callable, ClassVar, Protocol +from typing import TYPE_CHECKING, Callable, ClassVar, Protocol if sys.version_info >= (3, 10): from importlib import metadata else: import importlib_metadata as metadata -from commitizen.changelog import Metadata -from commitizen.config.base_config import BaseConfig from commitizen.exceptions import ChangelogFormatUnknown +if TYPE_CHECKING: + from commitizen.changelog import Metadata + from commitizen.config.base_config import BaseConfig + CHANGELOG_FORMAT_ENTRYPOINT = "commitizen.changelog_format" TEMPLATE_EXTENSION = "j2" diff --git a/commitizen/changelog_formats/base.py b/commitizen/changelog_formats/base.py index 64a795207a..eef6a23689 100644 --- a/commitizen/changelog_formats/base.py +++ b/commitizen/changelog_formats/base.py @@ -2,15 +2,17 @@ import os from abc import ABCMeta -from typing import IO, Any, ClassVar +from typing import IO, TYPE_CHECKING, Any, ClassVar from commitizen.changelog import Metadata -from commitizen.config.base_config import BaseConfig from commitizen.tags import TagRules, VersionTag from commitizen.version_schemes import get_version_scheme from . import ChangelogFormat +if TYPE_CHECKING: + from commitizen.config.base_config import BaseConfig + class BaseFormat(ChangelogFormat, metaclass=ABCMeta): """ diff --git a/commitizen/cmd.py b/commitizen/cmd.py index c8d4f33010..fe70da9c9b 100644 --- a/commitizen/cmd.py +++ b/commitizen/cmd.py @@ -2,13 +2,15 @@ import os import subprocess -from collections.abc import Mapping -from typing import NamedTuple +from typing import TYPE_CHECKING, NamedTuple from charset_normalizer import from_bytes from commitizen.exceptions import CharacterSetDecodeError +if TYPE_CHECKING: + from collections.abc import Mapping + class Command(NamedTuple): out: str diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index acf127fe38..0ed5ffd5b8 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -2,14 +2,13 @@ import warnings from logging import getLogger -from typing import cast +from typing import TYPE_CHECKING, cast import questionary from commitizen import bump, factory, git, hooks, out from commitizen.changelog_formats import get_changelog_format from commitizen.commands.changelog import Changelog -from commitizen.config import BaseConfig from commitizen.defaults import Settings from commitizen.exceptions import ( BumpCommitFailedError, @@ -33,6 +32,9 @@ get_version_scheme, ) +if TYPE_CHECKING: + from commitizen.config import BaseConfig + logger = getLogger("commitizen") @@ -69,7 +71,7 @@ def __init__(self, config: BaseConfig, arguments: BumpArgs) -> None: self.config: BaseConfig = config self.arguments = arguments self.bump_settings = cast( - BumpArgs, + "BumpArgs", { **config.settings, **{ @@ -260,7 +262,7 @@ def __call__(self) -> None: ) ) - rules = TagRules.from_settings(cast(Settings, self.bump_settings)) + rules = TagRules.from_settings(cast("Settings", self.bump_settings)) current_tag = rules.find_tag_for(git.get_tags(), current_version) current_tag_version = ( current_tag.name if current_tag else rules.normalize_tag(current_version) diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index 805d7472da..215e03206a 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -2,15 +2,13 @@ import os import os.path -from collections.abc import Generator, Iterable from difflib import SequenceMatcher from operator import itemgetter from pathlib import Path -from typing import Any, TypedDict, cast +from typing import TYPE_CHECKING, Any, TypedDict, cast from commitizen import changelog, defaults, factory, git, out from commitizen.changelog_formats import get_changelog_format -from commitizen.config import BaseConfig from commitizen.cz.utils import strip_local_version from commitizen.exceptions import ( DryRunExit, @@ -24,6 +22,11 @@ from commitizen.tags import TagRules from commitizen.version_schemes import get_version_scheme +if TYPE_CHECKING: + from collections.abc import Generator, Iterable + + from commitizen.config import BaseConfig + class ChangelogArgs(TypedDict, total=False): change_type_map: dict[str, str] @@ -97,7 +100,7 @@ def __init__(self, config: BaseConfig, arguments: ChangelogArgs) -> None: self.config.settings.get("change_type_map") or self.cz.change_type_map ) self.change_type_order = cast( - list[str], + "list[str]", self.config.settings.get("change_type_order") or self.cz.change_type_order or defaults.CHANGE_TYPE_ORDER, diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index a6101f7df7..0ea5885eba 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -2,10 +2,9 @@ import re import sys -from typing import TypedDict +from typing import TYPE_CHECKING, TypedDict from commitizen import factory, git, out -from commitizen.config import BaseConfig from commitizen.exceptions import ( CommitMessageLengthExceededError, InvalidCommandArgumentError, @@ -13,6 +12,9 @@ NoCommitsFoundError, ) +if TYPE_CHECKING: + from commitizen.config import BaseConfig + class CheckArgs(TypedDict, total=False): commit_msg_file: str diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 7144bced87..3894d0b77e 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -5,13 +5,11 @@ import shutil import subprocess import tempfile -from pathlib import Path -from typing import TypedDict +from typing import TYPE_CHECKING, TypedDict import questionary from commitizen import factory, git, out -from commitizen.config import BaseConfig from commitizen.cz.exceptions import CzException from commitizen.cz.utils import get_backup_file_path from commitizen.exceptions import ( @@ -27,6 +25,11 @@ ) from commitizen.git import smart_open +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config import BaseConfig + class CommitArgs(TypedDict, total=False): all: bool diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 4a8a69d9e9..62678a2244 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -1,16 +1,13 @@ from __future__ import annotations from pathlib import Path -from typing import Any, NamedTuple +from typing import TYPE_CHECKING, Any, NamedTuple import questionary import yaml from commitizen import cmd, factory, out, project_info from commitizen.__version__ import __version__ -from commitizen.config import ( - BaseConfig, -) from commitizen.config.factory import create_config from commitizen.cz import registry from commitizen.defaults import CONFIG_FILES, DEFAULT_SETTINGS @@ -18,6 +15,11 @@ from commitizen.git import get_latest_tag_name, get_tag_names, smart_open from commitizen.version_schemes import KNOWN_SCHEMES, Version, get_version_scheme +if TYPE_CHECKING: + from commitizen.config import ( + BaseConfig, + ) + class _VersionProviderOption(NamedTuple): provider_name: str diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index 6cf8b840d8..e30f9f789c 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -1,7 +1,7 @@ from __future__ import annotations -from collections.abc import Generator from pathlib import Path +from typing import TYPE_CHECKING from commitizen import defaults, git from commitizen.config.factory import create_config @@ -9,6 +9,9 @@ from .base_config import BaseConfig +if TYPE_CHECKING: + from collections.abc import Generator + def _resolve_config_paths(filepath: str | None = None) -> Generator[Path, None, None]: if filepath is not None: diff --git a/commitizen/config/factory.py b/commitizen/config/factory.py index b77aea5f32..d0a212b73f 100644 --- a/commitizen/config/factory.py +++ b/commitizen/config/factory.py @@ -1,12 +1,16 @@ from __future__ import annotations -from pathlib import Path +from typing import TYPE_CHECKING -from commitizen.config.base_config import BaseConfig from commitizen.config.json_config import JsonConfig from commitizen.config.toml_config import TomlConfig from commitizen.config.yaml_config import YAMLConfig +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig + def create_config(*, data: bytes | str | None = None, path: Path) -> BaseConfig: if "toml" in path.suffix: diff --git a/commitizen/config/json_config.py b/commitizen/config/json_config.py index 4e7097aa1a..860ca8ed5a 100644 --- a/commitizen/config/json_config.py +++ b/commitizen/config/json_config.py @@ -1,7 +1,6 @@ from __future__ import annotations import json -from pathlib import Path from typing import TYPE_CHECKING from commitizen.exceptions import InvalidConfigurationError @@ -11,6 +10,7 @@ if TYPE_CHECKING: import sys + from pathlib import Path # Self is Python 3.11+ but backported in typing-extensions if sys.version_info < (3, 11): diff --git a/commitizen/config/toml_config.py b/commitizen/config/toml_config.py index 4ea1dca7d4..b10cf9bd3e 100644 --- a/commitizen/config/toml_config.py +++ b/commitizen/config/toml_config.py @@ -1,7 +1,6 @@ from __future__ import annotations import os -from pathlib import Path from typing import TYPE_CHECKING from tomlkit import TOMLDocument, exceptions, parse, table @@ -12,6 +11,7 @@ if TYPE_CHECKING: import sys + from pathlib import Path # Self is Python 3.11+ but backported in typing-extensions if sys.version_info < (3, 11): diff --git a/commitizen/config/yaml_config.py b/commitizen/config/yaml_config.py index c048ab272a..58722d0f60 100644 --- a/commitizen/config/yaml_config.py +++ b/commitizen/config/yaml_config.py @@ -1,6 +1,5 @@ from __future__ import annotations -from pathlib import Path from typing import TYPE_CHECKING import yaml @@ -12,6 +11,7 @@ if TYPE_CHECKING: import sys + from pathlib import Path # Self is Python 3.11+ but backported in typing-extensions if sys.version_info < (3, 11): diff --git a/commitizen/cz/__init__.py b/commitizen/cz/__init__.py index cb17fe32cd..58753036ff 100644 --- a/commitizen/cz/__init__.py +++ b/commitizen/cz/__init__.py @@ -4,14 +4,18 @@ import pkgutil import sys import warnings -from collections.abc import Iterable if sys.version_info >= (3, 10): from importlib import metadata else: import importlib_metadata as metadata -from commitizen.cz.base import BaseCommitizen +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from collections.abc import Iterable + + from commitizen.cz.base import BaseCommitizen def discover_plugins( diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index f7d6ea24f2..e4bf88cc1c 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -1,16 +1,16 @@ from __future__ import annotations from abc import ABCMeta, abstractmethod -from collections.abc import Iterable, Mapping from typing import TYPE_CHECKING, Any, Callable, Protocol from jinja2 import BaseLoader, PackageLoader from prompt_toolkit.styles import Style -from commitizen import git -from commitizen.config.base_config import BaseConfig - if TYPE_CHECKING: + from collections.abc import Iterable, Mapping + + from commitizen import git + from commitizen.config.base_config import BaseConfig from commitizen.question import CzQuestion diff --git a/commitizen/cz/customize/customize.py b/commitizen/cz/customize/customize.py index fa774e4202..0bc31db30a 100644 --- a/commitizen/cz/customize/customize.py +++ b/commitizen/cz/customize/customize.py @@ -1,11 +1,13 @@ from __future__ import annotations -from collections.abc import Mapping from typing import TYPE_CHECKING, Any if TYPE_CHECKING: + from collections.abc import Mapping + from jinja2 import Template + from commitizen.config import BaseConfig from commitizen.question import CzQuestion else: try: @@ -15,7 +17,6 @@ from commitizen import defaults -from commitizen.config import BaseConfig from commitizen.cz.base import BaseCommitizen from commitizen.exceptions import MissingCzCustomizeConfigError diff --git a/commitizen/cz/jira/jira.py b/commitizen/cz/jira/jira.py index 9c9fbf8fa2..bbe4fc5ee3 100644 --- a/commitizen/cz/jira/jira.py +++ b/commitizen/cz/jira/jira.py @@ -1,12 +1,13 @@ from __future__ import annotations import os -from collections.abc import Mapping from typing import TYPE_CHECKING from commitizen.cz.base import BaseCommitizen if TYPE_CHECKING: + from collections.abc import Mapping + from commitizen.question import CzQuestion __all__ = ["JiraSmartCz"] diff --git a/commitizen/defaults.py b/commitizen/defaults.py index c78dc18f8c..b91fe4879c 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -1,12 +1,13 @@ from __future__ import annotations -import pathlib import warnings from collections import OrderedDict from collections.abc import Iterable, MutableMapping, Sequence from typing import TYPE_CHECKING, Any, TypedDict if TYPE_CHECKING: + import pathlib + from commitizen.question import CzQuestion diff --git a/commitizen/hooks.py b/commitizen/hooks.py index f60bd9b43e..10560d5eae 100644 --- a/commitizen/hooks.py +++ b/commitizen/hooks.py @@ -1,11 +1,14 @@ from __future__ import annotations import os -from collections.abc import Mapping +from typing import TYPE_CHECKING from commitizen import cmd, out from commitizen.exceptions import RunHookError +if TYPE_CHECKING: + from collections.abc import Mapping + def run(hooks: str | list[str], _env_prefix: str = "CZ_", **env: object) -> None: if isinstance(hooks, str): diff --git a/commitizen/providers/__init__.py b/commitizen/providers/__init__.py index 3e01fe22f8..4cef578ab9 100644 --- a/commitizen/providers/__init__.py +++ b/commitizen/providers/__init__.py @@ -1,16 +1,14 @@ from __future__ import annotations import sys -from typing import cast +from typing import TYPE_CHECKING, cast if sys.version_info >= (3, 10): from importlib import metadata else: import importlib_metadata as metadata -from commitizen.config.base_config import BaseConfig from commitizen.exceptions import VersionProviderUnknown -from commitizen.providers.base_provider import VersionProvider from commitizen.providers.cargo_provider import CargoProvider from commitizen.providers.commitizen_provider import CommitizenProvider from commitizen.providers.composer_provider import ComposerProvider @@ -20,6 +18,10 @@ from commitizen.providers.scm_provider import ScmProvider from commitizen.providers.uv_provider import UvProvider +if TYPE_CHECKING: + from commitizen.config.base_config import BaseConfig + from commitizen.providers.base_provider import VersionProvider + __all__ = [ "CargoProvider", "CommitizenProvider", @@ -48,4 +50,4 @@ def get_provider(config: BaseConfig) -> VersionProvider: except ValueError: raise VersionProviderUnknown(f'Version Provider "{provider_name}" unknown.') provider_cls = ep.load() - return cast(VersionProvider, provider_cls(config)) + return cast("VersionProvider", provider_cls(config)) diff --git a/commitizen/providers/base_provider.py b/commitizen/providers/base_provider.py index c91bfdae20..84b745e326 100644 --- a/commitizen/providers/base_provider.py +++ b/commitizen/providers/base_provider.py @@ -2,13 +2,15 @@ import json from abc import ABC, abstractmethod -from collections.abc import Mapping from pathlib import Path -from typing import Any, ClassVar +from typing import TYPE_CHECKING, Any, ClassVar import tomlkit -from commitizen.config.base_config import BaseConfig +if TYPE_CHECKING: + from collections.abc import Mapping + + from commitizen.config.base_config import BaseConfig class VersionProvider(ABC): diff --git a/commitizen/providers/cargo_provider.py b/commitizen/providers/cargo_provider.py index 02fdd2cc6d..ca00f05e7b 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -7,10 +7,12 @@ from tomlkit import TOMLDocument, dumps, parse from tomlkit.exceptions import NonExistentKey -from tomlkit.items import AoT from commitizen.providers.base_provider import TomlProvider +if TYPE_CHECKING: + from tomlkit.items import AoT + class CargoProvider(TomlProvider): """ diff --git a/commitizen/providers/npm_provider.py b/commitizen/providers/npm_provider.py index 3125447250..7aeb0ee7df 100644 --- a/commitizen/providers/npm_provider.py +++ b/commitizen/providers/npm_provider.py @@ -1,12 +1,14 @@ from __future__ import annotations import json -from collections.abc import Mapping from pathlib import Path -from typing import Any, ClassVar +from typing import TYPE_CHECKING, Any, ClassVar from commitizen.providers.base_provider import VersionProvider +if TYPE_CHECKING: + from collections.abc import Mapping + class NpmProvider(VersionProvider): """ diff --git a/commitizen/providers/poetry_provider.py b/commitizen/providers/poetry_provider.py index f63b13b793..d9a174a0a4 100644 --- a/commitizen/providers/poetry_provider.py +++ b/commitizen/providers/poetry_provider.py @@ -1,9 +1,12 @@ from __future__ import annotations -import tomlkit +from typing import TYPE_CHECKING from commitizen.providers.base_provider import TomlProvider +if TYPE_CHECKING: + import tomlkit + class PoetryProvider(TomlProvider): """ diff --git a/commitizen/providers/uv_provider.py b/commitizen/providers/uv_provider.py index 21e8322d94..4574dc4b6b 100644 --- a/commitizen/providers/uv_provider.py +++ b/commitizen/providers/uv_provider.py @@ -1,15 +1,12 @@ from __future__ import annotations from pathlib import Path -from typing import TYPE_CHECKING import tomlkit +import tomlkit.items from commitizen.providers.base_provider import TomlProvider -if TYPE_CHECKING: - import tomlkit.items - class UvProvider(TomlProvider): """ diff --git a/commitizen/tags.py b/commitizen/tags.py index e3f54370f1..68c74a72e6 100644 --- a/commitizen/tags.py +++ b/commitizen/tags.py @@ -2,7 +2,6 @@ import re import warnings -from collections.abc import Iterable, Sequence from dataclasses import dataclass, field from functools import cached_property from itertools import chain @@ -22,6 +21,7 @@ if TYPE_CHECKING: import sys + from collections.abc import Iterable, Sequence from commitizen.version_schemes import VersionScheme diff --git a/commitizen/version_schemes.py b/commitizen/version_schemes.py index 0696d85aa5..0c71bb06cc 100644 --- a/commitizen/version_schemes.py +++ b/commitizen/version_schemes.py @@ -277,7 +277,7 @@ def bump( current_base = ".".join(str(part) for part in release) pre_version = ( - self if base == current_base else cast(BaseVersion, self.scheme(base)) + self if base == current_base else cast("BaseVersion", self.scheme(base)) ).generate_prerelease(prerelease, offset=prerelease_offset) # TODO: post version @@ -433,7 +433,7 @@ def get_version_scheme(settings: Settings, name: str | None = None) -> VersionSc (ep,) = metadata.entry_points(name=name, group=SCHEMES_ENTRYPOINT) except ValueError: raise VersionSchemeUnknown(f'Version scheme "{name}" unknown.') - scheme = cast(VersionScheme, ep.load()) + scheme = cast("VersionScheme", ep.load()) if not isinstance(scheme, VersionProtocol): warnings.warn(f"Version scheme {name} does not implement the VersionProtocol") diff --git a/pyproject.toml b/pyproject.toml index 097aed9c1e..7ea99cc69f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -208,6 +208,13 @@ select = [ "RUF100", # Checks for uses of the assert keyword. "S101", + # flake8-type-checking (TC) + "TC001", + "TC002", + "TC003", + "TC004", + "TC005", + "TC006", ] ignore = ["E501", "D1", "D415"] diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index 8871a6bf0f..8dbe8f447e 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -5,17 +5,14 @@ import sys from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING from unittest.mock import MagicMock, call -import py import pytest -from pytest_mock import MockFixture import commitizen.commands.bump as bump from commitizen import cli, cmd, defaults, git, hooks -from commitizen.changelog_formats import ChangelogFormat from commitizen.config.base_config import BaseConfig -from commitizen.cz.base import BaseCommitizen from commitizen.exceptions import ( BumpTagFailedError, CommitizenException, @@ -33,6 +30,13 @@ ) from tests.utils import create_file_and_commit, create_tag, skip_below_py_3_13 +if TYPE_CHECKING: + import py + from pytest_mock import MockFixture + + from commitizen.changelog_formats import ChangelogFormat + from commitizen.cz.base import BaseCommitizen + @pytest.mark.parametrize( "commit_msg", diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index d2a82a903a..e7918ca238 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -2,9 +2,9 @@ import sys from io import StringIO +from typing import TYPE_CHECKING import pytest -from pytest_mock import MockFixture from commitizen import cli, commands, git from commitizen.exceptions import ( @@ -15,6 +15,9 @@ ) from tests.utils import create_file_and_commit, skip_below_py_3_13 +if TYPE_CHECKING: + from pytest_mock import MockFixture + COMMIT_LOG = [ "refactor: A code change that neither fixes a bug nor adds a feature", r"refactor(cz/connventional_commit): use \S to check scope", diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index cfecfebeb1..54fa271fd9 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -4,18 +4,21 @@ import os import sys from pathlib import Path -from typing import Any +from typing import TYPE_CHECKING, Any import pytest import yaml -from pytest_mock import MockFixture from commitizen import cli, cmd, commands from commitizen.__version__ import __version__ -from commitizen.config.base_config import BaseConfig from commitizen.exceptions import InitFailedError, NoAnswersError from tests.utils import skip_below_py_3_10 +if TYPE_CHECKING: + from pytest_mock import MockFixture + + from commitizen.config.base_config import BaseConfig + class FakeQuestion: def __init__(self, expected_return): diff --git a/tests/conftest.py b/tests/conftest.py index 95e4a33c65..5eaa17440a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,12 +3,9 @@ import os import re import tempfile -from collections.abc import Iterator, Mapping -from pathlib import Path from typing import TYPE_CHECKING import pytest -from pytest_mock import MockerFixture from commitizen import cmd, defaults from commitizen.changelog_formats import ( @@ -20,6 +17,11 @@ from commitizen.cz.base import BaseCommitizen if TYPE_CHECKING: + from collections.abc import Iterator, Mapping + from pathlib import Path + + from pytest_mock import MockerFixture + from commitizen.question import CzQuestion from tests.utils import create_file_and_commit diff --git a/tests/providers/conftest.py b/tests/providers/conftest.py index f73cdb72a5..41b7bd02f1 100644 --- a/tests/providers/conftest.py +++ b/tests/providers/conftest.py @@ -1,11 +1,14 @@ from __future__ import annotations import os -from collections.abc import Iterator from pathlib import Path +from typing import TYPE_CHECKING import pytest +if TYPE_CHECKING: + from collections.abc import Iterator + @pytest.fixture def chdir(tmp_path: Path) -> Iterator[Path]: diff --git a/tests/providers/test_base_provider.py b/tests/providers/test_base_provider.py index 482bd698ea..782a8ba89e 100644 --- a/tests/providers/test_base_provider.py +++ b/tests/providers/test_base_provider.py @@ -1,12 +1,16 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pytest -from commitizen.config.base_config import BaseConfig from commitizen.exceptions import VersionProviderUnknown from commitizen.providers import get_provider from commitizen.providers.commitizen_provider import CommitizenProvider +if TYPE_CHECKING: + from commitizen.config.base_config import BaseConfig + def test_default_version_provider_is_commitizen_config(config: BaseConfig): provider = get_provider(config) diff --git a/tests/providers/test_cargo_provider.py b/tests/providers/test_cargo_provider.py index b7dc932d38..ea15fdbf39 100644 --- a/tests/providers/test_cargo_provider.py +++ b/tests/providers/test_cargo_provider.py @@ -3,13 +3,16 @@ import os from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING import pytest -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.cargo_provider import CargoProvider +if TYPE_CHECKING: + from commitizen.config.base_config import BaseConfig + CARGO_TOML = """\ [package] name = "whatever" diff --git a/tests/providers/test_commitizen_provider.py b/tests/providers/test_commitizen_provider.py index b8df60da93..c28dc90f79 100644 --- a/tests/providers/test_commitizen_provider.py +++ b/tests/providers/test_commitizen_provider.py @@ -2,12 +2,13 @@ from typing import TYPE_CHECKING -from commitizen.config.base_config import BaseConfig from commitizen.providers.commitizen_provider import CommitizenProvider if TYPE_CHECKING: from pytest_mock import MockerFixture + from commitizen.config.base_config import BaseConfig + def test_commitizen_provider(config: BaseConfig, mocker: MockerFixture): config.settings["version"] = "42" diff --git a/tests/providers/test_composer_provider.py b/tests/providers/test_composer_provider.py index 45cbc8afa4..22357b7a7f 100644 --- a/tests/providers/test_composer_provider.py +++ b/tests/providers/test_composer_provider.py @@ -1,14 +1,18 @@ from __future__ import annotations -from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING import pytest -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.composer_provider import ComposerProvider +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig + COMPOSER_JSON = """\ { "name": "whatever", diff --git a/tests/providers/test_npm_provider.py b/tests/providers/test_npm_provider.py index bc9399916d..785a2cb7fd 100644 --- a/tests/providers/test_npm_provider.py +++ b/tests/providers/test_npm_provider.py @@ -1,14 +1,18 @@ from __future__ import annotations -from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING import pytest -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.npm_provider import NpmProvider +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig + NPM_PACKAGE_JSON = """\ { "name": "whatever", diff --git a/tests/providers/test_pep621_provider.py b/tests/providers/test_pep621_provider.py index 16bb479cc4..f44cef38c8 100644 --- a/tests/providers/test_pep621_provider.py +++ b/tests/providers/test_pep621_provider.py @@ -1,14 +1,18 @@ from __future__ import annotations -from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING import pytest -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.pep621_provider import Pep621Provider +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig + PEP621_TOML = """\ [project] version = "0.1.0" diff --git a/tests/providers/test_poetry_provider.py b/tests/providers/test_poetry_provider.py index e26e2a44fb..ad998d41c7 100644 --- a/tests/providers/test_poetry_provider.py +++ b/tests/providers/test_poetry_provider.py @@ -1,14 +1,18 @@ from __future__ import annotations -from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING import pytest -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.poetry_provider import PoetryProvider +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig + POETRY_TOML = """\ [tool.poetry] version = "0.1.0" diff --git a/tests/providers/test_scm_provider.py b/tests/providers/test_scm_provider.py index 9d955b2323..e28a6782ab 100644 --- a/tests/providers/test_scm_provider.py +++ b/tests/providers/test_scm_provider.py @@ -1,8 +1,9 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pytest -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.scm_provider import ScmProvider from tests.utils import ( @@ -13,6 +14,9 @@ switch_branch, ) +if TYPE_CHECKING: + from commitizen.config.base_config import BaseConfig + @pytest.mark.parametrize( "tag_format,tag,expected_version", diff --git a/tests/providers/test_uv_provider.py b/tests/providers/test_uv_provider.py index 4093709376..7cb0782dd6 100644 --- a/tests/providers/test_uv_provider.py +++ b/tests/providers/test_uv_provider.py @@ -2,13 +2,14 @@ from typing import TYPE_CHECKING -from commitizen.config.base_config import BaseConfig from commitizen.providers import get_provider from commitizen.providers.uv_provider import UvProvider if TYPE_CHECKING: from pytest_regressions.file_regression import FileRegressionFixture + from commitizen.config.base_config import BaseConfig + PYPROJECT_TOML = """ [project] diff --git a/tests/test_changelog.py b/tests/test_changelog.py index 4465fcccbc..e32a9bcf9e 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -4,14 +4,13 @@ import re from dataclasses import dataclass from pathlib import Path -from typing import Any +from typing import TYPE_CHECKING, Any from unittest.mock import Mock import pytest from jinja2 import FileSystemLoader from commitizen import changelog, git -from commitizen.changelog_formats import ChangelogFormat from commitizen.commands.changelog import Changelog from commitizen.config import BaseConfig from commitizen.cz.conventional_commits.conventional_commits import ( @@ -20,6 +19,9 @@ from commitizen.exceptions import InvalidConfigurationError from commitizen.version_schemes import Pep440 +if TYPE_CHECKING: + from commitizen.changelog_formats import ChangelogFormat + COMMITS_DATA: list[dict[str, Any]] = [ { "rev": "141ee441c9c9da0809c554103a558eb17c30ed17", diff --git a/tests/test_changelog_format_asciidoc.py b/tests/test_changelog_format_asciidoc.py index cc81a24f2a..199c4b9729 100644 --- a/tests/test_changelog_format_asciidoc.py +++ b/tests/test_changelog_format_asciidoc.py @@ -1,12 +1,16 @@ from __future__ import annotations -from pathlib import Path +from typing import TYPE_CHECKING import pytest from commitizen.changelog import Metadata from commitizen.changelog_formats.asciidoc import AsciiDoc -from commitizen.config.base_config import BaseConfig + +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig CHANGELOG_A = """ = Changelog diff --git a/tests/test_changelog_format_markdown.py b/tests/test_changelog_format_markdown.py index 1abc63f29f..e09d68cfed 100644 --- a/tests/test_changelog_format_markdown.py +++ b/tests/test_changelog_format_markdown.py @@ -1,12 +1,16 @@ from __future__ import annotations -from pathlib import Path +from typing import TYPE_CHECKING import pytest from commitizen.changelog import Metadata from commitizen.changelog_formats.markdown import Markdown -from commitizen.config.base_config import BaseConfig + +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig CHANGELOG_A = """ # Changelog diff --git a/tests/test_changelog_format_restructuredtext.py b/tests/test_changelog_format_restructuredtext.py index ca79620ad3..e6eceff4fa 100644 --- a/tests/test_changelog_format_restructuredtext.py +++ b/tests/test_changelog_format_restructuredtext.py @@ -1,6 +1,5 @@ from __future__ import annotations -from pathlib import Path from textwrap import dedent from typing import TYPE_CHECKING @@ -12,11 +11,14 @@ _is_overlined_title, _is_underlined_title, ) -from commitizen.config.base_config import BaseConfig if TYPE_CHECKING: + from pathlib import Path + from _pytest.mark.structures import ParameterSet + from commitizen.config.base_config import BaseConfig + CASES: list[ParameterSet] = [] diff --git a/tests/test_changelog_format_textile.py b/tests/test_changelog_format_textile.py index 812fa6bf60..752cf229e5 100644 --- a/tests/test_changelog_format_textile.py +++ b/tests/test_changelog_format_textile.py @@ -1,12 +1,16 @@ from __future__ import annotations -from pathlib import Path +from typing import TYPE_CHECKING import pytest from commitizen.changelog import Metadata from commitizen.changelog_formats.textile import Textile -from commitizen.config.base_config import BaseConfig + +if TYPE_CHECKING: + from pathlib import Path + + from commitizen.config.base_config import BaseConfig CHANGELOG_A = """ h1. Changelog diff --git a/tests/test_changelog_formats.py b/tests/test_changelog_formats.py index e0d99e0325..ff7126d345 100644 --- a/tests/test_changelog_formats.py +++ b/tests/test_changelog_formats.py @@ -1,5 +1,7 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pytest from commitizen import defaults @@ -9,9 +11,11 @@ _guess_changelog_format, get_changelog_format, ) -from commitizen.config.base_config import BaseConfig from commitizen.exceptions import ChangelogFormatUnknown +if TYPE_CHECKING: + from commitizen.config.base_config import BaseConfig + @pytest.mark.parametrize("format", KNOWN_CHANGELOG_FORMATS.values()) def test_guess_format(format: type[ChangelogFormat]): diff --git a/tests/test_git.py b/tests/test_git.py index f433ed633a..45e6028c9e 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -4,9 +4,9 @@ import os import platform import shutil +from typing import TYPE_CHECKING import pytest -from pytest_mock import MockFixture from commitizen import cmd, git from commitizen.exceptions import GitCommandError @@ -18,6 +18,9 @@ switch_branch, ) +if TYPE_CHECKING: + from pytest_mock import MockFixture + @pytest.mark.parametrize("date", ["2020-01-21", "1970-01-01"]) def test_git_tag_date(date: str): diff --git a/tests/test_version_schemes.py b/tests/test_version_schemes.py index 8e2dae9027..afaae76188 100644 --- a/tests/test_version_schemes.py +++ b/tests/test_version_schemes.py @@ -7,13 +7,18 @@ else: import importlib_metadata as metadata +from typing import TYPE_CHECKING + import pytest -from pytest_mock import MockerFixture -from commitizen.config.base_config import BaseConfig from commitizen.exceptions import VersionSchemeUnknown from commitizen.version_schemes import Pep440, SemVer, get_version_scheme +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + from commitizen.config.base_config import BaseConfig + def test_default_version_scheme_is_pep440(config: BaseConfig): scheme = get_version_scheme(config.settings) diff --git a/tests/utils.py b/tests/utils.py index 43e0cf79a0..bea7f20a1d 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -4,13 +4,15 @@ import time import uuid from pathlib import Path -from typing import NamedTuple +from typing import TYPE_CHECKING, NamedTuple import pytest from deprecated import deprecated from commitizen import cmd, exceptions, git -from commitizen.version_schemes import Increment, Prerelease + +if TYPE_CHECKING: + from commitizen.version_schemes import Increment, Prerelease skip_below_py_3_10 = pytest.mark.skipif( sys.version_info < (3, 10), From 609011ce85a4d66ab3f54a84fd0db2b1551ea5a0 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 22 Nov 2025 16:35:16 +0800 Subject: [PATCH 120/221] fix(version): fix the behavior of cz version --major --- commitizen/cli.py | 4 +- commitizen/commands/version.py | 47 ++++++++----- tests/commands/test_version_command.py | 69 ++++++++++++------- ...shows_description_when_use_help_option.txt | 6 +- 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index f4f92cb0a4..e5538aeb49 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -543,13 +543,13 @@ def __call__( }, { "name": ["--major"], - "help": "get just the major version", + "help": "get just the major version. Need to be used with --project or --verbose.", "action": "store_true", "exclusive_group": "group2", }, { "name": ["--minor"], - "help": "get just the minor version", + "help": "get just the minor version. Need to be used with --project or --verbose.", "action": "store_true", "exclusive_group": "group2", }, diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 7ccadb5135..338fce0760 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -11,6 +11,7 @@ class VersionArgs(TypedDict, total=False): + commitizen: bool report: bool project: bool verbose: bool @@ -19,46 +20,58 @@ class VersionArgs(TypedDict, total=False): class Version: - """Get the version of the installed commitizen or the current project.""" + """Get the version of the installed commitizen or the current project. + Precedence: + 1. report + 2. commitizen + 3. verbose, project + """ def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None: self.config: BaseConfig = config self.parameter = arguments - self.operating_system = platform.system() - self.python_version = sys.version def __call__(self) -> None: if self.parameter.get("report"): out.write(f"Commitizen Version: {__version__}") - out.write(f"Python Version: {self.python_version}") - out.write(f"Operating System: {self.operating_system}") + out.write(f"Python Version: {sys.version}") + out.write(f"Operating System: {platform.system()}") return - if (verbose := self.parameter.get("verbose")) or self.parameter.get("project"): - if verbose: - out.write(f"Installed Commitizen Version: {__version__}") + if self.parameter.get("verbose"): + out.write(f"Installed Commitizen Version: {__version__}") + if not self.parameter.get("commitizen") and ( + self.parameter.get("project") or self.parameter.get("verbose") + ): try: version = get_provider(self.config).get_version() except NoVersionSpecifiedError: out.error("No project information in this project.") return - try: - version_scheme = get_version_scheme(self.config.settings) + version_scheme = get_version_scheme(self.config.settings)(version) except VersionSchemeUnknown: out.error("Unknown version scheme.") return - _version = version_scheme(version) - if self.parameter.get("major"): - version = f"{_version.major}" + version = f"{version_scheme.major}" elif self.parameter.get("minor"): - version = f"{_version.minor}" + version = f"{version_scheme.minor}" + + out.write( + f"Project Version: {version}" + if self.parameter.get("verbose") + else version + ) + return - out.write(f"Project Version: {version}" if verbose else version) + if self.parameter.get("major") or self.parameter.get("minor"): + out.error( + "Major or minor version can only be used with --project or --verbose." + ) return - # if no argument is given, show installed commitizen version - out.write(f"{__version__}") + # If no arguments are provided, just show the installed commitizen version + out.write(__version__) diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 7b5b13a7e1..a5faf4e16d 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -11,54 +11,51 @@ from tests.utils import skip_below_py_3_10 -def test_version_for_showing_project_version(config, capsys): - # No version exist +def test_version_for_showing_project_version_error(config, capsys): + # No version specified in config commands.Version( config, - {"report": False, "project": True, "commitizen": False, "verbose": False}, + {"project": True}, )() captured = capsys.readouterr() assert "No project information in this project." in captured.err + +def test_version_for_showing_project_version(config, capsys): config.settings["version"] = "v0.0.1" commands.Version( config, - {"report": False, "project": True, "commitizen": False, "verbose": False}, + {"project": True}, )() captured = capsys.readouterr() assert "v0.0.1" in captured.out -def test_version_for_showing_commitizen_version(config, capsys): - commands.Version( - config, - {"report": False, "project": False, "commitizen": True, "verbose": False}, - )() - captured = capsys.readouterr() - assert f"{__version__}" in captured.out - - # default showing commitizen version +@pytest.mark.parametrize("project", (True, False)) +def test_version_for_showing_commitizen_version(config, capsys, project: bool): commands.Version( config, - {"report": False, "project": False, "commitizen": False, "verbose": False}, + {"project": project, "commitizen": True}, )() captured = capsys.readouterr() assert f"{__version__}" in captured.out -def test_version_for_showing_both_versions(config, capsys): +def test_version_for_showing_both_versions_no_project(config, capsys): commands.Version( config, - {"report": False, "project": False, "commitizen": False, "verbose": True}, + {"verbose": True}, )() captured = capsys.readouterr() assert f"Installed Commitizen Version: {__version__}" in captured.out assert "No project information in this project." in captured.err + +def test_version_for_showing_both_versions(config, capsys): config.settings["version"] = "v0.0.1" commands.Version( config, - {"report": False, "project": False, "commitizen": False, "verbose": True}, + {"verbose": True}, )() captured = capsys.readouterr() expected_out = ( @@ -70,7 +67,7 @@ def test_version_for_showing_both_versions(config, capsys): def test_version_for_showing_commitizen_system_info(config, capsys): commands.Version( config, - {"report": True, "project": False, "commitizen": False, "verbose": False}, + {"report": True}, )() captured = capsys.readouterr() assert f"Commitizen Version: {__version__}" in captured.out @@ -96,7 +93,6 @@ def test_version_use_version_provider( commands.Version( config, { - "report": False, "project": project, "verbose": not project, }, @@ -135,16 +131,20 @@ def test_version_command_shows_description_when_use_help_option( @pytest.mark.parametrize( - "version, expected_version", (("1.0.0", "1\n"), ("2.1.3", "2\n"), ("0.0.1", "0\n")) + "version, expected_version", + [ + ("1.0.0", "1\n"), + ("2.1.3", "2\n"), + ("0.0.1", "0\n"), + ("0.1.0", "0\n"), + ], ) def test_version_just_major(config, capsys, version: str, expected_version: str): config.settings["version"] = version commands.Version( config, { - "report": False, "project": True, - "verbose": False, "major": True, }, )() @@ -154,18 +154,37 @@ def test_version_just_major(config, capsys, version: str, expected_version: str) @pytest.mark.parametrize( "version, expected_version", - (("1.0.0", "0\n"), ("2.1.3", "1\n"), ("0.0.1", "0\n"), ("0.1.0", "1\n")), + [ + ("1.0.0", "0\n"), + ("2.1.3", "1\n"), + ("0.0.1", "0\n"), + ("0.1.0", "1\n"), + ], ) def test_version_just_minor(config, capsys, version: str, expected_version: str): config.settings["version"] = version commands.Version( config, { - "report": False, "project": True, - "verbose": False, "minor": True, }, )() captured = capsys.readouterr() assert expected_version == captured.out + + +@pytest.mark.parametrize("argument", ("major", "minor")) +def test_version_just_major_error_no_project(config, capsys, argument: str): + commands.Version( + config, + { + argument: True, # type: ignore[misc] + }, + )() + captured = capsys.readouterr() + assert not captured.out + assert ( + "Major or minor version can only be used with --project or --verbose." + in captured.err + ) diff --git a/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt b/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt index b1ed94124e..a194615a98 100644 --- a/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt +++ b/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt @@ -10,5 +10,7 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project - --major get just the major version - --minor get just the minor version + --major get just the major version. Need to be used with --project + or --verbose. + --minor get just the minor version. Need to be used with --project + or --verbose. From 5b471c3e51e35382ef9911923b671b7cb5a7b45f Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Thu, 27 Nov 2025 23:26:34 +0800 Subject: [PATCH 121/221] refactor(version): rename class member to align with other classes --- commitizen/commands/version.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 338fce0760..9290e80b8f 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -29,20 +29,20 @@ class Version: def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None: self.config: BaseConfig = config - self.parameter = arguments + self.arguments = arguments def __call__(self) -> None: - if self.parameter.get("report"): + if self.arguments.get("report"): out.write(f"Commitizen Version: {__version__}") out.write(f"Python Version: {sys.version}") out.write(f"Operating System: {platform.system()}") return - if self.parameter.get("verbose"): + if self.arguments.get("verbose"): out.write(f"Installed Commitizen Version: {__version__}") - if not self.parameter.get("commitizen") and ( - self.parameter.get("project") or self.parameter.get("verbose") + if not self.arguments.get("commitizen") and ( + self.arguments.get("project") or self.arguments.get("verbose") ): try: version = get_provider(self.config).get_version() @@ -55,19 +55,19 @@ def __call__(self) -> None: out.error("Unknown version scheme.") return - if self.parameter.get("major"): + if self.arguments.get("major"): version = f"{version_scheme.major}" - elif self.parameter.get("minor"): + elif self.arguments.get("minor"): version = f"{version_scheme.minor}" out.write( f"Project Version: {version}" - if self.parameter.get("verbose") + if self.arguments.get("verbose") else version ) return - if self.parameter.get("major") or self.parameter.get("minor"): + if self.arguments.get("major") or self.arguments.get("minor"): out.error( "Major or minor version can only be used with --project or --verbose." ) From 9473ef3c83bb90f9e398462b84aa70913192d668 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 15:24:38 +0000 Subject: [PATCH 122/221] docs(cli/screenshots): update CLI screenshots [skip ci] --- docs/images/cli_help/cz_version___help.svg | 90 ++++++++++++---------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/docs/images/cli_help/cz_version___help.svg b/docs/images/cli_help/cz_version___help.svg index 7ddec177d8..a8e0bd844e 100644 --- a/docs/images/cli_help/cz_version___help.svg +++ b/docs/images/cli_help/cz_version___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 440.4" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 489.2" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,100 +19,108 @@ font-weight: 700; } - .terminal-2062799951-matrix { + .terminal-752487608-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2062799951-title { + .terminal-752487608-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2062799951-r1 { fill: #c5c8c6 } -.terminal-2062799951-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-752487608-r1 { fill: #c5c8c6 } +.terminal-752487608-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-2062799951-clip-terminal"> - <rect x="0" y="0" width="975.0" height="389.4" /> + <clipPath id="terminal-752487608-clip-terminal"> + <rect x="0" y="0" width="975.0" height="438.2" /> </clipPath> - <clipPath id="terminal-2062799951-line-0"> + <clipPath id="terminal-752487608-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-1"> +<clipPath id="terminal-752487608-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-2"> +<clipPath id="terminal-752487608-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-3"> +<clipPath id="terminal-752487608-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-4"> +<clipPath id="terminal-752487608-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-5"> +<clipPath id="terminal-752487608-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-6"> +<clipPath id="terminal-752487608-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-7"> +<clipPath id="terminal-752487608-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-8"> +<clipPath id="terminal-752487608-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-9"> +<clipPath id="terminal-752487608-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-10"> +<clipPath id="terminal-752487608-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-11"> +<clipPath id="terminal-752487608-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-12"> +<clipPath id="terminal-752487608-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-13"> +<clipPath id="terminal-752487608-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2062799951-line-14"> +<clipPath id="terminal-752487608-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-752487608-line-15"> + <rect x="0" y="367.5" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-752487608-line-16"> + <rect x="0" y="391.9" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="438.4" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="487.2" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-2062799951-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-752487608-clip-terminal)"> - <g class="terminal-2062799951-matrix"> - <text class="terminal-2062799951-r1" x="0" y="20" textLength="231.8" clip-path="url(#terminal-2062799951-line-0)">$ cz version --help</text><text class="terminal-2062799951-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-2062799951-line-0)"> -</text><text class="terminal-2062799951-r1" x="0" y="44.4" textLength="219.6" clip-path="url(#terminal-2062799951-line-1)">usage: cz version </text><text class="terminal-2062799951-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)">[</text><text class="terminal-2062799951-r1" x="231.8" y="44.4" textLength="24.4" clip-path="url(#terminal-2062799951-line-1)">-h</text><text class="terminal-2062799951-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)">]</text><text class="terminal-2062799951-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)">[</text><text class="terminal-2062799951-r1" x="292.8" y="44.4" textLength="207.4" clip-path="url(#terminal-2062799951-line-1)">-r | -p | -c | -v</text><text class="terminal-2062799951-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)">]</text><text class="terminal-2062799951-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)">[</text><text class="terminal-2062799951-r1" x="536.8" y="44.4" textLength="207.4" clip-path="url(#terminal-2062799951-line-1)">--major | --minor</text><text class="terminal-2062799951-r2" x="744.2" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)">]</text><text class="terminal-2062799951-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-1)"> -</text><text class="terminal-2062799951-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-2062799951-line-2)"> -</text><text class="terminal-2062799951-r1" x="0" y="93.2" textLength="817.4" clip-path="url(#terminal-2062799951-line-3)">get the version of the installed commitizen or the current project </text><text class="terminal-2062799951-r2" x="817.4" y="93.2" textLength="12.2" clip-path="url(#terminal-2062799951-line-3)">(</text><text class="terminal-2062799951-r1" x="829.6" y="93.2" textLength="97.6" clip-path="url(#terminal-2062799951-line-3)">default:</text><text class="terminal-2062799951-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-2062799951-line-3)"> -</text><text class="terminal-2062799951-r1" x="0" y="117.6" textLength="244" clip-path="url(#terminal-2062799951-line-4)">installed commitizen</text><text class="terminal-2062799951-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-2062799951-line-4)">)</text><text class="terminal-2062799951-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-2062799951-line-4)"> -</text><text class="terminal-2062799951-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-2062799951-line-5)"> -</text><text class="terminal-2062799951-r1" x="0" y="166.4" textLength="97.6" clip-path="url(#terminal-2062799951-line-6)">options:</text><text class="terminal-2062799951-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-6)"> -</text><text class="terminal-2062799951-r1" x="0" y="190.8" textLength="622.2" clip-path="url(#terminal-2062799951-line-7)">  -h, --help        show this help message and exit</text><text class="terminal-2062799951-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-2062799951-line-7)"> -</text><text class="terminal-2062799951-r1" x="0" y="215.2" textLength="744.2" clip-path="url(#terminal-2062799951-line-8)">  -r, --report      get system information for reporting bugs</text><text class="terminal-2062799951-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-2062799951-line-8)"> -</text><text class="terminal-2062799951-r1" x="0" y="239.6" textLength="707.6" clip-path="url(#terminal-2062799951-line-9)">  -p, --project     get the version of the current project</text><text class="terminal-2062799951-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-2062799951-line-9)"> -</text><text class="terminal-2062799951-r1" x="0" y="264" textLength="768.6" clip-path="url(#terminal-2062799951-line-10)">  -c, --commitizen  get the version of the installed commitizen</text><text class="terminal-2062799951-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-2062799951-line-10)"> -</text><text class="terminal-2062799951-r1" x="0" y="288.4" textLength="927.2" clip-path="url(#terminal-2062799951-line-11)">  -v, --verbose     get the version of both the installed commitizen and the</text><text class="terminal-2062799951-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-2062799951-line-11)"> -</text><text class="terminal-2062799951-r1" x="0" y="312.8" textLength="427" clip-path="url(#terminal-2062799951-line-12)">                    current project</text><text class="terminal-2062799951-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-2062799951-line-12)"> -</text><text class="terminal-2062799951-r1" x="0" y="337.2" textLength="561.2" clip-path="url(#terminal-2062799951-line-13)">  --major           get just the major version</text><text class="terminal-2062799951-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-2062799951-line-13)"> -</text><text class="terminal-2062799951-r1" x="0" y="361.6" textLength="561.2" clip-path="url(#terminal-2062799951-line-14)">  --minor           get just the minor version</text><text class="terminal-2062799951-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-2062799951-line-14)"> -</text><text class="terminal-2062799951-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-2062799951-line-15)"> + <g class="terminal-752487608-matrix"> + <text class="terminal-752487608-r1" x="0" y="20" textLength="231.8" clip-path="url(#terminal-752487608-line-0)">$ cz version --help</text><text class="terminal-752487608-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-752487608-line-0)"> +</text><text class="terminal-752487608-r1" x="0" y="44.4" textLength="219.6" clip-path="url(#terminal-752487608-line-1)">usage: cz version </text><text class="terminal-752487608-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">[</text><text class="terminal-752487608-r1" x="231.8" y="44.4" textLength="24.4" clip-path="url(#terminal-752487608-line-1)">-h</text><text class="terminal-752487608-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">]</text><text class="terminal-752487608-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">[</text><text class="terminal-752487608-r1" x="292.8" y="44.4" textLength="207.4" clip-path="url(#terminal-752487608-line-1)">-r | -p | -c | -v</text><text class="terminal-752487608-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">]</text><text class="terminal-752487608-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">[</text><text class="terminal-752487608-r1" x="536.8" y="44.4" textLength="207.4" clip-path="url(#terminal-752487608-line-1)">--major | --minor</text><text class="terminal-752487608-r2" x="744.2" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">]</text><text class="terminal-752487608-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)"> +</text><text class="terminal-752487608-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-752487608-line-2)"> +</text><text class="terminal-752487608-r1" x="0" y="93.2" textLength="817.4" clip-path="url(#terminal-752487608-line-3)">get the version of the installed commitizen or the current project </text><text class="terminal-752487608-r2" x="817.4" y="93.2" textLength="12.2" clip-path="url(#terminal-752487608-line-3)">(</text><text class="terminal-752487608-r1" x="829.6" y="93.2" textLength="97.6" clip-path="url(#terminal-752487608-line-3)">default:</text><text class="terminal-752487608-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-752487608-line-3)"> +</text><text class="terminal-752487608-r1" x="0" y="117.6" textLength="244" clip-path="url(#terminal-752487608-line-4)">installed commitizen</text><text class="terminal-752487608-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-752487608-line-4)">)</text><text class="terminal-752487608-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-752487608-line-4)"> +</text><text class="terminal-752487608-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-752487608-line-5)"> +</text><text class="terminal-752487608-r1" x="0" y="166.4" textLength="97.6" clip-path="url(#terminal-752487608-line-6)">options:</text><text class="terminal-752487608-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-752487608-line-6)"> +</text><text class="terminal-752487608-r1" x="0" y="190.8" textLength="622.2" clip-path="url(#terminal-752487608-line-7)">  -h, --help        show this help message and exit</text><text class="terminal-752487608-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-752487608-line-7)"> +</text><text class="terminal-752487608-r1" x="0" y="215.2" textLength="744.2" clip-path="url(#terminal-752487608-line-8)">  -r, --report      get system information for reporting bugs</text><text class="terminal-752487608-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-752487608-line-8)"> +</text><text class="terminal-752487608-r1" x="0" y="239.6" textLength="707.6" clip-path="url(#terminal-752487608-line-9)">  -p, --project     get the version of the current project</text><text class="terminal-752487608-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-752487608-line-9)"> +</text><text class="terminal-752487608-r1" x="0" y="264" textLength="768.6" clip-path="url(#terminal-752487608-line-10)">  -c, --commitizen  get the version of the installed commitizen</text><text class="terminal-752487608-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-752487608-line-10)"> +</text><text class="terminal-752487608-r1" x="0" y="288.4" textLength="927.2" clip-path="url(#terminal-752487608-line-11)">  -v, --verbose     get the version of both the installed commitizen and the</text><text class="terminal-752487608-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-752487608-line-11)"> +</text><text class="terminal-752487608-r1" x="0" y="312.8" textLength="427" clip-path="url(#terminal-752487608-line-12)">                    current project</text><text class="terminal-752487608-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-752487608-line-12)"> +</text><text class="terminal-752487608-r1" x="0" y="337.2" textLength="951.6" clip-path="url(#terminal-752487608-line-13)">  --major           get just the major version. Need to be used with --project</text><text class="terminal-752487608-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-752487608-line-13)"> +</text><text class="terminal-752487608-r1" x="0" y="361.6" textLength="402.6" clip-path="url(#terminal-752487608-line-14)">                    or --verbose.</text><text class="terminal-752487608-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-752487608-line-14)"> +</text><text class="terminal-752487608-r1" x="0" y="386" textLength="951.6" clip-path="url(#terminal-752487608-line-15)">  --minor           get just the minor version. Need to be used with --project</text><text class="terminal-752487608-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-752487608-line-15)"> +</text><text class="terminal-752487608-r1" x="0" y="410.4" textLength="402.6" clip-path="url(#terminal-752487608-line-16)">                    or --verbose.</text><text class="terminal-752487608-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-752487608-line-16)"> +</text><text class="terminal-752487608-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-752487608-line-17)"> </text> </g> </g> From c2ae121f848c77df906d2208cd17c2c311d01118 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 15:24:40 +0000 Subject: [PATCH 123/221] =?UTF-8?q?bump:=20version=204.10.0=20=E2=86=92=20?= =?UTF-8?q?4.10.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf207ea60b..f70fbf2f10 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.10.0 # automatically updated by Commitizen + rev: v4.10.1 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index f8bca478b3..7ee748085f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## v4.10.1 (2025-12-11) + +### Fix + +- **version**: fix the behavior of cz version --major +- **cli**: debug and no_raise can be used together in sys.excepthook +- **git**: replace lstrip with strip for compatibility issue +- **bump**: remove NotAllowed related to --get-next option, other related refactoring + +### Refactor + +- **version**: rename class member to align with other classes +- **cargo_provider**: cleanup and get rid of potential type errors +- **bump**: extract option validation and new version resolution to new functions +- **changelog**: raise NotAllow when file_name not passed instead of using assert +- **bump**: rename parameter and variables + +### Perf + +- **ruff**: enable ruff rules TC001~TC006 +- add TYPE_CHECKING to CzQuestion imports + ## v4.10.0 (2025-11-10) ### Feat diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 897e6be2ff..4e499ea83a 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.10.0" +__version__ = "4.10.1" diff --git a/pyproject.toml b/pyproject.toml index 7ea99cc69f..3e9c45ae63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.10.0" +version = "4.10.1" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -121,7 +121,7 @@ build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "4.10.0" +version = "4.10.1" tag_format = "v$version" version_files = [ "pyproject.toml:version", From 2b0b4d89e7d24efa211411ae733ddbfdbf64efa9 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Fri, 12 Dec 2025 00:31:15 +0800 Subject: [PATCH 124/221] docs: add missing site_url --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index ac1fbfa097..fe42da177b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,5 @@ site_name: Commitizen +site_url: https://commitizen-tools.github.io/commitizen/ site_description: commit rules, semantic version, conventional commits theme: From 30bb513b993cec111abf255f666ee190f4041530 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Fri, 12 Dec 2025 00:22:15 +0800 Subject: [PATCH 125/221] build: add missing dark mode back --- mkdocs.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index fe42da177b..656e8dd423 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,9 +3,8 @@ site_url: https://commitizen-tools.github.io/commitizen/ site_description: commit rules, semantic version, conventional commits theme: - name: "material" + name: material palette: - - primary: 'deep purple' # Palette toggle for automatic mode - media: "(prefers-color-scheme)" toggle: @@ -15,6 +14,7 @@ theme: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default + primary: deep purple toggle: icon: material/brightness-7 name: Switch to dark mode @@ -22,6 +22,7 @@ theme: # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate + primary: deep purple toggle: icon: material/brightness-4 name: Switch to system preference From 1e5869ec87c3886e1e2d313fd9d3d273db974b33 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Fri, 12 Dec 2025 00:42:12 +0800 Subject: [PATCH 126/221] style(mkdocs.yml): make indent consistent in nav section --- mkdocs.yml | 80 +++++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 656e8dd423..9666a203db 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -34,53 +34,53 @@ edit_uri: "" nav: - Introduction: "README.md" - Commands: - - init: "commands/init.md" - - commit: "commands/commit.md" - - bump: "commands/bump.md" - - check: "commands/check.md" - - changelog: "commands/changelog.md" - - example: "commands/example.md" - - info: "commands/info.md" - - ls: "commands/ls.md" - - schema: "commands/schema.md" - - version: "commands/version.md" + - init: "commands/init.md" + - commit: "commands/commit.md" + - bump: "commands/bump.md" + - check: "commands/check.md" + - changelog: "commands/changelog.md" + - example: "commands/example.md" + - info: "commands/info.md" + - ls: "commands/ls.md" + - schema: "commands/schema.md" + - version: "commands/version.md" - Configuration: - - Configuration File: "config/configuration_file.md" - - Version Provider: "config/version_provider.md" - - bump: "config/bump.md" - - commit: "config/commit.md" - - check: "config/check.md" - - changelog: "config/changelog.md" - - Misc Options: "config/option.md" + - Configuration File: "config/configuration_file.md" + - Version Provider: "config/version_provider.md" + - bump: "config/bump.md" + - commit: "config/commit.md" + - check: "config/check.md" + - changelog: "config/changelog.md" + - Misc Options: "config/option.md" - Advanced Customization: - - Configuration File: "customization/config_file.md" - - Customized Python Class: "customization/python_class.md" - - Changelog Template: "customization/changelog_template.md" + - Configuration File: "customization/config_file.md" + - Customized Python Class: "customization/python_class.md" + - Changelog Template: "customization/changelog_template.md" - Tutorials: - - Writing commits: "tutorials/writing_commits.md" - - Managing tags formats: "tutorials/tag_format.md" - - Auto check commits: "tutorials/auto_check.md" - - Auto prepare commit message: "tutorials/auto_prepare_commit_message.md" - - GitLab CI: "tutorials/gitlab_ci.md" - - GitHub Actions: "tutorials/github_actions.md" - - Jenkins pipeline: "tutorials/jenkins_pipeline.md" - - Developmental releases: "tutorials/dev_releases.md" - - Monorepo support: "tutorials/monorepo_guidance.md" + - Writing commits: "tutorials/writing_commits.md" + - Managing tags formats: "tutorials/tag_format.md" + - Auto check commits: "tutorials/auto_check.md" + - Auto prepare commit message: "tutorials/auto_prepare_commit_message.md" + - GitLab CI: "tutorials/gitlab_ci.md" + - GitHub Actions: "tutorials/github_actions.md" + - Jenkins pipeline: "tutorials/jenkins_pipeline.md" + - Developmental releases: "tutorials/dev_releases.md" + - Monorepo support: "tutorials/monorepo_guidance.md" - FAQ: "faq.md" - Features we won't add: "features_wont_add.md" - Exit Codes: "exit_codes.md" - Third-Party Commitizen Plugins: - - About: "third-party-plugins/about.md" - # Please sort the plugins alphabetically - - "third-party-plugins/commitizen-deno-provider.md" - - "third-party-plugins/commitizen-emoji.md" - - "third-party-plugins/conventional-jira.md" - - "third-party-plugins/cz-ai.md" - - "third-party-plugins/cz-conventional-gitmoji.md" - - "third-party-plugins/cz-emoji.md" - - "third-party-plugins/cz-legacy.md" - - "third-party-plugins/cz-path.md" - - "third-party-plugins/github-jira-conventional.md" + - About: "third-party-plugins/about.md" + # Please sort the plugins alphabetically + - "third-party-plugins/commitizen-deno-provider.md" + - "third-party-plugins/commitizen-emoji.md" + - "third-party-plugins/conventional-jira.md" + - "third-party-plugins/cz-ai.md" + - "third-party-plugins/cz-conventional-gitmoji.md" + - "third-party-plugins/cz-emoji.md" + - "third-party-plugins/cz-legacy.md" + - "third-party-plugins/cz-path.md" + - "third-party-plugins/github-jira-conventional.md" - Contributing: "contributing.md" - Contributing TL;DR: "contributing_tldr.md" - Resources: "external_links.md" From c0da2e6824ce30273bc84ddccf82681e137fa9c4 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Fri, 12 Dec 2025 12:00:38 +0800 Subject: [PATCH 127/221] docs: fix some format issues in docs --- docs/config/bump.md | 22 +++++++++++----------- docs/config/version_provider.md | 8 ++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/config/bump.md b/docs/config/bump.md index fa46e18f8d..10ca5bcf8d 100644 --- a/docs/config/bump.md +++ b/docs/config/bump.md @@ -185,11 +185,11 @@ version_files = [ ```json title="setup.json" { - "name": "magictool", - "version": "1.2.3", - "dependencies": { - "lodash": "1.2.3" - } + "name": "magictool", + "version": "1.2.3", + "dependencies": { + "lodash": "1.2.3" + } } ``` @@ -197,12 +197,12 @@ version_files = [ ```diff title="setup.json" { - "name": "magictool", - - "version": "1.2.3", - + "version": "2.0.0", - "dependencies": { - "lodash": "1.2.3" - } + "name": "magictool", + - "version": "1.2.3", + + "version": "2.0.0", + "dependencies": { + "lodash": "1.2.3" + } } ``` diff --git a/docs/config/version_provider.md b/docs/config/version_provider.md index 4f070b2fd3..859f84f781 100644 --- a/docs/config/version_provider.md +++ b/docs/config/version_provider.md @@ -19,6 +19,7 @@ Commitizen includes several built-in version providers for common package manage The default version provider stores and retrieves the version from your Commitizen configuration file (e.g., `pyproject.toml`, `.cz.toml`, etc.). **Use when:** + - You want to keep version management separate from your package manager - Your project doesn't use a standard package manager - You need maximum flexibility in version management @@ -35,6 +36,7 @@ version = "0.1.0" # Required when using this provider Fetches the version from Git tags using `git describe`. This provider **only reads** version information and never writes it back to files. It's designed to work with tools like `setuptools-scm` or other package manager `*-scm` plugins that derive version numbers from Git history. **Use when:** + - You're using `setuptools-scm` or similar tools - You want version numbers derived from Git tags - You don't want Commitizen to modify any files for version management @@ -54,6 +56,7 @@ version_provider = "scm" Manages version in `pyproject.toml` under the `project.version` field, following [PEP 621](https://peps.python.org/pep-0621/) standards. **Use when:** + - You're using a modern Python project with PEP 621-compliant `pyproject.toml` - You want version management integrated with your Python project metadata @@ -75,6 +78,7 @@ version = "0.1.0" # Managed by Commitizen Manages version in `pyproject.toml` under the `tool.poetry.version` field, which is used by the [Poetry](https://python-poetry.org/) package manager. This approach is recommended only for users running Poetry versions earlier than 2.0 or relying on Poetry-specific features. For most users on Poetry 2.0 or later, it is recommended to use `pep621` instead. [Read More](https://python-poetry.org/docs/main/managing-dependencies/) **Use when:** + - You're using Poetry < 2.0 as your Python package manager - You're using Poetry >= 2.0 as your Python package manager, but don't need poetry-specific features - You want Commitizen to manage the version that Poetry uses @@ -101,6 +105,7 @@ Manages version in both `pyproject.toml` (`project.version`) and `uv.lock` (`pac Even though uv follows PEP 621 format, `pep621` does not manage the version in `uv.lock`. `uv` is still suggested for uv users. **Use when:** + - You're using `uv` as your Python package manager - You want version synchronization between `pyproject.toml` and `uv.lock` @@ -115,6 +120,7 @@ version_provider = "uv" Manages version in both `Cargo.toml` (`package.version`) and `Cargo.lock` (`package.version` for the matching package name). This ensures consistency between your Rust project's manifest and lock file. **Use when:** + - You're working with a Rust project using Cargo - You want Commitizen to manage Rust package versions @@ -136,6 +142,7 @@ version = "0.1.0" # Managed by Commitizen Manages version in `package.json` and optionally synchronizes with `package-lock.json` and `npm-shrinkwrap.json` if they exist. **Use when:** + - You're working with a Node.js/JavaScript project - You want Commitizen to manage npm package versions @@ -158,6 +165,7 @@ version_provider = "npm" Manages version in `composer.json` under the `version` field, used by PHP's Composer package manager. **Use when:** + - You're working with a PHP project using Composer - You want Commitizen to manage Composer package versions From b64c6f675808590c98b8b127db886b7a7b6d0ae8 Mon Sep 17 00:00:00 2001 From: Parker <parkerhiphop027@gmail.com> Date: Sat, 13 Dec 2025 23:13:19 +0900 Subject: [PATCH 128/221] docs: fix broken links in doc --- docs/README.md | 6 +++--- docs/external_links.md | 2 +- docs/faq.md | 2 +- docs/tutorials/github_actions.md | 11 ++++++----- docs/tutorials/writing_commits.md | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/README.md b/docs/README.md index fa3fab2239..3b8fd7fb64 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,7 +45,7 @@ This standardization makes your commit history more readable and meaningful, whi - Intelligent [version bumping](https://commitizen-tools.github.io/commitizen/commands/bump/) using [Semantic Versioning][semver] - Automatic [keep a changelog][keepchangelog] generation - Built-in commit validation with pre-commit hooks -- [Customizable](https://commitizen-tools.github.io/commitizen/customization/) commit rules and templates +- [Customizable](https://commitizen-tools.github.io/commitizen/customization/config_file/) commit rules and templates - Multi-format version file support - Custom rules and plugins via pip @@ -174,7 +174,7 @@ You can customize: - [Version files](https://commitizen-tools.github.io/commitizen/commands/bump/#version_files) - [Version scheme](https://commitizen-tools.github.io/commitizen/commands/bump/#version_scheme) -- [Version provider](https://commitizen-tools.github.io/commitizen/config/#version-providers) +- [Version provider](https://commitizen-tools.github.io/commitizen/config/version_provider/) For all available options, see the [bump command documentation](https://commitizen-tools.github.io/commitizen/commands/bump/). @@ -249,7 +249,7 @@ Commitizen provides a comprehensive CLI with various commands. Here's the comple - [Conventional Commits Specification][conventional_commits] - [Exit Codes Reference](https://commitizen-tools.github.io/commitizen/exit_codes/) -- [Configuration Guide](https://commitizen-tools.github.io/commitizen/config/) +- [Configuration Guide](https://commitizen-tools.github.io/commitizen/config/configuration_file/) - [Command Documentation](https://commitizen-tools.github.io/commitizen/commands/init/) ### Getting Help diff --git a/docs/external_links.md b/docs/external_links.md index 1b5efb05df..9c30758774 100644 --- a/docs/external_links.md +++ b/docs/external_links.md @@ -14,6 +14,6 @@ - [Python Table Manners - Commitizen: 規格化 commit message](https://blog.wei-lee.me/posts/tech/2020/03/python-table-manners-commitizen/) (Written in Traditional Mandarin) - [Automating semantic release with commitizen](https://woile.dev/posts/automating-semver-releases-with-commitizen/) (English) - [How to Write Better Git Commit Messages – A Step-By-Step Guide](https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/?utm_source=tldrnewsletter) (English) -- [Continuous delivery made easy (in Python)](https://medium.com/dev-genius/continuous-delivery-made-easy-in-python-c085e9c82e69) +- [Continuous delivery made easy (in Python)](https://blog.devgenius.io/continuous-delivery-made-easy-in-python-c085e9c82e69) [automatizando]: https://youtu.be/t3aE2M8UPBo diff --git a/docs/faq.md b/docs/faq.md index 9de0c43e41..fba72325b8 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -120,7 +120,7 @@ If you would like to learn more about both schemes, there are plenty of good res - [API Versioning from Stripe](https://stripe.com/blog/api-versioning) - [Discussion about pip's use of CalVer](https://github.com/pypa/pip/issues/5645#issuecomment-407192448) - [Git Version Numbering](https://code.erpenbeck.io/git/2021/12/16/git-version-numbering/) -- [SemVer vs. CalVer and Why I Use Both](https://mikestaszel.com/2021/04/03/semver-vs-calver-and-why-i-use-both/) (but not at the same time) +- [SemVer vs. CalVer and Why I Use Both](https://mikestaszel.com/post/semver-vs-calver-and-why-i-use-both/) (but not at the same time) - [Semver Will Not Save You](https://hynek.me/articles/semver-will-not-save-you/) - [Why I Don't Like SemVer](https://snarky.ca/why-i-dont-like-semver/) diff --git a/docs/tutorials/github_actions.md b/docs/tutorials/github_actions.md index 2cb58cfee6..f15b62fbaa 100644 --- a/docs/tutorials/github_actions.md +++ b/docs/tutorials/github_actions.md @@ -113,13 +113,14 @@ jobs: poetry install - name: Build and publish env: - PYPI_USERNAME: __token__ - PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - ./scripts/publish + POETRY_HTTP_BASIC_PYPI_USERNAME: __token__ + POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: poetry publish --build ``` -Notice that we are using poetry, and we are calling a bash script in `./scripts/publish`. You should configure the action, and publish with your tools (twine, poetry, etc.). Check [Commitizen example](https://github.com/commitizen-tools/commitizen/blob/master/scripts/publish) +Notice that we are using poetry to publish the package. + + You can also use [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) to publish your package. Push the changes and that's it. diff --git a/docs/tutorials/writing_commits.md b/docs/tutorials/writing_commits.md index a56d6494d4..a3cf778dcf 100644 --- a/docs/tutorials/writing_commits.md +++ b/docs/tutorials/writing_commits.md @@ -46,6 +46,6 @@ Emojis may be added as well (e.g., see [cz-emoji][cz_emoji]), which requires the [customization]: ../customization/config_file.md [conventional_commits]: https://www.conventionalcommits.org -[cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-commitizen/#cz-emoji +[cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-plugins/cz-emoji/ [configuration]: ../config/commit.md#encoding [breaking-change-config]: ../config/commit.md#breaking_change_exclamation_in_title From a587af3dd06302bacfe076ec0558b8e9f77d18c7 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 6 Dec 2025 21:06:08 +0800 Subject: [PATCH 129/221] ci: add link checker --- .github/workflows/links.yml | 41 +++++++++++++++++++++++++++++++++++++ docs/README.md | 1 + 2 files changed, 42 insertions(+) create mode 100644 .github/workflows/links.yml diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 0000000000..8ef41f7789 --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,41 @@ +name: Links + +on: + repository_dispatch: + workflow_dispatch: + pull_request: + schedule: + - cron: "00 18 * * *" + +jobs: + check-links: + runs-on: ubuntu-latest + permissions: + issues: write # required for peter-evans/create-issue-from-file + steps: + - uses: actions/checkout@v5 + + - name: Link Checker + id: lychee + uses: lycheeverse/lychee-action@v2 + with: + args: . --exclude-path "tests" + fail: false + + - name: Broken Links Report + if: steps.lychee.outputs.exit_code != 0 && github.event_name == 'schedule' + uses: actions/github-script@v8 + with: + script: | + const fs = require('fs'); + + // Read the markdown file + // Ensure the path is correct relative to the workspace root + const reportBody = fs.readFileSync('./lychee/out.md', 'utf8'); + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Broken Links Report', + body: reportBody + });' diff --git a/docs/README.md b/docs/README.md index 3b8fd7fb64..abf059bac7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,5 @@ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/commitizen-tools/commitizen/pythonpackage.yml?label=python%20package&logo=github&logoColor=white&style=flat-square)](https://github.com/commitizen-tools/commitizen/actions) +[![Check Links](https://github.com/commitizen-tools/commitizen/actions/workflows/links.yml/badge.svg)](https://github.com/commitizen-tools/commitizen/actions/workflows/links.yml) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square)](https://conventionalcommits.org) [![PyPI Package latest release](https://img.shields.io/pypi/v/commitizen.svg?style=flat-square)](https://pypi.org/project/commitizen/) [![PyPI Package download count (per month)](https://img.shields.io/pypi/dm/commitizen?style=flat-square)](https://pypi.org/project/commitizen/) From 12ddd3791ded2263b21cca799e1282f66a8aeff9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Dec 2025 01:05:43 +0000 Subject: [PATCH 130/221] ci(deps): bump actions/checkout from 5 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> --- .github/workflows/links.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index 8ef41f7789..f5af8a76fb 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -13,7 +13,7 @@ jobs: permissions: issues: write # required for peter-evans/create-issue-from-file steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Link Checker id: lychee From c41d19b143cd3af2dc3591dc874131063638395f Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Fri, 26 Dec 2025 11:19:16 +0800 Subject: [PATCH 131/221] ci: fix syntax error in links.yml workflow --- .github/workflows/links.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index f5af8a76fb..c9d73f9746 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -38,4 +38,4 @@ jobs: repo: context.repo.repo, title: 'Broken Links Report', body: reportBody - });' + }); From 8c57f63354d5c5a52e470c66881fccf3f53daaa6 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 27 Dec 2025 20:28:59 +0800 Subject: [PATCH 132/221] ci: add configuration file for link checker --- .github/workflows/links.yml | 1 - lychee.toml | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 lychee.toml diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index c9d73f9746..b1d643217f 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -19,7 +19,6 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v2 with: - args: . --exclude-path "tests" fail: false - name: Broken Links Report diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 0000000000..a28b14d29f --- /dev/null +++ b/lychee.toml @@ -0,0 +1,5 @@ +exclude_path = ["./tests"] + +exclude = [ + "https://blog.devgenius.io/continuous-delivery-made-easy-in-python-c085e9c82e69" # Membership only article, sometimes it's 403 forbidden +] From 57cd232ffb40499f8bcb8814e375f2e577f5d4ee Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sat, 8 Nov 2025 19:10:56 +0800 Subject: [PATCH 133/221] build: update dev dependencies --- poetry.lock | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/poetry.lock b/poetry.lock index e7600db5d3..d5e5b4815b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1340,14 +1340,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.18" +version = "10.19" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "pymdown_extensions-10.18-py3-none-any.whl", hash = "sha256:090bca72be43f7d3186374e23c782899dbef9dc153ef24c59dcd3c346f9ffcae"}, - {file = "pymdown_extensions-10.18.tar.gz", hash = "sha256:20252abe6367354b24191431617a072ee6be9f68c5afcc74ea5573508a61f9e5"}, + {file = "pymdown_extensions-10.19-py3-none-any.whl", hash = "sha256:dc5f249fc3a1b6d8a6de4634ba8336b88d0942cee75e92b18ac79eaf3503bf7c"}, + {file = "pymdown_extensions-10.19.tar.gz", hash = "sha256:01bb917ea231f9ce14456fa9092cdb95ac3e5bd32202a3ee61dbd5ad2dd9ef9b"}, ] [package.dependencies] @@ -1689,31 +1689,31 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.14.8" +version = "0.14.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["linters"] files = [ - {file = "ruff-0.14.8-py3-none-linux_armv6l.whl", hash = "sha256:ec071e9c82eca417f6111fd39f7043acb53cd3fde9b1f95bbed745962e345afb"}, - {file = "ruff-0.14.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8cdb162a7159f4ca36ce980a18c43d8f036966e7f73f866ac8f493b75e0c27e9"}, - {file = "ruff-0.14.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e2fcbefe91f9fad0916850edf0854530c15bd1926b6b779de47e9ab619ea38f"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d70721066a296f45786ec31916dc287b44040f553da21564de0ab4d45a869b"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c87e09b3cd9d126fc67a9ecd3b5b1d3ded2b9c7fce3f16e315346b9d05cfb52"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d62cb310c4fbcb9ee4ac023fe17f984ae1e12b8a4a02e3d21489f9a2a5f730c"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1af35c2d62633d4da0521178e8a2641c636d2a7153da0bac1b30cfd4ccd91344"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25add4575ffecc53d60eed3f24b1e934493631b48ebbc6ebaf9d8517924aca4b"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c943d847b7f02f7db4201a0600ea7d244d8a404fbb639b439e987edcf2baf9a"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb6e8bf7b4f627548daa1b69283dac5a296bfe9ce856703b03130732e20ddfe2"}, - {file = "ruff-0.14.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7aaf2974f378e6b01d1e257c6948207aec6a9b5ba53fab23d0182efb887a0e4a"}, - {file = "ruff-0.14.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e5758ca513c43ad8a4ef13f0f081f80f08008f410790f3611a21a92421ab045b"}, - {file = "ruff-0.14.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f74f7ba163b6e85a8d81a590363bf71618847e5078d90827749bfda1d88c9cdf"}, - {file = "ruff-0.14.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:eed28f6fafcc9591994c42254f5a5c5ca40e69a30721d2ab18bb0bb3baac3ab6"}, - {file = "ruff-0.14.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:21d48fa744c9d1cb8d71eb0a740c4dd02751a5de9db9a730a8ef75ca34cf138e"}, - {file = "ruff-0.14.8-py3-none-win32.whl", hash = "sha256:15f04cb45c051159baebb0f0037f404f1dc2f15a927418f29730f411a79bc4e7"}, - {file = "ruff-0.14.8-py3-none-win_amd64.whl", hash = "sha256:9eeb0b24242b5bbff3011409a739929f497f3fb5fe3b5698aba5e77e8c833097"}, - {file = "ruff-0.14.8-py3-none-win_arm64.whl", hash = "sha256:965a582c93c63fe715fd3e3f8aa37c4b776777203d8e1d8aa3cc0c14424a4b99"}, - {file = "ruff-0.14.8.tar.gz", hash = "sha256:774ed0dd87d6ce925e3b8496feb3a00ac564bea52b9feb551ecd17e0a23d1eed"}, + {file = "ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75"}, + {file = "ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2"}, + {file = "ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a"}, + {file = "ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed"}, + {file = "ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b"}, + {file = "ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567"}, + {file = "ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a"}, + {file = "ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8"}, + {file = "ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197"}, + {file = "ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2"}, + {file = "ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84"}, + {file = "ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b"}, ] [[package]] @@ -1944,14 +1944,14 @@ markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"" [[package]] name = "urllib3" -version = "2.6.1" +version = "2.6.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["documentation"] files = [ - {file = "urllib3-2.6.1-py3-none-any.whl", hash = "sha256:e67d06fe947c36a7ca39f4994b08d73922d40e6cca949907be05efa6fd75110b"}, - {file = "urllib3-2.6.1.tar.gz", hash = "sha256:5379eb6e1aba4088bae84f8242960017ec8d8e3decf30480b3a1abdaa9671a3f"}, + {file = "urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"}, + {file = "urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797"}, ] [package.extras] From f226ea0f1bfd7179bbf19af8e9c4f7865d6f2efe Mon Sep 17 00:00:00 2001 From: Benedikt Ziegler <benediktziegler@gmail.com> Date: Mon, 1 Dec 2025 09:10:19 +0100 Subject: [PATCH 134/221] feat: add custom validation --- commitizen/commands/check.py | 50 +-- commitizen/cz/base.py | 65 ++- docs/customization.md | 596 +++++++++++++++++++++++++++ tests/commands/test_check_command.py | 137 +++++- 4 files changed, 812 insertions(+), 36 deletions(-) create mode 100644 docs/customization.md diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index 0ea5885eba..8ec5b47f8d 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -6,7 +6,6 @@ from commitizen import factory, git, out from commitizen.exceptions import ( - CommitMessageLengthExceededError, InvalidCommandArgumentError, InvalidCommitMessageError, NoCommitsFoundError, @@ -83,7 +82,7 @@ def __call__(self) -> None: """Validate if commit messages follows the conventional pattern. Raises: - InvalidCommitMessageError: if the commit provided not follows the conventional pattern + InvalidCommitMessageError: if the commit provided does not follow the conventional pattern NoCommitsFoundError: if no commit is found with the given range """ commits = self._get_commits() @@ -91,18 +90,24 @@ def __call__(self) -> None: raise NoCommitsFoundError(f"No commit found with range: '{self.rev_range}'") pattern = re.compile(self.cz.schema_pattern()) - invalid_msgs_content = "\n".join( - f'commit "{commit.rev}": "{commit.message}"' + invalid_commits = [ + (commit, check.errors) for commit in commits - if not self._validate_commit_message(commit.message, pattern, commit.rev) - ) - if invalid_msgs_content: - # TODO: capitalize the first letter of the error message for consistency in v5 + if not ( + check := self.cz.validate_commit_message( + commit_msg=commit.message, + pattern=pattern, + allow_abort=self.allow_abort, + allowed_prefixes=self.allowed_prefixes, + max_msg_length=self.max_msg_length, + commit_hash=commit.rev, + ) + ).is_valid + ] + + if invalid_commits: raise InvalidCommitMessageError( - "commit validation: failed!\n" - "please enter a commit message in the commitizen format.\n" - f"{invalid_msgs_content}\n" - f"pattern: {pattern.pattern}" + self.cz.format_exception_message(invalid_commits) ) out.success("Commit validation: successful!") @@ -157,24 +162,3 @@ def _filter_comments(msg: str) -> str: if not line.startswith("#"): lines.append(line) return "\n".join(lines) - - def _validate_commit_message( - self, commit_msg: str, pattern: re.Pattern[str], commit_hash: str - ) -> bool: - if not commit_msg: - return self.allow_abort - - if any(map(commit_msg.startswith, self.allowed_prefixes)): - return True - - if self.max_msg_length is not None: - msg_len = len(commit_msg.partition("\n")[0].strip()) - if msg_len > self.max_msg_length: - raise CommitMessageLengthExceededError( - f"commit validation: failed!\n" - f"commit message length exceeds the limit.\n" - f'commit "{commit_hash}": "{commit_msg}"\n' - f"message length limit: {self.max_msg_length} (actual: {msg_len})" - ) - - return bool(pattern.match(commit_msg)) diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index e4bf88cc1c..249b21515a 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -1,12 +1,16 @@ from __future__ import annotations from abc import ABCMeta, abstractmethod -from typing import TYPE_CHECKING, Any, Callable, Protocol +from collections.abc import Iterable, Mapping +from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Protocol from jinja2 import BaseLoader, PackageLoader from prompt_toolkit.styles import Style +from commitizen.exceptions import CommitMessageLengthExceededError + if TYPE_CHECKING: + import re from collections.abc import Iterable, Mapping from commitizen import git @@ -26,6 +30,11 @@ def __call__( ) -> dict[str, Any]: ... +class ValidationResult(NamedTuple): + is_valid: bool + errors: list + + class BaseCommitizen(metaclass=ABCMeta): bump_pattern: str | None = None bump_map: dict[str, str] | None = None @@ -43,7 +52,7 @@ class BaseCommitizen(metaclass=ABCMeta): ("disabled", "fg:#858585 italic"), ] - # The whole subject will be parsed as message by default + # The whole subject will be parsed as a message by default # This allows supporting changelog for any rule system. # It can be modified per rule commit_parser: str | None = r"(?P<message>.*)" @@ -101,3 +110,55 @@ def schema_pattern(self) -> str: @abstractmethod def info(self) -> str: """Information about the standardized commit message.""" + + def validate_commit_message( + self, + *, + commit_msg: str, + pattern: re.Pattern[str], + allow_abort: bool, + allowed_prefixes: list[str], + max_msg_length: int | None, + commit_hash: str, + ) -> ValidationResult: + """Validate commit message against the pattern.""" + if not commit_msg: + return ValidationResult( + allow_abort, [] if allow_abort else ["commit message is empty"] + ) + + if any(map(commit_msg.startswith, allowed_prefixes)): + return ValidationResult(True, []) + + if max_msg_length is not None: + msg_len = len(commit_msg.partition("\n")[0].strip()) + if msg_len > max_msg_length: + # TODO: capitalize the first letter of the error message for consistency in v5 + raise CommitMessageLengthExceededError( + f"commit validation: failed!\n" + f"commit message length exceeds the limit.\n" + f'commit "{commit_hash}": "{commit_msg}"\n' + f"message length limit: {max_msg_length} (actual: {msg_len})" + ) + + return ValidationResult( + bool(pattern.match(commit_msg)), + [f"pattern: {pattern.pattern}"], + ) + + def format_exception_message( + self, invalid_commits: list[tuple[git.GitCommit, list]] + ) -> str: + """Format commit errors.""" + displayed_msgs_content = "\n".join( + [ + f'commit "{commit.rev}": "{commit.message}\n"' + "\n".join(errors) + for commit, errors in invalid_commits + ] + ) + # TODO: capitalize the first letter of the error message for consistency in v5 + return ( + "commit validation: failed!\n" + "please enter a commit message in the commitizen format.\n" + f"{displayed_msgs_content}" + ) diff --git a/docs/customization.md b/docs/customization.md new file mode 100644 index 0000000000..93d85460f3 --- /dev/null +++ b/docs/customization.md @@ -0,0 +1,596 @@ +Customizing Commitizen is not hard at all. +We have two different ways to do so. + +## 1. Customize in configuration file + +The basic steps are: + +1. Define your custom committing or bumping rules in the configuration file. +2. Declare `name = "cz_customize"` in your configuration file, or add `-n cz_customize` when running Commitizen. + +Example: + +```toml title="pyproject.toml" +[tool.commitizen] +name = "cz_customize" + +[tool.commitizen.customize] +message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}" +example = "feature: this feature enable customize through config file" +schema = "<type>: <body>" +schema_pattern = "(feature|bug fix):(\\s.*)" +bump_pattern = "^(break|new|fix|hotfix)" +bump_map = {"break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH"} +change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"] +info_path = "cz_customize_info.txt" +info = """ +This is customized info +""" +commit_parser = "^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?" +changelog_pattern = "^(feature|bug fix)?(!)?" +change_type_map = {"feature" = "Feat", "bug fix" = "Fix"} + +[[tool.commitizen.customize.questions]] +type = "list" +name = "change_type" +choices = [{value = "feature", name = "feature: A new feature."}, {value = "bug fix", name = "bug fix: A bug fix."}] +# choices = ["feature", "fix"] # short version +message = "Select the type of change you are committing" + +[[tool.commitizen.customize.questions]] +type = "input" +name = "message" +message = "Body." + +[[tool.commitizen.customize.questions]] +type = "confirm" +name = "show_message" +message = "Do you want to add body message in commit?" +``` + +The equivalent example for a json config file: + +```json title=".cz.json" +{ + "commitizen": { + "name": "cz_customize", + "customize": { + "message_template": "{{change_type}}:{% if show_message %} {{message}}{% endif %}", + "example": "feature: this feature enable customize through config file", + "schema": "<type>: <body>", + "schema_pattern": "(feature|bug fix):(\\s.*)", + "bump_pattern": "^(break|new|fix|hotfix)", + "bump_map": { + "break": "MAJOR", + "new": "MINOR", + "fix": "PATCH", + "hotfix": "PATCH" + }, + "change_type_order": ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"], + "info_path": "cz_customize_info.txt", + "info": "This is customized info", + "commit_parser": "^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?", + "changelog_pattern": "^(feature|bug fix)?(!)?", + "change_type_map": {"feature": "Feat", "bug fix": "Fix"}, + "questions": [ + { + "type": "list", + "name": "change_type", + "choices": [ + { + "value": "feature", + "name": "feature: A new feature." + }, + { + "value": "bug fix", + "name": "bug fix: A bug fix." + } + ], + "message": "Select the type of change you are committing" + }, + { + "type": "input", + "name": "message", + "message": "Body." + }, + { + "type": "confirm", + "name": "show_message", + "message": "Do you want to add body message in commit?" + } + ] + } + } +} +``` + +And the correspondent example for a yaml file: + +```yaml title=".cz.yaml" +commitizen: + name: cz_customize + customize: + message_template: '{{change_type}}:{% if show_message %} {{message}}{% endif %}' + example: 'feature: this feature enable customize through config file' + schema: '<type>: <body>' + schema_pattern: '(feature|bug fix):(\\s.*)' + bump_pattern: '^(break|new|fix|hotfix)' + commit_parser: '^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?' + changelog_pattern: '^(feature|bug fix)?(!)?' + change_type_map: + feature: Feat + bug fix: Fix + bump_map: + break: MAJOR + new: MINOR + fix: PATCH + hotfix: PATCH + change_type_order: ['BREAKING CHANGE', 'feat', 'fix', 'refactor', 'perf'] + info_path: cz_customize_info.txt + info: This is customized info + questions: + - type: list + name: change_type + choices: + - value: feature + name: 'feature: A new feature.' + - value: bug fix + name: 'bug fix: A bug fix.' + message: Select the type of change you are committing + - type: input + name: message + message: 'Body.' + - type: confirm + name: show_message + message: 'Do you want to add body message in commit?' +``` + +### Customize configuration + +| Parameter | Type | Default | Description | +| ------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `questions` | `Questions` | `None` | Questions regarding the commit message. Detailed below. The type `Questions` is an alias to `Iterable[MutableMapping[str, Any]]` which is defined in `commitizen.defaults`. It expects a list of dictionaries. | +| `message_template` | `str` | `None` | The template for generating message from the given answers. `message_template` should either follow [Jinja2][jinja2] formatting specification, and all the variables in this template should be defined in `name` in `questions` | +| `example` | `str` | `""` | (OPTIONAL) Provide an example to help understand the style. Used by `cz example`. | +| `schema` | `str` | `""` | (OPTIONAL) Show the schema used. Used by `cz schema`. | +| `schema_pattern` | `str` | `""` | (OPTIONAL) The regular expression used to do commit message validation. Used by `cz check`. | +| `info_path` | `str` | `""` | (OPTIONAL) The path to the file that contains explanation of the commit rules. Used by `cz info`. If not provided `cz info`, will load `info` instead. | +| `info` | `str` | `""` | (OPTIONAL) Explanation of the commit rules. Used by `cz info`. | +| `bump_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | +| `bump_pattern` | `str` | `None` | (OPTIONAL) Regex to extract information from commit (subject and body) | +| `change_type_order` | `str` | `None` | (OPTIONAL) List of strings used to order the Changelog. All other types will be sorted alphabetically. Default is `["BREAKING CHANGE", "Feat", "Fix", "Refactor", "Perf"]` | +| `commit_parser` | `str` | `None` | (OPTIONAL) Regex to extract information used in creating changelog. [See more][changelog-spec] | +| `changelog_pattern` | `str` | `None` | (OPTIONAL) Regex to understand which commits to include in the changelog | +| `change_type_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the type of the commit to a changelog entry | + +[jinja2]: https://jinja.palletsprojects.com/en/2.10.x/ +[changelog-spec]: https://commitizen-tools.github.io/commitizen/commands/changelog/ + +#### Detailed `questions` content + +| Parameter | Type | Default | Description | +| ----------- | ------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `type` | `str` | `None` | The type of questions. Valid types: `list`, `select`, `input`, etc. The `select` type provides an interactive searchable list interface. [See More][different-question-types] | +| `name` | `str` | `None` | The key for the value answered by user. It's used in `message_template` | +| `message` | `str` | `None` | Detail description for the question. | +| `choices` | `list` | `None` | (OPTIONAL) The choices when `type = list` or `type = select`. Either use a list of values or a list of dictionaries with `name` and `value` keys. Keyboard shortcuts can be defined via `key`. See examples above. | +| `default` | `Any` | `None` | (OPTIONAL) The default value for this question. | +| `filter` | `str` | `None` | (OPTIONAL) Validator for user's answer. **(Work in Progress)** | +| `multiline` | `bool` | `False` | (OPTIONAL) Enable multiline support when `type = input`. | +| `use_search_filter` | `bool` | `False` | (OPTIONAL) Enable search/filter functionality for list/select type questions. This allows users to type and filter through the choices. | +| `use_jk_keys` | `bool` | `True` | (OPTIONAL) Enable/disable j/k keys for navigation in list/select type questions. Set to false if you prefer arrow keys only. | + +[different-question-types]: https://github.com/tmbo/questionary#different-question-types + +#### Shortcut keys + +When the [`use_shortcuts`](config.md#settings) config option is enabled, Commitizen can show and use keyboard shortcuts to select items from lists directly. +For example, when using the `cz_conventional_commits` Commitizen template, shortcut keys are shown when selecting the commit type. Unless otherwise defined, keyboard shortcuts will be numbered automatically. +To specify keyboard shortcuts for your custom choices, provide the shortcut using the `key` parameter in dictionary form for each choice you would like to customize. + +## 2. Customize through customizing a class + +The basic steps are: + +1. Inheriting from `BaseCommitizen`. +2. Give a name to your rules. +3. Create a python package using `setup.py`, `poetry`, etc. +4. Expose the class as a `commitizen.plugin` entrypoint. + +Check an [example][convcomms] on how to configure `BaseCommitizen`. + +You can also automate the steps above through [cookiecutter](https://cookiecutter.readthedocs.io/en/1.7.0/). + +```sh +cookiecutter gh:commitizen-tools/commitizen_cz_template +``` + +See [commitizen_cz_template](https://github.com/commitizen-tools/commitizen_cz_template) for details. + +Once you publish your rules, you can send us a PR to the [Third-party section](./third-party-commitizen.md). + +### Custom commit rules + +Create a Python module, for example `cz_jira.py`. + +Inherit from `BaseCommitizen`, and you must define `questions` and `message`. The others are optional. + +```python title="cz_jira.py" +from commitizen.cz.base import BaseCommitizen +from commitizen.defaults import Questions + + +class JiraCz(BaseCommitizen): + # Questions = Iterable[MutableMapping[str, Any]] + # It expects a list with dictionaries. + def questions(self) -> Questions: + """Questions regarding the commit message.""" + questions = [ + {"type": "input", "name": "title", "message": "Commit title"}, + {"type": "input", "name": "issue", "message": "Jira Issue number:"}, + ] + return questions + + def message(self, answers: dict) -> str: + """Generate the message with the given answers.""" + return "{0} (#{1})".format(answers["title"], answers["issue"]) + + def example(self) -> str: + """Provide an example to help understand the style (OPTIONAL) + + Used by `cz example`. + """ + return "Problem with user (#321)" + + def schema(self) -> str: + """Show the schema used (OPTIONAL) + + Used by `cz schema`. + """ + return "<title> (<issue>)" + + def info(self) -> str: + """Explanation of the commit rules. (OPTIONAL) + + Used by `cz info`. + """ + return "We use this because is useful" +``` + +The next file required is `setup.py` modified from flask version. + +```python title="setup.py" +from setuptools import setup + +setup( + name="JiraCommitizen", + version="0.1.0", + py_modules=["cz_jira"], + license="MIT", + long_description="this is a long description", + install_requires=["commitizen"], + entry_points={"commitizen.plugin": ["cz_jira = cz_jira:JiraCz"]}, +) +``` + +So in the end, we would have + + . + ├── cz_jira.py + └── setup.py + +And that's it. You can install it without uploading to pypi by simply +doing `pip install .` + +If you feel like it should be part of this repo, create a PR. + +### Custom bump rules + +You need to define 2 parameters inside your custom `BaseCommitizen`. + +| Parameter | Type | Default | Description | +| -------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | +| `bump_pattern` | `str` | `None` | Regex to extract information from commit (subject and body) | +| `bump_map` | `dict` | `None` | Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | + +Let's see an example. + +```python title="cz_strange.py" +from commitizen.cz.base import BaseCommitizen + + +class StrangeCommitizen(BaseCommitizen): + bump_pattern = r"^(break|new|fix|hotfix)" + bump_map = {"break": "MAJOR", "new": "MINOR", "fix": "PATCH", "hotfix": "PATCH"} +``` + +That's it, your Commitizen now supports custom rules, and you can run. + +```bash +cz -n cz_strange bump +``` + +[convcomms]: https://github.com/commitizen-tools/commitizen/blob/master/commitizen/cz/conventional_commits/conventional_commits.py + +### Custom commit validation and error message + +The commit message validation can be customized by overriding the `validate_commit_message` and `format_error_message` +methods from `BaseCommitizen`. This allows for a more detailed feedback to the user where the error originates from. + +```python +import re + +from commitizen.cz.base import BaseCommitizen, ValidationResult +from commitizen import git + + +class CustomValidationCz(BaseCommitizen): + def validate_commit_message( + self, + *, + commit_msg: str, + pattern: str | None, + allow_abort: bool, + allowed_prefixes: list[str], + max_msg_length: int, + ) -> ValidationResult: + """Validate commit message against the pattern.""" + if not commit_msg: + return allow_abort, [] if allow_abort else [f"commit message is empty"] + + if pattern is None: + return True, [] + + if any(map(commit_msg.startswith, allowed_prefixes)): + return True, [] + if max_msg_length: + msg_len = len(commit_msg.partition("\n")[0].strip()) + if msg_len > max_msg_length: + return False, [ + f"commit message is too long. Max length is {max_msg_length}" + ] + pattern_match = re.match(pattern, commit_msg) + if pattern_match: + return True, [] + else: + # Perform additional validation of the commit message format + # and add custom error messages as needed + return False, ["commit message does not match the pattern"] + + def format_exception_message( + self, ill_formated_commits: list[tuple[git.GitCommit, list]] + ) -> str: + """Format commit errors.""" + displayed_msgs_content = "\n".join( + [ + ( + f'commit "{commit.rev}": "{commit.message}"' + f"errors:\n" + "\n".join((f"- {error}" for error in errors)) + ) + for commit, errors in ill_formated_commits + ] + ) + return ( + "commit validation: failed!\n" + "please enter a commit message in the commitizen format.\n" + f"{displayed_msgs_content}\n" + f"pattern: {self.schema_pattern()}" + ) +``` + +### Custom changelog generator + +The changelog generator should just work in a very basic manner without touching anything. +You can customize it of course, and the following variables are the ones you need to add to your custom `BaseCommitizen`. + +| Parameter | Type | Required | Description | +| -------------------------------- | ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `commit_parser` | `str` | NO | Regex which should provide the variables explained in the [changelog description][changelog-des] | +| `changelog_pattern` | `str` | NO | Regex to validate the commits, this is useful to skip commits that don't meet your ruling standards like a Merge. Usually the same as bump_pattern | +| `change_type_map` | `dict` | NO | Convert the title of the change type that will appear in the changelog, if a value is not found, the original will be provided | +| `changelog_message_builder_hook` | `method: (dict, git.GitCommit) -> dict | list | None` | NO | Customize with extra information your message output, like adding links, this function is executed per parsed commit. Each GitCommit contains the following attrs: `rev`, `title`, `body`, `author`, `author_email`. Returning a falsy value ignore the commit. | +| `changelog_hook` | `method: (full_changelog: str, partial_changelog: Optional[str]) -> str` | NO | Receives the whole and partial (if used incremental) changelog. Useful to send slack messages or notify a compliance department. Must return the full_changelog | +| `changelog_release_hook` | `method: (release: dict, tag: git.GitTag) -> dict` | NO | Receives each generated changelog release and its associated tag. Useful to enrich releases before they are rendered. Must return the update release + +```python title="cz_strange.py" +from commitizen.cz.base import BaseCommitizen +import chat +import compliance + + +class StrangeCommitizen(BaseCommitizen): + changelog_pattern = r"^(break|new|fix|hotfix)" + commit_parser = r"^(?P<change_type>feat|fix|refactor|perf|BREAKING CHANGE)(?:\((?P<scope>[^()\r\n]*)\)|\()?(?P<breaking>!)?:\s(?P<message>.*)?" + change_type_map = { + "feat": "Features", + "fix": "Bug Fixes", + "refactor": "Code Refactor", + "perf": "Performance improvements", + } + + def changelog_message_builder_hook( + self, parsed_message: dict, commit: git.GitCommit + ) -> dict | list | None: + rev = commit.rev + m = parsed_message["message"] + parsed_message[ + "message" + ] = f"{m} {rev} [{commit.author}]({commit.author_email})" + return parsed_message + + def changelog_release_hook(self, release: dict, tag: git.GitTag) -> dict: + release["author"] = tag.author + return release + + def changelog_hook( + self, full_changelog: str, partial_changelog: Optional[str] + ) -> str: + """Executed at the end of the changelog generation + + full_changelog: it's the output about to being written into the file + partial_changelog: it's the new stuff, this is useful to send slack messages or + similar + + Return: + the new updated full_changelog + """ + if partial_changelog: + chat.room("#committers").notify(partial_changelog) + if full_changelog: + compliance.send(full_changelog) + full_changelog.replace(" fix ", " **fix** ") + return full_changelog +``` + +### Raise Customize Exception + +If you want `commitizen` to catch your exception and print the message, you'll have to inherit `CzException`. + +```python +from commitizen.cz.exception import CzException + + +class NoSubjectProvidedException(CzException): + ... +``` + +### Migrating from legacy plugin format + +Commitizen migrated to a new plugin format relying on `importlib.metadata.EntryPoint`. +Migration should be straight-forward for legacy plugins: + +- Remove the `discover_this` line from your plugin module +- Expose the plugin class under as a `commitizen.plugin` entrypoint. + +The name of the plugin is now determined by the name of the entrypoint. + +#### Example + +If you were having a `CzPlugin` class in a `cz_plugin.py` module like this: + +```python +from commitizen.cz.base import BaseCommitizen + + +class PluginCz(BaseCommitizen): + ... + + +discover_this = PluginCz +``` + +Then remove the `discover_this` line: + +```python +from commitizen.cz.base import BaseCommitizen + + +class PluginCz(BaseCommitizen): + ... +``` + +and expose the class as entrypoint in you setuptools: + +```python +from setuptools import setup + +setup( + name="MyPlugin", + version="0.1.0", + py_modules=["cz_plugin"], + entry_points={"commitizen.plugin": ["plugin = cz_plugin:PluginCz"]}, + ..., +) +``` + +Then your plugin will be available under the name `plugin`. + +## Customizing the changelog template + +Commitizen gives you the possibility to provide your own changelog template, by: + +- providing one with your customization class +- providing one from the current working directory and setting it: + - as [configuration][template-config] + - as `--template` parameter to both `bump` and `changelog` commands +- either by providing a template with the same name as the default template + +By default, the template used is the `CHANGELOG.md.j2` file from the Commitizen repository. + +### Providing a template with your customization class + +There are 3 parameters available to change the template rendering from your custom `BaseCommitizen`. + +| Parameter | Type | Default | Description | +| ----------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | +| `template` | `str` | `None` | Provide your own template name (default to `CHANGELOG.md.j2`) | +| `template_loader` | `str` | `None` | Override the default template loader (so you can provide template from your customization class) | +| `template_extras` | `dict` | `None` | Provide some extra template parameters | + +Let's see an example. + +```python +from commitizen.cz.base import BaseCommitizen +from jinja2 import PackageLoader + + +class MyPlugin(BaseCommitizen): + template = "CHANGELOG.md.jinja" + template_loader = PackageLoader("my_plugin", "templates") + template_extras = {"key": "value"} +``` + +This snippet will: + +- use `CHANGELOG.md.jinja` as template name +- search for it in the `templates` directory for `my_plugin` package +- add the `key=value` variable in the template + +### Providing a template from the current working directory + +Users can provide their own template from their current working directory (your project root) by: + +- providing a template with the same name (`CHANGELOG.md.j2` unless overridden by your custom class) +- setting your template path as `template` configuration +- giving your template path as `--template` parameter to `bump` and `changelog` commands + +!!! note + The path is relative to the current working directory, aka your project root most of the time. + +### Template variables + +The default template use a single `tree` variable which is a list of entries (a release) with the following format: + +| Name | Type | Description | +| ---- | ---- | ----------- | +| version | `str` | The release version | +| date | `datetime` | The release date | +| changes | `list[tuple[str, list[Change]]]` | The release sorted changes list in the form `(type, changes)` | + +Each `Change` has the following fields: + +| Name | Type | Description | +| ---- | ---- | ----------- | +| scope | `str | None` | An optional scope | +| message | `str` | The commit message body | +| sha1 | `str` | The commit `sha1` | +| parents | `list[str]` | The parent commit(s) `sha1`(s) | +| author | `str` | The commit author name | +| author_email | `str` | The commit author email | + +!!! note + The field values depend on the customization class and/or the settings you provide + +The `parents` field can be used to identify merge commits and generate a changelog based on those. Another use case +is listing commits that belong to the same pull request. + +When using another template (either provided by a plugin or by yourself), you can also pass extra template variables +by: + +- defining them in your configuration with the [`extras` settings][extras-config] +- providing them on the command line with the `--extra/-e` parameter to `bump` and `changelog` commands + +[template-config]: config.md#template +[extras-config]: config.md#extras +[changelog-des]: ./commands/changelog.md#description diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index e7918ca238..d545dbb18e 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -2,11 +2,13 @@ import sys from io import StringIO -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any import pytest from commitizen import cli, commands, git +from commitizen.cz import registry +from commitizen.cz.base import BaseCommitizen, ValidationResult from commitizen.exceptions import ( CommitMessageLengthExceededError, InvalidCommandArgumentError, @@ -16,8 +18,13 @@ from tests.utils import create_file_and_commit, skip_below_py_3_13 if TYPE_CHECKING: + import re + from collections.abc import Mapping + from pytest_mock import MockFixture + from commitizen.question import CzQuestion + COMMIT_LOG = [ "refactor: A code change that neither fixes a bug nor adds a feature", r"refactor(cz/connventional_commit): use \S to check scope", @@ -520,3 +527,131 @@ def test_check_command_cli_overrides_config_message_length_limit( config=config, arguments={"message": message, "message_length_limit": None}, ) + + +class ValidationCz(BaseCommitizen): + def questions(self) -> list[CzQuestion]: + return [ + {"type": "input", "name": "commit", "message": "Initial commit:\n"}, + {"type": "input", "name": "issue_nb", "message": "ABC-123"}, + ] + + def message(self, answers: Mapping[str, Any]) -> str: + return f"{answers['issue_nb']}: {answers['commit']}" + + def schema(self) -> str: + return "<issue_nb>: <commit>" + + def schema_pattern(self) -> str: + return r"^(?P<issue_nb>[A-Z]{3}-\d+): (?P<commit>.*)$" + + def example(self) -> str: + return "ABC-123: fixed a bug" + + def info(self) -> str: + return "Commit message must start with an issue number like ABC-123" + + def validate_commit_message( + self, + *, + commit_msg: str, + pattern: re.Pattern[str], + allow_abort: bool, + allowed_prefixes: list[str], + max_msg_length: int | None, + commit_hash: str, + ) -> ValidationResult: + """Validate commit message against the pattern.""" + if not commit_msg: + return ValidationResult( + allow_abort, [] if allow_abort else ["commit message is empty"] + ) + + if any(map(commit_msg.startswith, allowed_prefixes)): + return ValidationResult(True, []) + + if max_msg_length: + msg_len = len(commit_msg.partition("\n")[0].strip()) + if msg_len > max_msg_length: + # TODO: capitalize the first letter of the error message for consistency in v5 + raise CommitMessageLengthExceededError( + f"commit validation: failed!\n" + f"commit message length exceeds the limit.\n" + f'commit "{commit_hash}": "{commit_msg}"\n' + f"message length limit: {max_msg_length} (actual: {msg_len})" + ) + + return ValidationResult( + bool(pattern.match(commit_msg)), [f"pattern: {pattern.pattern}"] + ) + + def format_exception_message( + self, invalid_commits: list[tuple[git.GitCommit, list]] + ) -> str: + """Format commit errors.""" + displayed_msgs_content = "\n".join( + [ + ( + f'commit "{commit.rev}": "{commit.message}"\nerrors:\n\n'.join( + f"- {error}" for error in errors + ) + ) + for (commit, errors) in invalid_commits + ] + ) + return ( + "commit validation: failed!\n" + "please enter a commit message in the commitizen format.\n" + f"{displayed_msgs_content}" + ) + + +@pytest.fixture +def use_cz_custom_validator(mocker): + new_cz = {**registry, "cz_custom_validator": ValidationCz} + mocker.patch.dict("commitizen.cz.registry", new_cz) + + +@pytest.mark.usefixtures("use_cz_custom_validator") +def test_check_command_with_custom_validator_succeed(mocker: MockFixture, capsys): + testargs = [ + "cz", + "--name", + "cz_custom_validator", + "check", + "--commit-msg-file", + "some_file", + ] + mocker.patch.object(sys, "argv", testargs) + mocker.patch( + "commitizen.commands.check.open", + mocker.mock_open(read_data="ABC-123: add commitizen pre-commit hook"), + ) + cli.main() + out, _ = capsys.readouterr() + assert "Commit validation: successful!" in out + + +@pytest.mark.usefixtures("use_cz_custom_validator") +def test_check_command_with_custom_validator_failed(mocker: MockFixture): + testargs = [ + "cz", + "--name", + "cz_custom_validator", + "check", + "--commit-msg-file", + "some_file", + ] + mocker.patch.object(sys, "argv", testargs) + mocker.patch( + "commitizen.commands.check.open", + mocker.mock_open( + read_data="123-ABC issue id has wrong format and misses colon" + ), + ) + with pytest.raises(InvalidCommitMessageError) as excinfo: + cli.main() + assert "commit validation: failed!" in str(excinfo.value), ( + "Pattern validation unexpectedly passed" + ) + assert "pattern: " in str(excinfo.value), "Pattern not found in error message" From b494695f246c06da40512e28073687d042f4e954 Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sun, 16 Nov 2025 10:39:53 +0800 Subject: [PATCH 135/221] feat: Drop support for Python 3.9 as EOL reached and add Python 3.14 support --- .github/workflows/pythonpackage.yml | 2 +- docs/README.md | 2 +- docs/contributing.md | 2 +- docs/contributing_tldr.md | 6 +- docs/tutorials/gitlab_ci.md | 2 +- poetry.lock | 437 ++++++++++++---------------- pyproject.toml | 6 +- 7 files changed, 197 insertions(+), 260 deletions(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 4e4738ac90..7605301822 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -6,7 +6,7 @@ jobs: python-check: strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] platform: [ubuntu-22.04, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/docs/README.md b/docs/README.md index abf059bac7..d61ec18085 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,7 +56,7 @@ This standardization makes your commit history more readable and meaningful, whi Before installing Commitizen, ensure you have: -- [Python](https://www.python.org/downloads/) `3.9+` +- [Python](https://www.python.org/downloads/) `3.10+` - [Git][gitscm] `1.8.5.2+` ### Installation diff --git a/docs/contributing.md b/docs/contributing.md index 741a13f213..18d767750c 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -15,7 +15,7 @@ If you're a first-time contributor, please check out issues labeled [good first ### Required Tools 1. **Python Environment** - - Python `>=3.9` + - Python `>=3.10` - [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.2.0` 2. **Version Control & Security** - Git diff --git a/docs/contributing_tldr.md b/docs/contributing_tldr.md index 7b040c2951..b7c1c94762 100644 --- a/docs/contributing_tldr.md +++ b/docs/contributing_tldr.md @@ -2,7 +2,7 @@ Feel free to send a PR to update this file if you find anything useful. 🙇 ## Environment -- Python `>=3.9` +- Python `>=3.10` - [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.2.0` ## Useful commands @@ -21,8 +21,8 @@ poetry format # Check if ruff and mypy are happy poetry lint -# Check if mypy is happy in python 3.9 -mypy --python-version 3.9 +# Check if mypy is happy in python 3.10 +mypy --python-version 3.10 # Run tests in parallel. pytest -n auto # This may take a while. diff --git a/docs/tutorials/gitlab_ci.md b/docs/tutorials/gitlab_ci.md index 6f6d53a57e..0af05c4e7b 100644 --- a/docs/tutorials/gitlab_ci.md +++ b/docs/tutorials/gitlab_ci.md @@ -74,7 +74,7 @@ test: auto-bump: stage: auto-bump - image: python:3.9 + image: python:3.10 before_script: - "which ssh-agent || ( apt-get update -qy && apt-get install openssh-client -qqy )" - eval `ssh-agent -s` diff --git a/poetry.lock b/poetry.lock index d5e5b4815b..72cafcd565 100644 --- a/poetry.lock +++ b/poetry.lock @@ -92,14 +92,14 @@ files = [ [[package]] name = "cfgv" -version = "3.4.0" +version = "3.5.0" description = "Validate configuration and produce human readable error messages." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["linters"] files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, + {file = "cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}, + {file = "cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}, ] [[package]] @@ -239,14 +239,14 @@ files = [ [[package]] name = "click" -version = "8.1.8" +version = "8.3.1" description = "Composable command line interface toolkit" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" groups = ["documentation"] files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, ] [package.dependencies] @@ -266,116 +266,104 @@ files = [ [[package]] name = "coverage" -version = "7.10.7" +version = "7.13.0" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["test"] files = [ - {file = "coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a"}, - {file = "coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5"}, - {file = "coverage-7.10.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17"}, - {file = "coverage-7.10.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b"}, - {file = "coverage-7.10.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87"}, - {file = "coverage-7.10.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e"}, - {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e"}, - {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df"}, - {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0"}, - {file = "coverage-7.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13"}, - {file = "coverage-7.10.7-cp310-cp310-win32.whl", hash = "sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b"}, - {file = "coverage-7.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807"}, - {file = "coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59"}, - {file = "coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a"}, - {file = "coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699"}, - {file = "coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d"}, - {file = "coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e"}, - {file = "coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23"}, - {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab"}, - {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82"}, - {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2"}, - {file = "coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61"}, - {file = "coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14"}, - {file = "coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2"}, - {file = "coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a"}, - {file = "coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417"}, - {file = "coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973"}, - {file = "coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c"}, - {file = "coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7"}, - {file = "coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6"}, - {file = "coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59"}, - {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b"}, - {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a"}, - {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb"}, - {file = "coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1"}, - {file = "coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256"}, - {file = "coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba"}, - {file = "coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf"}, - {file = "coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d"}, - {file = "coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b"}, - {file = "coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e"}, - {file = "coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b"}, - {file = "coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49"}, - {file = "coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911"}, - {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0"}, - {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f"}, - {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c"}, - {file = "coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f"}, - {file = "coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698"}, - {file = "coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843"}, - {file = "coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546"}, - {file = "coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c"}, - {file = "coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15"}, - {file = "coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4"}, - {file = "coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0"}, - {file = "coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0"}, - {file = "coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65"}, - {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541"}, - {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6"}, - {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999"}, - {file = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2"}, - {file = "coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a"}, - {file = "coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb"}, - {file = "coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb"}, - {file = "coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520"}, - {file = "coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32"}, - {file = "coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f"}, - {file = "coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a"}, - {file = "coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360"}, - {file = "coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69"}, - {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14"}, - {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe"}, - {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e"}, - {file = "coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd"}, - {file = "coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2"}, - {file = "coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681"}, - {file = "coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880"}, - {file = "coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63"}, - {file = "coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2"}, - {file = "coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d"}, - {file = "coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0"}, - {file = "coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699"}, - {file = "coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9"}, - {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f"}, - {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1"}, - {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0"}, - {file = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399"}, - {file = "coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235"}, - {file = "coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d"}, - {file = "coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a"}, - {file = "coverage-7.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3"}, - {file = "coverage-7.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c"}, - {file = "coverage-7.10.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396"}, - {file = "coverage-7.10.7-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40"}, - {file = "coverage-7.10.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594"}, - {file = "coverage-7.10.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a"}, - {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b"}, - {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3"}, - {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0"}, - {file = "coverage-7.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f"}, - {file = "coverage-7.10.7-cp39-cp39-win32.whl", hash = "sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431"}, - {file = "coverage-7.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07"}, - {file = "coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260"}, - {file = "coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239"}, + {file = "coverage-7.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:02d9fb9eccd48f6843c98a37bd6817462f130b86da8660461e8f5e54d4c06070"}, + {file = "coverage-7.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:367449cf07d33dc216c083f2036bb7d976c6e4903ab31be400ad74ad9f85ce98"}, + {file = "coverage-7.13.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cdb3c9f8fef0a954c632f64328a3935988d33a6604ce4bf67ec3e39670f12ae5"}, + {file = "coverage-7.13.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d10fd186aac2316f9bbb46ef91977f9d394ded67050ad6d84d94ed6ea2e8e54e"}, + {file = "coverage-7.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f88ae3e69df2ab62fb0bc5219a597cb890ba5c438190ffa87490b315190bb33"}, + {file = "coverage-7.13.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4be718e51e86f553bcf515305a158a1cd180d23b72f07ae76d6017c3cc5d791"}, + {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a00d3a393207ae12f7c49bb1c113190883b500f48979abb118d8b72b8c95c032"}, + {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a7b1cd820e1b6116f92c6128f1188e7afe421c7e1b35fa9836b11444e53ebd9"}, + {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:37eee4e552a65866f15dedd917d5e5f3d59805994260720821e2c1b51ac3248f"}, + {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62d7c4f13102148c78d7353c6052af6d899a7f6df66a32bddcc0c0eb7c5326f8"}, + {file = "coverage-7.13.0-cp310-cp310-win32.whl", hash = "sha256:24e4e56304fdb56f96f80eabf840eab043b3afea9348b88be680ec5986780a0f"}, + {file = "coverage-7.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:74c136e4093627cf04b26a35dab8cbfc9b37c647f0502fc313376e11726ba303"}, + {file = "coverage-7.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820"}, + {file = "coverage-7.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753"}, + {file = "coverage-7.13.0-cp311-cp311-win32.whl", hash = "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b"}, + {file = "coverage-7.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe"}, + {file = "coverage-7.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7"}, + {file = "coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf"}, + {file = "coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd"}, + {file = "coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef"}, + {file = "coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae"}, + {file = "coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080"}, + {file = "coverage-7.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:28ee1c96109974af104028a8ef57cec21447d42d0e937c0275329272e370ebcf"}, + {file = "coverage-7.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e97353dcc5587b85986cda4ff3ec98081d7e84dd95e8b2a6d59820f0545f8a"}, + {file = "coverage-7.13.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:99acd4dfdfeb58e1937629eb1ab6ab0899b131f183ee5f23e0b5da5cba2fec74"}, + {file = "coverage-7.13.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff45e0cd8451e293b63ced93161e189780baf444119391b3e7d25315060368a6"}, + {file = "coverage-7.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4f72a85316d8e13234cafe0a9f81b40418ad7a082792fa4165bd7d45d96066b"}, + {file = "coverage-7.13.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11c21557d0e0a5a38632cbbaca5f008723b26a89d70db6315523df6df77d6232"}, + {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76541dc8d53715fb4f7a3a06b34b0dc6846e3c69bc6204c55653a85dd6220971"}, + {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6e9e451dee940a86789134b6b0ffbe31c454ade3b849bb8a9d2cca2541a8e91d"}, + {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5c67dace46f361125e6b9cace8fe0b729ed8479f47e70c89b838d319375c8137"}, + {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f59883c643cb19630500f57016f76cfdcd6845ca8c5b5ea1f6e17f74c8e5f511"}, + {file = "coverage-7.13.0-cp313-cp313-win32.whl", hash = "sha256:58632b187be6f0be500f553be41e277712baa278147ecb7559983c6d9faf7ae1"}, + {file = "coverage-7.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:73419b89f812f498aca53f757dd834919b48ce4799f9d5cad33ca0ae442bdb1a"}, + {file = "coverage-7.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb76670874fdd6091eedcc856128ee48c41a9bbbb9c3f1c7c3cf169290e3ffd6"}, + {file = "coverage-7.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6e63ccc6e0ad8986386461c3c4b737540f20426e7ec932f42e030320896c311a"}, + {file = "coverage-7.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:494f5459ffa1bd45e18558cd98710c36c0b8fbfa82a5eabcbe671d80ecffbfe8"}, + {file = "coverage-7.13.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:06cac81bf10f74034e055e903f5f946e3e26fc51c09fc9f584e4a1605d977053"}, + {file = "coverage-7.13.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f2ffc92b46ed6e6760f1d47a71e56b5664781bc68986dbd1836b2b70c0ce2071"}, + {file = "coverage-7.13.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0602f701057c6823e5db1b74530ce85f17c3c5be5c85fc042ac939cbd909426e"}, + {file = "coverage-7.13.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:25dc33618d45456ccb1d37bce44bc78cf269909aa14c4db2e03d63146a8a1493"}, + {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:71936a8b3b977ddd0b694c28c6a34f4fff2e9dd201969a4ff5d5fc7742d614b0"}, + {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:936bc20503ce24770c71938d1369461f0c5320830800933bc3956e2a4ded930e"}, + {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:af0a583efaacc52ae2521f8d7910aff65cdb093091d76291ac5820d5e947fc1c"}, + {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f1c23e24a7000da892a312fb17e33c5f94f8b001de44b7cf8ba2e36fbd15859e"}, + {file = "coverage-7.13.0-cp313-cp313t-win32.whl", hash = "sha256:5f8a0297355e652001015e93be345ee54393e45dc3050af4a0475c5a2b767d46"}, + {file = "coverage-7.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6abb3a4c52f05e08460bd9acf04fec027f8718ecaa0d09c40ffbc3fbd70ecc39"}, + {file = "coverage-7.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:3ad968d1e3aa6ce5be295ab5fe3ae1bf5bb4769d0f98a80a0252d543a2ef2e9e"}, + {file = "coverage-7.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:453b7ec753cf5e4356e14fe858064e5520c460d3bbbcb9c35e55c0d21155c256"}, + {file = "coverage-7.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af827b7cbb303e1befa6c4f94fd2bf72f108089cfa0f8abab8f4ca553cf5ca5a"}, + {file = "coverage-7.13.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9987a9e4f8197a1000280f7cc089e3ea2c8b3c0a64d750537809879a7b4ceaf9"}, + {file = "coverage-7.13.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3188936845cd0cb114fa6a51842a304cdbac2958145d03be2377ec41eb285d19"}, + {file = "coverage-7.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2bdb3babb74079f021696cb46b8bb5f5661165c385d3a238712b031a12355be"}, + {file = "coverage-7.13.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7464663eaca6adba4175f6c19354feea61ebbdd735563a03d1e472c7072d27bb"}, + {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8069e831f205d2ff1f3d355e82f511eb7c5522d7d413f5db5756b772ec8697f8"}, + {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6fb2d5d272341565f08e962cce14cdf843a08ac43bd621783527adb06b089c4b"}, + {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5e70f92ef89bac1ac8a99b3324923b4749f008fdbd7aa9cb35e01d7a284a04f9"}, + {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4b5de7d4583e60d5fd246dd57fcd3a8aa23c6e118a8c72b38adf666ba8e7e927"}, + {file = "coverage-7.13.0-cp314-cp314-win32.whl", hash = "sha256:a6c6e16b663be828a8f0b6c5027d36471d4a9f90d28444aa4ced4d48d7d6ae8f"}, + {file = "coverage-7.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:0900872f2fdb3ee5646b557918d02279dc3af3dfb39029ac4e945458b13f73bc"}, + {file = "coverage-7.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:3a10260e6a152e5f03f26db4a407c4c62d3830b9af9b7c0450b183615f05d43b"}, + {file = "coverage-7.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9097818b6cc1cfb5f174e3263eba4a62a17683bcfe5c4b5d07f4c97fa51fbf28"}, + {file = "coverage-7.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0018f73dfb4301a89292c73be6ba5f58722ff79f51593352759c1790ded1cabe"}, + {file = "coverage-7.13.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:166ad2a22ee770f5656e1257703139d3533b4a0b6909af67c6b4a3adc1c98657"}, + {file = "coverage-7.13.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f6aaef16d65d1787280943f1c8718dc32e9cf141014e4634d64446702d26e0ff"}, + {file = "coverage-7.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e999e2dcc094002d6e2c7bbc1fb85b58ba4f465a760a8014d97619330cdbbbf3"}, + {file = "coverage-7.13.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:00c3d22cf6fb1cf3bf662aaaa4e563be8243a5ed2630339069799835a9cc7f9b"}, + {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22ccfe8d9bb0d6134892cbe1262493a8c70d736b9df930f3f3afae0fe3ac924d"}, + {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9372dff5ea15930fea0445eaf37bbbafbc771a49e70c0aeed8b4e2c2614cc00e"}, + {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:69ac2c492918c2461bc6ace42d0479638e60719f2a4ef3f0815fa2df88e9f940"}, + {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:739c6c051a7540608d097b8e13c76cfa85263ced467168dc6b477bae3df7d0e2"}, + {file = "coverage-7.13.0-cp314-cp314t-win32.whl", hash = "sha256:fe81055d8c6c9de76d60c94ddea73c290b416e061d40d542b24a5871bad498b7"}, + {file = "coverage-7.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:445badb539005283825959ac9fa4a28f712c214b65af3a2c464f1adc90f5fcbc"}, + {file = "coverage-7.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:de7f6748b890708578fc4b7bb967d810aeb6fcc9bff4bb77dbca77dab2f9df6a"}, + {file = "coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904"}, + {file = "coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936"}, ] [package.dependencies] @@ -445,7 +433,7 @@ description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" groups = ["dev", "test"] -markers = "python_version < \"3.11\"" +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, @@ -489,14 +477,14 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "filelock" -version = "3.19.1" +version = "3.20.0" description = "A platform independent file lock." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev", "linters"] files = [ - {file = "filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"}, - {file = "filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58"}, + {file = "filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2"}, + {file = "filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4"}, ] [[package]] @@ -562,53 +550,28 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] -[[package]] -name = "importlib-metadata" -version = "8.6.1" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.9" -groups = ["main", "documentation"] -markers = "python_version == \"3.9\"" -files = [ - {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, - {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, -] - -[package.dependencies] -zipp = ">=3.20" - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -perf = ["ipython"] -test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy"] - [[package]] name = "iniconfig" -version = "2.1.0" +version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["test"] files = [ - {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, - {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, ] [[package]] name = "ipython" -version = "8.18.1" +version = "8.37.0" description = "IPython: Productive Interactive Computing" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, - {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, + {file = "ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2"}, + {file = "ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216"}, ] [package.dependencies] @@ -617,25 +580,26 @@ decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -prompt-toolkit = ">=3.0.41,<3.1.0" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt_toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" -stack-data = "*" -traitlets = ">=5" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} +stack_data = "*" +traitlets = ">=5.13.0" +typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli ; python_version < \"3.11\"", "typing_extensions"] kernel = ["ipykernel"] +matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] +test = ["packaging", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] [[package]] name = "jedi" @@ -763,33 +727,30 @@ files = [ [[package]] name = "markdown" -version = "3.9" +version = "3.10" description = "Python implementation of John Gruber's Markdown." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["documentation"] files = [ - {file = "markdown-3.9-py3-none-any.whl", hash = "sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280"}, - {file = "markdown-3.9.tar.gz", hash = "sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a"}, + {file = "markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c"}, + {file = "markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e"}, ] -[package.dependencies] -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} - [package.extras] docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] [[package]] name = "markdown-it-py" -version = "3.0.0" +version = "4.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["script"] files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, + {file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}, + {file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}, ] [package.dependencies] @@ -797,13 +758,12 @@ mdurl = ">=0.1,<1.0" [package.extras] benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "markdown-it-pyrs", "mistletoe (>=1.0,<2.0)", "mistune (>=3.0,<4.0)", "panflute (>=2.3,<3.0)"] linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] +plugins = ["mdit-py-plugins (>=0.5.0)"] profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] +rtd = ["ipykernel", "jupyter_sphinx", "mdit-py-plugins (>=0.5.0)", "myst-parser", "pyyaml", "sphinx", "sphinx-book-theme (>=1.0,<2.0)", "sphinx-copybutton", "sphinx-design"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "requests"] [[package]] name = "markupsafe" @@ -962,7 +922,6 @@ files = [ click = ">=7.0" colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} jinja2 = ">=2.11.1" markdown = ">=3.3.6" markupsafe = ">=2.0.1" @@ -991,7 +950,6 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} mergedeep = ">=1.3.4" platformdirs = ">=2.2.0" pyyaml = ">=5.1" @@ -1199,7 +1157,7 @@ description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" groups = ["dev"] -markers = "sys_platform != \"win32\"" +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, @@ -1210,20 +1168,20 @@ ptyprocess = ">=0.5" [[package]] name = "platformdirs" -version = "4.4.0" +version = "4.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev", "documentation", "linters"] files = [ - {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, - {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, + {file = "platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"}, + {file = "platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] +docs = ["furo (>=2025.9.25)", "proselint (>=0.14)", "sphinx (>=8.2.3)", "sphinx-autodoc-typehints (>=3.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)"] +type = ["mypy (>=1.18.2)"] [[package]] name = "pluggy" @@ -1243,34 +1201,34 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "poethepoet" -version = "0.37.0" +version = "0.38.0" description = "A task runner that works well with poetry and uv." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "poethepoet-0.37.0-py3-none-any.whl", hash = "sha256:861790276315abcc8df1b4bd60e28c3d48a06db273edd3092f3c94e1a46e5e22"}, - {file = "poethepoet-0.37.0.tar.gz", hash = "sha256:73edf458707c674a079baa46802e21455bda3a7f82a408e58c31b9f4fe8e933d"}, + {file = "poethepoet-0.38.0-py3-none-any.whl", hash = "sha256:214bd9fcb348ff3dfd1466579d67e0c02242451a7044aced1a79641adef9cad0"}, + {file = "poethepoet-0.38.0.tar.gz", hash = "sha256:aeeb2f0a2cf0d3afa833976eff3ac7b8f5e472ae64171824900d79d3c68163c7"}, ] [package.dependencies] pastel = ">=0.2.1,<0.3.0" -pyyaml = ">=6.0.2,<7.0" -tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} +pyyaml = ">=6.0.3,<7.0" +tomli = {version = ">=1.3.0", markers = "python_version < \"3.11\""} [package.extras] poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""] [[package]] name = "pre-commit" -version = "4.3.0" +version = "4.5.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["linters"] files = [ - {file = "pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8"}, - {file = "pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16"}, + {file = "pre_commit-4.5.0-py2.py3-none-any.whl", hash = "sha256:25e2ce09595174d9c97860a95609f9f852c0614ba602de3561e267547f2335e1"}, + {file = "pre_commit-4.5.0.tar.gz", hash = "sha256:dc5a065e932b19fc1d4c653c6939068fe54325af8e741e74e88db4d28a4dd66b"}, ] [package.dependencies] @@ -1302,7 +1260,7 @@ description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" groups = ["dev"] -markers = "sys_platform != \"win32\"" +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -1359,41 +1317,41 @@ extra = ["pygments (>=2.19.1)"] [[package]] name = "pyproject-api" -version = "1.9.1" +version = "1.10.0" description = "API to interact with the python pyproject.toml based projects" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pyproject_api-1.9.1-py3-none-any.whl", hash = "sha256:7d6238d92f8962773dd75b5f0c4a6a27cce092a14b623b811dba656f3b628948"}, - {file = "pyproject_api-1.9.1.tar.gz", hash = "sha256:43c9918f49daab37e302038fc1aed54a8c7a91a9fa935d00b9a485f37e0f5335"}, + {file = "pyproject_api-1.10.0-py3-none-any.whl", hash = "sha256:8757c41a79c0f4ab71b99abed52b97ecf66bd20b04fa59da43b5840bac105a09"}, + {file = "pyproject_api-1.10.0.tar.gz", hash = "sha256:40c6f2d82eebdc4afee61c773ed208c04c19db4c4a60d97f8d7be3ebc0bbb330"}, ] [package.dependencies] packaging = ">=25" -tomli = {version = ">=2.2.1", markers = "python_version < \"3.11\""} +tomli = {version = ">=2.3", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=3.2)"] -testing = ["covdefaults (>=2.3)", "pytest (>=8.3.5)", "pytest-cov (>=6.1.1)", "pytest-mock (>=3.14)", "setuptools (>=80.3.1)"] +docs = ["furo (>=2025.9.25)", "sphinx-autodoc-typehints (>=3.5.1)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)", "setuptools (>=80.9)"] [[package]] name = "pytest" -version = "8.4.2" +version = "9.0.2" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["test"] files = [ - {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, - {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, + {file = "pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b"}, + {file = "pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11"}, ] [package.dependencies] colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} -iniconfig = ">=1" -packaging = ">=20" +iniconfig = ">=1.0.1" +packaging = ">=22" pluggy = ">=1.5,<2" pygments = ">=2.7.2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} @@ -1750,14 +1708,14 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "termcolor" -version = "3.1.0" +version = "3.2.0" description = "ANSI color formatting for output in terminal" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa"}, - {file = "termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970"}, + {file = "termcolor-3.2.0-py3-none-any.whl", hash = "sha256:a10343879eba4da819353c55cb8049b0933890c2ebf9ad5d3ecd2bb32ea96ea6"}, + {file = "termcolor-3.2.0.tar.gz", hash = "sha256:610e6456feec42c4bcd28934a8c87a06c3fa28b01561d46aa09a9881b8622c58"}, ] [package.extras] @@ -1814,7 +1772,7 @@ files = [ {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"}, {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, ] -markers = {dev = "python_version < \"3.11\"", linters = "python_version < \"3.11\"", test = "python_full_version <= \"3.11.0a6\""} +markers = {dev = "python_version == \"3.10\"", linters = "python_version == \"3.10\"", test = "python_full_version <= \"3.11.0a6\""} [[package]] name = "tomlkit" @@ -1830,28 +1788,28 @@ files = [ [[package]] name = "tox" -version = "4.30.3" +version = "4.32.0" description = "tox is a generic virtualenv management and test command line tool" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "tox-4.30.3-py3-none-any.whl", hash = "sha256:a9f17b4b2d0f74fe0d76207236925a119095011e5c2e661a133115a8061178c9"}, - {file = "tox-4.30.3.tar.gz", hash = "sha256:f3dd0735f1cd4e8fbea5a3661b77f517456b5f0031a6256432533900e34b90bf"}, + {file = "tox-4.32.0-py3-none-any.whl", hash = "sha256:451e81dc02ba8d1ed20efd52ee409641ae4b5d5830e008af10fe8823ef1bd551"}, + {file = "tox-4.32.0.tar.gz", hash = "sha256:1ad476b5f4d3679455b89a992849ffc3367560bbc7e9495ee8a3963542e7c8ff"}, ] [package.dependencies] -cachetools = ">=6.1" +cachetools = ">=6.2" chardet = ">=5.2" colorama = ">=0.4.6" -filelock = ">=3.18" +filelock = ">=3.20" packaging = ">=25" -platformdirs = ">=4.3.8" +platformdirs = ">=4.5" pluggy = ">=1.6" pyproject-api = ">=1.9.1" -tomli = {version = ">=2.2.1", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.14.1", markers = "python_version < \"3.11\""} -virtualenv = ">=20.31.2" +tomli = {version = ">=2.3", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.15", markers = "python_version < \"3.11\""} +virtualenv = ">=20.34" [[package]] name = "traitlets" @@ -1940,7 +1898,7 @@ files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] -markers = {main = "python_version < \"3.11\"", dev = "python_version < \"3.11\"", test = "python_version < \"3.11\""} +markers = {main = "python_version == \"3.10\"", dev = "python_version < \"3.12\"", test = "python_version == \"3.10\""} [[package]] name = "urllib3" @@ -2157,28 +2115,7 @@ files = [ [package.extras] dev = ["pytest", "setuptools"] -[[package]] -name = "zipp" -version = "3.23.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.9" -groups = ["main", "documentation"] -markers = "python_version == \"3.9\"" -files = [ - {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, - {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy"] - [metadata] lock-version = "2.1" -python-versions = ">=3.9,<4.0" -content-hash = "8f4edbdaff3ae48098899feacba7ea3764bdf2d960b78b8f5e8c39b19cc8c2e1" +python-versions = ">=3.10,<4.0" +content-hash = "694d9328c2fd7b1aaa342efe590802db4ddf915a91020276a8b28b2e025d5842" diff --git a/pyproject.toml b/pyproject.toml index 3e9c45ae63..120bd2792d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ maintainers = [ ] license = { file = "LICENSE" } readme = "docs/README.md" -requires-python = ">=3.9,<4.0" +requires-python = ">=3.10,<4.0" dependencies = [ "questionary (>=2.0,<3.0)", # Exclude transitive dependency due to known issue in questionary: https://github.com/tmbo/questionary/issues/454 @@ -39,11 +39,11 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "License :: OSI Approved :: MIT License", ] @@ -173,7 +173,7 @@ testpaths = ["tests/"] [tool.tox] requires = ["tox>=4.22"] -env_list = ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] +env_list = ["3.10", "3.11", "3.12", "3.13", "3.14"] [tool.tox.env_run_base] description = "Run tests suite against Python {base_python}" From f1fd29fa4e7b74383b6d240396bb297d0b8aa278 Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Sun, 16 Nov 2025 10:46:48 +0800 Subject: [PATCH 136/221] style: remove Python 3.9 compatible code --- commitizen/changelog_formats/__init__.py | 11 ++++------- commitizen/cz/__init__.py | 9 ++------- commitizen/cz/base.py | 4 ++-- commitizen/providers/__init__.py | 8 ++------ commitizen/question.py | 5 +++-- commitizen/version_schemes.py | 14 +++----------- tests/test_factory.py | 6 +----- tests/test_version_schemes.py | 8 +------- 8 files changed, 18 insertions(+), 47 deletions(-) diff --git a/commitizen/changelog_formats/__init__.py b/commitizen/changelog_formats/__init__.py index e4eb5e0a59..018aa3b329 100644 --- a/commitizen/changelog_formats/__init__.py +++ b/commitizen/changelog_formats/__init__.py @@ -1,16 +1,13 @@ from __future__ import annotations -import sys -from typing import TYPE_CHECKING, Callable, ClassVar, Protocol - -if sys.version_info >= (3, 10): - from importlib import metadata -else: - import importlib_metadata as metadata +from importlib import metadata +from typing import TYPE_CHECKING, ClassVar, Protocol from commitizen.exceptions import ChangelogFormatUnknown if TYPE_CHECKING: + from collections.abc import Callable + from commitizen.changelog import Metadata from commitizen.config.base_config import BaseConfig diff --git a/commitizen/cz/__init__.py b/commitizen/cz/__init__.py index 58753036ff..6b7c1c887a 100644 --- a/commitizen/cz/__init__.py +++ b/commitizen/cz/__init__.py @@ -2,14 +2,9 @@ import importlib import pkgutil -import sys import warnings - -if sys.version_info >= (3, 10): - from importlib import metadata -else: - import importlib_metadata as metadata - +from collections.abc import Iterable +from importlib import metadata from typing import TYPE_CHECKING if TYPE_CHECKING: diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index 249b21515a..90633c42e6 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -2,7 +2,7 @@ from abc import ABCMeta, abstractmethod from collections.abc import Iterable, Mapping -from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Protocol +from typing import TYPE_CHECKING, Any, NamedTuple, Protocol from jinja2 import BaseLoader, PackageLoader from prompt_toolkit.styles import Style @@ -11,7 +11,7 @@ if TYPE_CHECKING: import re - from collections.abc import Iterable, Mapping + from collections.abc import Callable, Iterable, Mapping from commitizen import git from commitizen.config.base_config import BaseConfig diff --git a/commitizen/providers/__init__.py b/commitizen/providers/__init__.py index 4cef578ab9..6bec8f1567 100644 --- a/commitizen/providers/__init__.py +++ b/commitizen/providers/__init__.py @@ -1,13 +1,9 @@ from __future__ import annotations -import sys +from importlib import metadata from typing import TYPE_CHECKING, cast -if sys.version_info >= (3, 10): - from importlib import metadata -else: - import importlib_metadata as metadata - +from commitizen.config.base_config import BaseConfig from commitizen.exceptions import VersionProviderUnknown from commitizen.providers.cargo_provider import CargoProvider from commitizen.providers.commitizen_provider import CommitizenProvider diff --git a/commitizen/question.py b/commitizen/question.py index 393e386092..043b8f3ba3 100644 --- a/commitizen/question.py +++ b/commitizen/question.py @@ -1,4 +1,5 @@ -from typing import Callable, Literal, TypedDict, Union +from collections.abc import Callable +from typing import Literal, TypedDict class Choice(TypedDict, total=False): @@ -29,4 +30,4 @@ class ConfirmQuestion(TypedDict): default: bool -CzQuestion = Union[ListQuestion, InputQuestion, ConfirmQuestion] +CzQuestion = ListQuestion | InputQuestion | ConfirmQuestion diff --git a/commitizen/version_schemes.py b/commitizen/version_schemes.py index 0c71bb06cc..c03d908aab 100644 --- a/commitizen/version_schemes.py +++ b/commitizen/version_schemes.py @@ -1,8 +1,8 @@ from __future__ import annotations import re -import sys import warnings +from importlib import metadata from itertools import zip_longest from typing import ( TYPE_CHECKING, @@ -14,11 +14,6 @@ runtime_checkable, ) -if sys.version_info >= (3, 10): - from importlib import metadata -else: - import importlib_metadata as metadata - from packaging.version import InvalidVersion # noqa: F401 (expose the common exception) from packaging.version import Version as _BaseVersion @@ -26,11 +21,8 @@ from commitizen.exceptions import VersionSchemeUnknown if TYPE_CHECKING: - # TypeAlias is Python 3.10+ but backported in typing-extensions - if sys.version_info >= (3, 10): - from typing import TypeAlias - else: - from typing_extensions import TypeAlias + import sys + from typing import TypeAlias # Self is Python 3.11+ but backported in typing-extensions if sys.version_info < (3, 11): diff --git a/tests/test_factory.py b/tests/test_factory.py index d81a84b3d5..20ce49d781 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -1,11 +1,7 @@ import sys +from importlib import metadata from textwrap import dedent -if sys.version_info >= (3, 10): - from importlib import metadata -else: - import importlib_metadata as metadata - import pytest from commitizen import BaseCommitizen, defaults, factory diff --git a/tests/test_version_schemes.py b/tests/test_version_schemes.py index afaae76188..d51c8eeb2f 100644 --- a/tests/test_version_schemes.py +++ b/tests/test_version_schemes.py @@ -1,12 +1,6 @@ from __future__ import annotations -import sys - -if sys.version_info >= (3, 10): - from importlib import metadata -else: - import importlib_metadata as metadata - +from importlib import metadata from typing import TYPE_CHECKING import pytest From b3944257925d2728a51935fc214263989e8d294d Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 13 Dec 2025 11:02:44 +0800 Subject: [PATCH 137/221] test(commands): centralize all --help tests in a file to dedup code --- tests/commands/test_bump_command.py | 15 +--- tests/commands/test_changelog_command.py | 14 ---- tests/commands/test_check_command.py | 15 +--- tests/commands/test_commit_command.py | 17 +---- tests/commands/test_common_command.py | 69 +++++++++++++++++++ ...escription_when_use_help_option_bump_.txt} | 0 ...ption_when_use_help_option_changelog_.txt} | 0 ...scription_when_use_help_option_check_.txt} | 0 ...cription_when_use_help_option_commit_.txt} | 0 ...ription_when_use_help_option_example_.txt} | 0 ...escription_when_use_help_option_info_.txt} | 0 ...escription_when_use_help_option_init_.txt} | 0 ..._description_when_use_help_option_ls_.txt} | 0 ...cription_when_use_help_option_schema_.txt} | 0 ...ription_when_use_help_option_version_.txt} | 0 tests/commands/test_example_command.py | 26 ------- tests/commands/test_info_command.py | 26 ------- tests/commands/test_init_command.py | 17 +---- tests/commands/test_ls_command.py | 26 ------- tests/commands/test_schema_command.py | 26 ------- tests/commands/test_version_command.py | 29 +------- tests/utils.py | 12 ---- 22 files changed, 74 insertions(+), 218 deletions(-) create mode 100644 tests/commands/test_common_command.py rename tests/commands/{test_bump_command/test_bump_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_bump_.txt} (100%) rename tests/commands/{test_changelog_command/test_changelog_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_changelog_.txt} (100%) rename tests/commands/{test_check_command/test_check_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_check_.txt} (100%) rename tests/commands/{test_commit_command/test_commit_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_commit_.txt} (100%) rename tests/commands/{test_example_command/test_example_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_example_.txt} (100%) rename tests/commands/{test_info_command/test_info_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_info_.txt} (100%) rename tests/commands/{test_init_command/test_init_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_init_.txt} (100%) rename tests/commands/{test_ls_command/test_ls_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_ls_.txt} (100%) rename tests/commands/{test_schema_command/test_schema_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_schema_.txt} (100%) rename tests/commands/{test_version_command/test_version_command_shows_description_when_use_help_option.txt => test_common_command/test_command_shows_description_when_use_help_option_version_.txt} (100%) delete mode 100644 tests/commands/test_example_command.py delete mode 100644 tests/commands/test_info_command.py delete mode 100644 tests/commands/test_ls_command.py delete mode 100644 tests/commands/test_schema_command.py diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index 8dbe8f447e..d8cac56f75 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -28,7 +28,7 @@ NotAllowed, NoVersionSpecifiedError, ) -from tests.utils import create_file_and_commit, create_tag, skip_below_py_3_13 +from tests.utils import create_file_and_commit, create_tag if TYPE_CHECKING: import py @@ -1438,19 +1438,6 @@ def test_bump_changelog_contains_increment_only(mocker, tmp_commitizen_project, assert "2.0.0" not in out -@skip_below_py_3_13 -def test_bump_command_shows_description_when_use_help_option( - mocker: MockFixture, capsys, file_regression -): - testargs = ["cz", "bump", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") - - @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_get_next(mocker: MockFixture, capsys): create_file_and_commit("feat: new file") diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index f2e2ecbd38..17594eaa53 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -30,7 +30,6 @@ create_tag, get_current_branch, merge_branch, - skip_below_py_3_13, switch_branch, wait_for_tag, ) @@ -1927,16 +1926,3 @@ class FakeTemplate: assert not target.exists() assert "Template filename is not set" in str(exc_info.value) - - -@skip_below_py_3_13 -def test_changelog_command_shows_description_when_use_help_option( - mocker: MockFixture, capsys, file_regression -): - testargs = ["cz", "changelog", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index d545dbb18e..47dd3fe12c 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -15,7 +15,7 @@ InvalidCommitMessageError, NoCommitsFoundError, ) -from tests.utils import create_file_and_commit, skip_below_py_3_13 +from tests.utils import create_file_and_commit if TYPE_CHECKING: import re @@ -427,19 +427,6 @@ def test_check_conventional_commit_succeed_with_git_diff(mocker, capsys): assert "Commit validation: successful!" in out -@skip_below_py_3_13 -def test_check_command_shows_description_when_use_help_option( - mocker: MockFixture, capsys, file_regression -): - testargs = ["cz", "check", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") - - def test_check_command_with_message_length_limit(config, mocker: MockFixture): success_mock = mocker.patch("commitizen.out.success") message = "fix(scope): some commit message" diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index 3e408576fe..c987f4b3f3 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -1,11 +1,10 @@ import os -import sys from unittest.mock import ANY import pytest from pytest_mock import MockFixture -from commitizen import cli, cmd, commands +from commitizen import cmd, commands from commitizen.cz.exceptions import CzException from commitizen.cz.utils import get_backup_file_path from commitizen.exceptions import ( @@ -19,7 +18,6 @@ NotAllowed, NothingToCommitError, ) -from tests.utils import skip_below_py_3_13 @pytest.fixture @@ -512,19 +510,6 @@ def test_manual_edit(editor, config, mocker: MockFixture, tmp_path): assert edited_message == test_message.strip() -@skip_below_py_3_13 -def test_commit_command_shows_description_when_use_help_option( - mocker: MockFixture, capsys, file_regression -): - testargs = ["cz", "commit", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") - - @pytest.mark.usefixtures("staging_is_clean") @pytest.mark.parametrize( "out", ["no changes added to commit", "nothing added to commit"] diff --git a/tests/commands/test_common_command.py b/tests/commands/test_common_command.py new file mode 100644 index 0000000000..71ade5eda4 --- /dev/null +++ b/tests/commands/test_common_command.py @@ -0,0 +1,69 @@ +import sys + +import pytest +from pytest_mock import MockFixture + +from commitizen import cli +from commitizen.commands import Example, Info, ListCz, Schema + + +@pytest.mark.skipif( + sys.version_info < (3, 13), + reason="The output message of argparse is different between Python 3.13 and lower than Python 3.13", +) +@pytest.mark.parametrize( + "command", + [ + "bump", + "changelog", + "check", + "commit", + "example", + "info", + "init", + "ls", + "schema", + "version", + ], +) +def test_command_shows_description_when_use_help_option( + mocker: MockFixture, + capsys, + file_regression, + monkeypatch: pytest.MonkeyPatch, + command: str, +): + """Test that the command shows the description when the help option is used. + + Note: If the command description changes, please run `pytest tests/commands/test_common_command.py --regen-all` to regenerate the test files. + """ + # Force consistent terminal output + monkeypatch.setenv("COLUMNS", "80") + monkeypatch.setenv("TERM", "dumb") + monkeypatch.setenv("LC_ALL", "C") + monkeypatch.setenv("LANG", "C") + monkeypatch.setenv("NO_COLOR", "1") + monkeypatch.setenv("PAGER", "cat") + + testargs = ["cz", command, "--help"] + mocker.patch.object(sys, "argv", testargs) + with pytest.raises(SystemExit): + cli.main() + + out, _ = capsys.readouterr() + file_regression.check(out, extension=".txt") + + +@pytest.mark.parametrize( + "command", + [ + Example, + Info, + ListCz, + Schema, + ], +) +def test_simple_command_call_once(config, mocker: MockFixture, command): + write_mock = mocker.patch("commitizen.out.write") + command(config)() + write_mock.assert_called_once() diff --git a/tests/commands/test_bump_command/test_bump_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_bump_.txt similarity index 100% rename from tests/commands/test_bump_command/test_bump_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_bump_.txt diff --git a/tests/commands/test_changelog_command/test_changelog_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_changelog_.txt similarity index 100% rename from tests/commands/test_changelog_command/test_changelog_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_changelog_.txt diff --git a/tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_check_.txt similarity index 100% rename from tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_check_.txt diff --git a/tests/commands/test_commit_command/test_commit_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_commit_.txt similarity index 100% rename from tests/commands/test_commit_command/test_commit_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_commit_.txt diff --git a/tests/commands/test_example_command/test_example_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_example_.txt similarity index 100% rename from tests/commands/test_example_command/test_example_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_example_.txt diff --git a/tests/commands/test_info_command/test_info_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_info_.txt similarity index 100% rename from tests/commands/test_info_command/test_info_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_info_.txt diff --git a/tests/commands/test_init_command/test_init_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_init_.txt similarity index 100% rename from tests/commands/test_init_command/test_init_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_init_.txt diff --git a/tests/commands/test_ls_command/test_ls_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_ls_.txt similarity index 100% rename from tests/commands/test_ls_command/test_ls_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_ls_.txt diff --git a/tests/commands/test_schema_command/test_schema_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_schema_.txt similarity index 100% rename from tests/commands/test_schema_command/test_schema_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_schema_.txt diff --git a/tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_version_.txt similarity index 100% rename from tests/commands/test_version_command/test_version_command_shows_description_when_use_help_option.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_version_.txt diff --git a/tests/commands/test_example_command.py b/tests/commands/test_example_command.py deleted file mode 100644 index 0521679f1c..0000000000 --- a/tests/commands/test_example_command.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys - -import pytest -from pytest_mock import MockerFixture - -from commitizen import cli, commands -from tests.utils import skip_below_py_3_10 - - -def test_example(config, mocker: MockerFixture): - write_mock = mocker.patch("commitizen.out.write") - commands.Example(config)() - write_mock.assert_called_once() - - -@skip_below_py_3_10 -def test_example_command_shows_description_when_use_help_option( - mocker: MockerFixture, capsys, file_regression -): - testargs = ["cz", "example", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") diff --git a/tests/commands/test_info_command.py b/tests/commands/test_info_command.py deleted file mode 100644 index 2bd1553679..0000000000 --- a/tests/commands/test_info_command.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys - -import pytest -from pytest_mock import MockerFixture - -from commitizen import cli, commands -from tests.utils import skip_below_py_3_10 - - -def test_info(config, mocker: MockerFixture): - write_mock = mocker.patch("commitizen.out.write") - commands.Info(config)() - write_mock.assert_called_once() - - -@skip_below_py_3_10 -def test_info_command_shows_description_when_use_help_option( - mocker: MockerFixture, capsys, file_regression -): - testargs = ["cz", "info", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 54fa271fd9..e766524139 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -2,17 +2,15 @@ import json import os -import sys from pathlib import Path from typing import TYPE_CHECKING, Any import pytest import yaml -from commitizen import cli, cmd, commands +from commitizen import cmd, commands from commitizen.__version__ import __version__ from commitizen.exceptions import InitFailedError, NoAnswersError -from tests.utils import skip_below_py_3_10 if TYPE_CHECKING: from pytest_mock import MockFixture @@ -275,19 +273,6 @@ def test_empty_input_returns_default(self, mocker: MockFixture, config: BaseConf assert result == "$version" # This is the default format from DEFAULT_SETTINGS -@skip_below_py_3_10 -def test_init_command_shows_description_when_use_help_option( - mocker: MockFixture, capsys, file_regression -): - testargs = ["cz", "init", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") - - def test_init_with_confirmed_tag_format( config: BaseConfig, mocker: MockFixture, tmpdir ): diff --git a/tests/commands/test_ls_command.py b/tests/commands/test_ls_command.py deleted file mode 100644 index 7225d2a85c..0000000000 --- a/tests/commands/test_ls_command.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys - -import pytest -from pytest_mock import MockerFixture - -from commitizen import cli, commands -from tests.utils import skip_below_py_3_10 - - -def test_list_cz(config, mocker: MockerFixture): - write_mock = mocker.patch("commitizen.out.write") - commands.ListCz(config)() - write_mock.assert_called_once() - - -@skip_below_py_3_10 -def test_ls_command_shows_description_when_use_help_option( - mocker: MockerFixture, capsys, file_regression -): - testargs = ["cz", "ls", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") diff --git a/tests/commands/test_schema_command.py b/tests/commands/test_schema_command.py deleted file mode 100644 index 5e571721c5..0000000000 --- a/tests/commands/test_schema_command.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys - -import pytest -from pytest_mock import MockerFixture - -from commitizen import cli, commands -from tests.utils import skip_below_py_3_10 - - -def test_schema(config, mocker: MockerFixture): - write_mock = mocker.patch("commitizen.out.write") - commands.Schema(config)() - write_mock.assert_called_once() - - -@skip_below_py_3_10 -def test_schema_command_shows_description_when_use_help_option( - mocker: MockerFixture, capsys, file_regression -): - testargs = ["cz", "schema", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index a5faf4e16d..17f7238403 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -1,14 +1,12 @@ -import os import platform import sys import pytest from pytest_mock import MockerFixture -from commitizen import cli, commands +from commitizen import commands from commitizen.__version__ import __version__ from commitizen.config.base_config import BaseConfig -from tests.utils import skip_below_py_3_10 def test_version_for_showing_project_version_error(config, capsys): @@ -105,31 +103,6 @@ def test_version_use_version_provider( mock.set_version.assert_not_called() -@skip_below_py_3_10 -def test_version_command_shows_description_when_use_help_option( - mocker: MockerFixture, capsys, file_regression -): - # Force consistent terminal width for tests to avoid wrapping differences - # between single and multi-worker pytest modes - original_columns = os.environ.get("COLUMNS") - os.environ["COLUMNS"] = "80" - - try: - testargs = ["cz", "version", "--help"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(SystemExit): - cli.main() - - out, _ = capsys.readouterr() - file_regression.check(out, extension=".txt") - finally: - # Restore original COLUMNS - if original_columns is not None: - os.environ["COLUMNS"] = original_columns - else: - os.environ.pop("COLUMNS", None) - - @pytest.mark.parametrize( "version, expected_version", [ diff --git a/tests/utils.py b/tests/utils.py index bea7f20a1d..f5557f76d6 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,12 +1,10 @@ from __future__ import annotations -import sys import time import uuid from pathlib import Path from typing import TYPE_CHECKING, NamedTuple -import pytest from deprecated import deprecated from commitizen import cmd, exceptions, git @@ -14,16 +12,6 @@ if TYPE_CHECKING: from commitizen.version_schemes import Increment, Prerelease -skip_below_py_3_10 = pytest.mark.skipif( - sys.version_info < (3, 10), - reason="The output message of argparse is different between Python 3.10 and lower than Python 3.10", -) - -skip_below_py_3_13 = pytest.mark.skipif( - sys.version_info < (3, 13), - reason="The output message of argparse is different between Python 3.13 and lower than Python 3.13", -) - class VersionSchemeTestArgs(NamedTuple): current_version: str From 392a65479c5a16cff5fa4197c78ad8b9c5e537d2 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Sun, 21 Dec 2025 19:32:26 +0100 Subject: [PATCH 138/221] build(tox): do not use poetry anymore and use the builtin `dependency-group` support --- pyproject.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 120bd2792d..214dfb864b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -177,9 +177,7 @@ env_list = ["3.10", "3.11", "3.12", "3.13", "3.14"] [tool.tox.env_run_base] description = "Run tests suite against Python {base_python}" -skip_install = true -deps = ["poetry>=2.0"] -commands_pre = [["poetry", "install", "--only", "main,test"]] +dependency_groups = ["test"] commands = [["pytest", { replace = "posargs", extend = true }]] [tool.ruff] From 11467ced15e06e7c22de90b05206bdbe48950a40 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Sun, 28 Dec 2025 03:48:09 +0100 Subject: [PATCH 139/221] test(tox): ensure all tests can run from any directory --- poetry.lock | 15 ++++++ pyproject.toml | 1 + tests/conftest.py | 46 +++++++++--------- tests/{ => data}/CHANGELOG_FOR_TEST.md | 0 tests/test_bump_update_version_in_files.py | 55 ++++++++++------------ tests/test_changelog.py | 7 +-- tests/test_conf.py | 1 + tests/test_git.py | 31 +++++------- 8 files changed, 83 insertions(+), 73 deletions(-) rename tests/{ => data}/CHANGELOG_FOR_TEST.md (100%) diff --git a/poetry.lock b/poetry.lock index 72cafcd565..bc6a9d27f9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1414,6 +1414,21 @@ files = [ freezegun = ">=1.1" pytest = ">=3.6" +[[package]] +name = "pytest-gitconfig" +version = "0.9.0" +description = "Provide a Git config sandbox for testing" +optional = false +python-versions = ">=3.10" +groups = ["test"] +files = [ + {file = "pytest_gitconfig-0.9.0-py3-none-any.whl", hash = "sha256:3d855a9dd5fb3906010dbb1f8161366d4d86b34df8c14021fa012f23de3e5354"}, + {file = "pytest_gitconfig-0.9.0.tar.gz", hash = "sha256:5f9e8a29b4a8e55ddd740216ddb0a8a5e97f1c9c7f6bfdac91863473a8c60f9c"}, +] + +[package.dependencies] +pytest = ">=7.1.2" + [[package]] name = "pytest-mock" version = "3.15.1" diff --git a/pyproject.toml b/pyproject.toml index 214dfb864b..bf78009969 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,6 +95,7 @@ test = [ "pytest-regressions>=2.4.0", "pytest-freezer>=0.4.6", "pytest-xdist>=3.1.0", + "pytest-gitconfig>=0.9.0", ] linters = [ diff --git a/tests/conftest.py b/tests/conftest.py index 5eaa17440a..dc68da555a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ import os import re import tempfile +from pathlib import Path from typing import TYPE_CHECKING import pytest @@ -15,45 +16,46 @@ from commitizen.config import BaseConfig from commitizen.cz import registry from commitizen.cz.base import BaseCommitizen +from tests.utils import create_file_and_commit if TYPE_CHECKING: from collections.abc import Iterator, Mapping - from pathlib import Path from pytest_mock import MockerFixture from commitizen.question import CzQuestion -from tests.utils import create_file_and_commit + SIGNER = "GitHub Action" SIGNER_MAIL = "action@github.com" -@pytest.fixture(autouse=True) -def git_sandbox(monkeypatch: pytest.MonkeyPatch, tmp_path: Path): - """Ensure git commands are executed without the current user settings""" - # Clear any GIT_ prefixed environment variable - for var in os.environ: - if var.startswith("GIT_"): - monkeypatch.delenv(var) +@pytest.fixture +def repo_root() -> Path: + return Path(__file__).parent.parent + - # Define a dedicated temporary git config - gitconfig = tmp_path / ".git" / "config" - if not gitconfig.parent.exists(): - gitconfig.parent.mkdir() +@pytest.fixture +def in_repo_root(repo_root: Path) -> Iterator[Path]: + cwd = os.getcwd() + os.chdir(repo_root) + yield repo_root + os.chdir(cwd) - monkeypatch.setenv("GIT_CONFIG_GLOBAL", str(gitconfig)) - r = cmd.run(f"git config --file {gitconfig} user.name {SIGNER}") - assert r.return_code == 0, r.err - r = cmd.run(f"git config --file {gitconfig} user.email {SIGNER_MAIL}") - assert r.return_code == 0, r.err +@pytest.fixture +def data_dir(repo_root: Path) -> Path: + return repo_root / "tests" / "data" - r = cmd.run(f"git config --file {gitconfig} safe.directory '*'") - assert r.return_code == 0, r.err - r = cmd.run("git config --global init.defaultBranch master") - assert r.return_code == 0, r.err +@pytest.fixture(scope="session") +def set_default_gitconfig() -> dict[str, str]: + return { + "user.name": "SIGNER", + "user.email": SIGNER_MAIL, + "safe.cirectory": "*", + "init.defaultBranch": "master", + } @pytest.fixture diff --git a/tests/CHANGELOG_FOR_TEST.md b/tests/data/CHANGELOG_FOR_TEST.md similarity index 100% rename from tests/CHANGELOG_FOR_TEST.md rename to tests/data/CHANGELOG_FOR_TEST.md diff --git a/tests/test_bump_update_version_in_files.py b/tests/test_bump_update_version_in_files.py index 9d53a3e81d..5fb812f19f 100644 --- a/tests/test_bump_update_version_in_files.py +++ b/tests/test_bump_update_version_in_files.py @@ -1,5 +1,7 @@ +from collections.abc import Callable from pathlib import Path from shutil import copyfile +from typing import TypeAlias import pytest from _pytest.fixtures import FixtureRequest @@ -10,53 +12,48 @@ MULTIPLE_VERSIONS_INCREASE_STRING = 'version = "1.2.9"\n' * 30 MULTIPLE_VERSIONS_REDUCE_STRING = 'version = "1.2.10"\n' * 30 -TESTING_FILE_PREFIX = "tests/data" +SampleFileFixture: TypeAlias = Callable[[str, str], Path] -def _copy_sample_file_to_tmpdir( - tmp_path: Path, source_filename: str, dest_filename: str -) -> Path: - tmp_file = tmp_path / dest_filename - copyfile(f"{TESTING_FILE_PREFIX}/{source_filename}", tmp_file) - return tmp_file + +@pytest.fixture +def sample_file(tmp_path: Path, data_dir: Path) -> SampleFileFixture: + def fixture(source: str, destination: str) -> Path: + tmp_file = tmp_path / destination + copyfile(data_dir / source, tmp_file) + return tmp_file + + return fixture @pytest.fixture(scope="function") -def commitizen_config_file(tmp_path: Path) -> Path: - return _copy_sample_file_to_tmpdir( - tmp_path, "sample_pyproject.toml", "pyproject.toml" - ) +def commitizen_config_file(sample_file: SampleFileFixture) -> Path: + return sample_file("sample_pyproject.toml", "pyproject.toml") @pytest.fixture(scope="function") -def python_version_file(tmp_path: Path, request: FixtureRequest) -> Path: - return _copy_sample_file_to_tmpdir(tmp_path, "sample_version.py", "__version__.py") +def python_version_file(sample_file: SampleFileFixture) -> Path: + return sample_file("sample_version.py", "__version__.py") @pytest.fixture(scope="function") -def inconsistent_python_version_file(tmp_path: Path) -> Path: - return _copy_sample_file_to_tmpdir( - tmp_path, "inconsistent_version.py", "__version__.py" - ) +def inconsistent_python_version_file(sample_file: SampleFileFixture) -> Path: + return sample_file("inconsistent_version.py", "__version__.py") @pytest.fixture(scope="function") -def random_location_version_file(tmp_path: Path) -> Path: - return _copy_sample_file_to_tmpdir(tmp_path, "sample_cargo.lock", "Cargo.lock") +def random_location_version_file(sample_file: SampleFileFixture) -> Path: + return sample_file("sample_cargo.lock", "Cargo.lock") @pytest.fixture(scope="function") -def version_repeated_file(tmp_path: Path) -> Path: - return _copy_sample_file_to_tmpdir( - tmp_path, "repeated_version_number.json", "package.json" - ) +def version_repeated_file(sample_file: SampleFileFixture) -> Path: + return sample_file("repeated_version_number.json", "package.json") @pytest.fixture(scope="function") -def docker_compose_file(tmp_path: Path) -> Path: - return _copy_sample_file_to_tmpdir( - tmp_path, "sample_docker_compose.yaml", "docker-compose.yaml" - ) +def docker_compose_file(sample_file: SampleFileFixture) -> Path: + return sample_file("sample_docker_compose.yaml", "docker-compose.yaml") @pytest.fixture( @@ -68,9 +65,9 @@ def docker_compose_file(tmp_path: Path) -> Path: ids=("with_eol", "without_eol"), ) def multiple_versions_to_update_poetry_lock( - tmp_path: Path, request: FixtureRequest + sample_file: SampleFileFixture, request: FixtureRequest ) -> Path: - return _copy_sample_file_to_tmpdir(tmp_path, request.param, "pyproject.toml") + return sample_file(request.param, "pyproject.toml") @pytest.fixture(scope="function") diff --git a/tests/test_changelog.py b/tests/test_changelog.py index e32a9bcf9e..bcf90b11da 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -578,9 +578,9 @@ def tags() -> list[git.GitTag]: @pytest.fixture -def changelog_content() -> str: - changelog_path = "tests/CHANGELOG_FOR_TEST.md" - with open(changelog_path, encoding="utf-8") as f: +def changelog_content(data_dir: Path) -> str: + changelog = data_dir / "CHANGELOG_FOR_TEST.md" + with changelog.open(encoding="utf-8") as f: return f.read() @@ -1657,6 +1657,7 @@ def test_tags_rules_get_version_tags(capsys: pytest.CaptureFixture): assert captured.err.count("not-a-version") == 2 +@pytest.mark.usefixtures("in_repo_root") def test_changelog_file_name_from_args_and_config(): mock_config = Mock(spec=BaseConfig) mock_path = Mock(spec=Path) diff --git a/tests/test_conf.py b/tests/test_conf.py index bbbed41e08..0df0d18647 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -164,6 +164,7 @@ def config_files_manager(request, tmpdir): yield +@pytest.mark.usefixtures("in_repo_root") def test_find_git_project_root(tmpdir): assert git.find_git_project_root() == Path(os.getcwd()) diff --git a/tests/test_git.py b/tests/test_git.py index 45e6028c9e..12c0e2ad82 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -3,7 +3,6 @@ import inspect import os import platform -import shutil from typing import TYPE_CHECKING import pytest @@ -19,6 +18,7 @@ ) if TYPE_CHECKING: + from pytest_gitconfig import GitConfig from pytest_mock import MockFixture @@ -260,25 +260,18 @@ def test_get_commits_with_and_without_parents(mocker: MockFixture): assert commits[2].parents == [] -def test_get_commits_with_signature(): - config_file = ".git/config" - config_backup = ".git/config.bak" - shutil.copy(config_file, config_backup) +@pytest.mark.usefixtures("in_repo_root") +def test_get_commits_with_signature(gitconfig: GitConfig): + # temporarily turn on --show-signature + gitconfig.set("log.showsignature", "true") - try: - # temporarily turn on --show-signature - cmd.run("git config log.showsignature true") - - # retrieve a commit that we know has a signature - commit = git.get_commits( - start="bec20ebf433f2281c70f1eb4b0b6a1d0ed83e9b2", - end="9eae518235d051f145807ddf971ceb79ad49953a", - )[0] - - assert commit.title.startswith("fix") - finally: - # restore the repo's original config - shutil.move(config_backup, config_file) + # retrieve a commit that we know has a signature + commit = git.get_commits( + start="bec20ebf433f2281c70f1eb4b0b6a1d0ed83e9b2", + end="9eae518235d051f145807ddf971ceb79ad49953a", + )[0] + + assert commit.title.startswith("fix") def test_get_tag_names_has_correct_arrow_annotation(): From cf03c8d5731387979d33bb5ff7af5dd311237e39 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 11:26:11 +0000 Subject: [PATCH 140/221] =?UTF-8?q?bump:=20version=204.10.1=20=E2=86=92=20?= =?UTF-8?q?4.11.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 7 +++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f70fbf2f10..2c9f437c91 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,7 +48,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.10.1 # automatically updated by Commitizen + rev: v4.11.0 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ee748085f..7cf5f7a090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## v4.11.0 (2025-12-29) + +### Feat + +- Drop support for Python 3.9 as EOL reached and add Python 3.14 support +- add custom validation + ## v4.10.1 (2025-12-11) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 4e499ea83a..bdb8bda6ae 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.10.1" +__version__ = "4.11.0" diff --git a/pyproject.toml b/pyproject.toml index bf78009969..7b5c5d35a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.10.1" +version = "4.11.0" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -122,7 +122,7 @@ build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "4.10.1" +version = "4.11.0" tag_format = "v$version" version_files = [ "pyproject.toml:version", From 98321b139ae6c7d555e8adb2ca2267b6fa1decc9 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Mon, 29 Dec 2025 20:54:29 +0800 Subject: [PATCH 141/221] ci: fix the issue lychee.toml was not consumed correctly --- .github/workflows/links.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index b1d643217f..ac8336a86b 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -19,6 +19,7 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v2 with: + args: --config lychee.toml . fail: false - name: Broken Links Report From 8c2bd6d2bf5508de14a29cb2ae1f088e29bb447a Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Mon, 29 Dec 2025 20:40:55 +0800 Subject: [PATCH 142/221] docs: remove incorrectedly reverted deleted content --- docs/customization.md | 596 ------------------------------------------ 1 file changed, 596 deletions(-) delete mode 100644 docs/customization.md diff --git a/docs/customization.md b/docs/customization.md deleted file mode 100644 index 93d85460f3..0000000000 --- a/docs/customization.md +++ /dev/null @@ -1,596 +0,0 @@ -Customizing Commitizen is not hard at all. -We have two different ways to do so. - -## 1. Customize in configuration file - -The basic steps are: - -1. Define your custom committing or bumping rules in the configuration file. -2. Declare `name = "cz_customize"` in your configuration file, or add `-n cz_customize` when running Commitizen. - -Example: - -```toml title="pyproject.toml" -[tool.commitizen] -name = "cz_customize" - -[tool.commitizen.customize] -message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}" -example = "feature: this feature enable customize through config file" -schema = "<type>: <body>" -schema_pattern = "(feature|bug fix):(\\s.*)" -bump_pattern = "^(break|new|fix|hotfix)" -bump_map = {"break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH"} -change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"] -info_path = "cz_customize_info.txt" -info = """ -This is customized info -""" -commit_parser = "^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?" -changelog_pattern = "^(feature|bug fix)?(!)?" -change_type_map = {"feature" = "Feat", "bug fix" = "Fix"} - -[[tool.commitizen.customize.questions]] -type = "list" -name = "change_type" -choices = [{value = "feature", name = "feature: A new feature."}, {value = "bug fix", name = "bug fix: A bug fix."}] -# choices = ["feature", "fix"] # short version -message = "Select the type of change you are committing" - -[[tool.commitizen.customize.questions]] -type = "input" -name = "message" -message = "Body." - -[[tool.commitizen.customize.questions]] -type = "confirm" -name = "show_message" -message = "Do you want to add body message in commit?" -``` - -The equivalent example for a json config file: - -```json title=".cz.json" -{ - "commitizen": { - "name": "cz_customize", - "customize": { - "message_template": "{{change_type}}:{% if show_message %} {{message}}{% endif %}", - "example": "feature: this feature enable customize through config file", - "schema": "<type>: <body>", - "schema_pattern": "(feature|bug fix):(\\s.*)", - "bump_pattern": "^(break|new|fix|hotfix)", - "bump_map": { - "break": "MAJOR", - "new": "MINOR", - "fix": "PATCH", - "hotfix": "PATCH" - }, - "change_type_order": ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"], - "info_path": "cz_customize_info.txt", - "info": "This is customized info", - "commit_parser": "^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?", - "changelog_pattern": "^(feature|bug fix)?(!)?", - "change_type_map": {"feature": "Feat", "bug fix": "Fix"}, - "questions": [ - { - "type": "list", - "name": "change_type", - "choices": [ - { - "value": "feature", - "name": "feature: A new feature." - }, - { - "value": "bug fix", - "name": "bug fix: A bug fix." - } - ], - "message": "Select the type of change you are committing" - }, - { - "type": "input", - "name": "message", - "message": "Body." - }, - { - "type": "confirm", - "name": "show_message", - "message": "Do you want to add body message in commit?" - } - ] - } - } -} -``` - -And the correspondent example for a yaml file: - -```yaml title=".cz.yaml" -commitizen: - name: cz_customize - customize: - message_template: '{{change_type}}:{% if show_message %} {{message}}{% endif %}' - example: 'feature: this feature enable customize through config file' - schema: '<type>: <body>' - schema_pattern: '(feature|bug fix):(\\s.*)' - bump_pattern: '^(break|new|fix|hotfix)' - commit_parser: '^(?P<change_type>feature|bug fix):\\s(?P<message>.*)?' - changelog_pattern: '^(feature|bug fix)?(!)?' - change_type_map: - feature: Feat - bug fix: Fix - bump_map: - break: MAJOR - new: MINOR - fix: PATCH - hotfix: PATCH - change_type_order: ['BREAKING CHANGE', 'feat', 'fix', 'refactor', 'perf'] - info_path: cz_customize_info.txt - info: This is customized info - questions: - - type: list - name: change_type - choices: - - value: feature - name: 'feature: A new feature.' - - value: bug fix - name: 'bug fix: A bug fix.' - message: Select the type of change you are committing - - type: input - name: message - message: 'Body.' - - type: confirm - name: show_message - message: 'Do you want to add body message in commit?' -``` - -### Customize configuration - -| Parameter | Type | Default | Description | -| ------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `questions` | `Questions` | `None` | Questions regarding the commit message. Detailed below. The type `Questions` is an alias to `Iterable[MutableMapping[str, Any]]` which is defined in `commitizen.defaults`. It expects a list of dictionaries. | -| `message_template` | `str` | `None` | The template for generating message from the given answers. `message_template` should either follow [Jinja2][jinja2] formatting specification, and all the variables in this template should be defined in `name` in `questions` | -| `example` | `str` | `""` | (OPTIONAL) Provide an example to help understand the style. Used by `cz example`. | -| `schema` | `str` | `""` | (OPTIONAL) Show the schema used. Used by `cz schema`. | -| `schema_pattern` | `str` | `""` | (OPTIONAL) The regular expression used to do commit message validation. Used by `cz check`. | -| `info_path` | `str` | `""` | (OPTIONAL) The path to the file that contains explanation of the commit rules. Used by `cz info`. If not provided `cz info`, will load `info` instead. | -| `info` | `str` | `""` | (OPTIONAL) Explanation of the commit rules. Used by `cz info`. | -| `bump_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | -| `bump_pattern` | `str` | `None` | (OPTIONAL) Regex to extract information from commit (subject and body) | -| `change_type_order` | `str` | `None` | (OPTIONAL) List of strings used to order the Changelog. All other types will be sorted alphabetically. Default is `["BREAKING CHANGE", "Feat", "Fix", "Refactor", "Perf"]` | -| `commit_parser` | `str` | `None` | (OPTIONAL) Regex to extract information used in creating changelog. [See more][changelog-spec] | -| `changelog_pattern` | `str` | `None` | (OPTIONAL) Regex to understand which commits to include in the changelog | -| `change_type_map` | `dict` | `None` | (OPTIONAL) Dictionary mapping the type of the commit to a changelog entry | - -[jinja2]: https://jinja.palletsprojects.com/en/2.10.x/ -[changelog-spec]: https://commitizen-tools.github.io/commitizen/commands/changelog/ - -#### Detailed `questions` content - -| Parameter | Type | Default | Description | -| ----------- | ------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `type` | `str` | `None` | The type of questions. Valid types: `list`, `select`, `input`, etc. The `select` type provides an interactive searchable list interface. [See More][different-question-types] | -| `name` | `str` | `None` | The key for the value answered by user. It's used in `message_template` | -| `message` | `str` | `None` | Detail description for the question. | -| `choices` | `list` | `None` | (OPTIONAL) The choices when `type = list` or `type = select`. Either use a list of values or a list of dictionaries with `name` and `value` keys. Keyboard shortcuts can be defined via `key`. See examples above. | -| `default` | `Any` | `None` | (OPTIONAL) The default value for this question. | -| `filter` | `str` | `None` | (OPTIONAL) Validator for user's answer. **(Work in Progress)** | -| `multiline` | `bool` | `False` | (OPTIONAL) Enable multiline support when `type = input`. | -| `use_search_filter` | `bool` | `False` | (OPTIONAL) Enable search/filter functionality for list/select type questions. This allows users to type and filter through the choices. | -| `use_jk_keys` | `bool` | `True` | (OPTIONAL) Enable/disable j/k keys for navigation in list/select type questions. Set to false if you prefer arrow keys only. | - -[different-question-types]: https://github.com/tmbo/questionary#different-question-types - -#### Shortcut keys - -When the [`use_shortcuts`](config.md#settings) config option is enabled, Commitizen can show and use keyboard shortcuts to select items from lists directly. -For example, when using the `cz_conventional_commits` Commitizen template, shortcut keys are shown when selecting the commit type. Unless otherwise defined, keyboard shortcuts will be numbered automatically. -To specify keyboard shortcuts for your custom choices, provide the shortcut using the `key` parameter in dictionary form for each choice you would like to customize. - -## 2. Customize through customizing a class - -The basic steps are: - -1. Inheriting from `BaseCommitizen`. -2. Give a name to your rules. -3. Create a python package using `setup.py`, `poetry`, etc. -4. Expose the class as a `commitizen.plugin` entrypoint. - -Check an [example][convcomms] on how to configure `BaseCommitizen`. - -You can also automate the steps above through [cookiecutter](https://cookiecutter.readthedocs.io/en/1.7.0/). - -```sh -cookiecutter gh:commitizen-tools/commitizen_cz_template -``` - -See [commitizen_cz_template](https://github.com/commitizen-tools/commitizen_cz_template) for details. - -Once you publish your rules, you can send us a PR to the [Third-party section](./third-party-commitizen.md). - -### Custom commit rules - -Create a Python module, for example `cz_jira.py`. - -Inherit from `BaseCommitizen`, and you must define `questions` and `message`. The others are optional. - -```python title="cz_jira.py" -from commitizen.cz.base import BaseCommitizen -from commitizen.defaults import Questions - - -class JiraCz(BaseCommitizen): - # Questions = Iterable[MutableMapping[str, Any]] - # It expects a list with dictionaries. - def questions(self) -> Questions: - """Questions regarding the commit message.""" - questions = [ - {"type": "input", "name": "title", "message": "Commit title"}, - {"type": "input", "name": "issue", "message": "Jira Issue number:"}, - ] - return questions - - def message(self, answers: dict) -> str: - """Generate the message with the given answers.""" - return "{0} (#{1})".format(answers["title"], answers["issue"]) - - def example(self) -> str: - """Provide an example to help understand the style (OPTIONAL) - - Used by `cz example`. - """ - return "Problem with user (#321)" - - def schema(self) -> str: - """Show the schema used (OPTIONAL) - - Used by `cz schema`. - """ - return "<title> (<issue>)" - - def info(self) -> str: - """Explanation of the commit rules. (OPTIONAL) - - Used by `cz info`. - """ - return "We use this because is useful" -``` - -The next file required is `setup.py` modified from flask version. - -```python title="setup.py" -from setuptools import setup - -setup( - name="JiraCommitizen", - version="0.1.0", - py_modules=["cz_jira"], - license="MIT", - long_description="this is a long description", - install_requires=["commitizen"], - entry_points={"commitizen.plugin": ["cz_jira = cz_jira:JiraCz"]}, -) -``` - -So in the end, we would have - - . - ├── cz_jira.py - └── setup.py - -And that's it. You can install it without uploading to pypi by simply -doing `pip install .` - -If you feel like it should be part of this repo, create a PR. - -### Custom bump rules - -You need to define 2 parameters inside your custom `BaseCommitizen`. - -| Parameter | Type | Default | Description | -| -------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | -| `bump_pattern` | `str` | `None` | Regex to extract information from commit (subject and body) | -| `bump_map` | `dict` | `None` | Dictionary mapping the extracted information to a `SemVer` increment type (`MAJOR`, `MINOR`, `PATCH`) | - -Let's see an example. - -```python title="cz_strange.py" -from commitizen.cz.base import BaseCommitizen - - -class StrangeCommitizen(BaseCommitizen): - bump_pattern = r"^(break|new|fix|hotfix)" - bump_map = {"break": "MAJOR", "new": "MINOR", "fix": "PATCH", "hotfix": "PATCH"} -``` - -That's it, your Commitizen now supports custom rules, and you can run. - -```bash -cz -n cz_strange bump -``` - -[convcomms]: https://github.com/commitizen-tools/commitizen/blob/master/commitizen/cz/conventional_commits/conventional_commits.py - -### Custom commit validation and error message - -The commit message validation can be customized by overriding the `validate_commit_message` and `format_error_message` -methods from `BaseCommitizen`. This allows for a more detailed feedback to the user where the error originates from. - -```python -import re - -from commitizen.cz.base import BaseCommitizen, ValidationResult -from commitizen import git - - -class CustomValidationCz(BaseCommitizen): - def validate_commit_message( - self, - *, - commit_msg: str, - pattern: str | None, - allow_abort: bool, - allowed_prefixes: list[str], - max_msg_length: int, - ) -> ValidationResult: - """Validate commit message against the pattern.""" - if not commit_msg: - return allow_abort, [] if allow_abort else [f"commit message is empty"] - - if pattern is None: - return True, [] - - if any(map(commit_msg.startswith, allowed_prefixes)): - return True, [] - if max_msg_length: - msg_len = len(commit_msg.partition("\n")[0].strip()) - if msg_len > max_msg_length: - return False, [ - f"commit message is too long. Max length is {max_msg_length}" - ] - pattern_match = re.match(pattern, commit_msg) - if pattern_match: - return True, [] - else: - # Perform additional validation of the commit message format - # and add custom error messages as needed - return False, ["commit message does not match the pattern"] - - def format_exception_message( - self, ill_formated_commits: list[tuple[git.GitCommit, list]] - ) -> str: - """Format commit errors.""" - displayed_msgs_content = "\n".join( - [ - ( - f'commit "{commit.rev}": "{commit.message}"' - f"errors:\n" - "\n".join((f"- {error}" for error in errors)) - ) - for commit, errors in ill_formated_commits - ] - ) - return ( - "commit validation: failed!\n" - "please enter a commit message in the commitizen format.\n" - f"{displayed_msgs_content}\n" - f"pattern: {self.schema_pattern()}" - ) -``` - -### Custom changelog generator - -The changelog generator should just work in a very basic manner without touching anything. -You can customize it of course, and the following variables are the ones you need to add to your custom `BaseCommitizen`. - -| Parameter | Type | Required | Description | -| -------------------------------- | ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `commit_parser` | `str` | NO | Regex which should provide the variables explained in the [changelog description][changelog-des] | -| `changelog_pattern` | `str` | NO | Regex to validate the commits, this is useful to skip commits that don't meet your ruling standards like a Merge. Usually the same as bump_pattern | -| `change_type_map` | `dict` | NO | Convert the title of the change type that will appear in the changelog, if a value is not found, the original will be provided | -| `changelog_message_builder_hook` | `method: (dict, git.GitCommit) -> dict | list | None` | NO | Customize with extra information your message output, like adding links, this function is executed per parsed commit. Each GitCommit contains the following attrs: `rev`, `title`, `body`, `author`, `author_email`. Returning a falsy value ignore the commit. | -| `changelog_hook` | `method: (full_changelog: str, partial_changelog: Optional[str]) -> str` | NO | Receives the whole and partial (if used incremental) changelog. Useful to send slack messages or notify a compliance department. Must return the full_changelog | -| `changelog_release_hook` | `method: (release: dict, tag: git.GitTag) -> dict` | NO | Receives each generated changelog release and its associated tag. Useful to enrich releases before they are rendered. Must return the update release - -```python title="cz_strange.py" -from commitizen.cz.base import BaseCommitizen -import chat -import compliance - - -class StrangeCommitizen(BaseCommitizen): - changelog_pattern = r"^(break|new|fix|hotfix)" - commit_parser = r"^(?P<change_type>feat|fix|refactor|perf|BREAKING CHANGE)(?:\((?P<scope>[^()\r\n]*)\)|\()?(?P<breaking>!)?:\s(?P<message>.*)?" - change_type_map = { - "feat": "Features", - "fix": "Bug Fixes", - "refactor": "Code Refactor", - "perf": "Performance improvements", - } - - def changelog_message_builder_hook( - self, parsed_message: dict, commit: git.GitCommit - ) -> dict | list | None: - rev = commit.rev - m = parsed_message["message"] - parsed_message[ - "message" - ] = f"{m} {rev} [{commit.author}]({commit.author_email})" - return parsed_message - - def changelog_release_hook(self, release: dict, tag: git.GitTag) -> dict: - release["author"] = tag.author - return release - - def changelog_hook( - self, full_changelog: str, partial_changelog: Optional[str] - ) -> str: - """Executed at the end of the changelog generation - - full_changelog: it's the output about to being written into the file - partial_changelog: it's the new stuff, this is useful to send slack messages or - similar - - Return: - the new updated full_changelog - """ - if partial_changelog: - chat.room("#committers").notify(partial_changelog) - if full_changelog: - compliance.send(full_changelog) - full_changelog.replace(" fix ", " **fix** ") - return full_changelog -``` - -### Raise Customize Exception - -If you want `commitizen` to catch your exception and print the message, you'll have to inherit `CzException`. - -```python -from commitizen.cz.exception import CzException - - -class NoSubjectProvidedException(CzException): - ... -``` - -### Migrating from legacy plugin format - -Commitizen migrated to a new plugin format relying on `importlib.metadata.EntryPoint`. -Migration should be straight-forward for legacy plugins: - -- Remove the `discover_this` line from your plugin module -- Expose the plugin class under as a `commitizen.plugin` entrypoint. - -The name of the plugin is now determined by the name of the entrypoint. - -#### Example - -If you were having a `CzPlugin` class in a `cz_plugin.py` module like this: - -```python -from commitizen.cz.base import BaseCommitizen - - -class PluginCz(BaseCommitizen): - ... - - -discover_this = PluginCz -``` - -Then remove the `discover_this` line: - -```python -from commitizen.cz.base import BaseCommitizen - - -class PluginCz(BaseCommitizen): - ... -``` - -and expose the class as entrypoint in you setuptools: - -```python -from setuptools import setup - -setup( - name="MyPlugin", - version="0.1.0", - py_modules=["cz_plugin"], - entry_points={"commitizen.plugin": ["plugin = cz_plugin:PluginCz"]}, - ..., -) -``` - -Then your plugin will be available under the name `plugin`. - -## Customizing the changelog template - -Commitizen gives you the possibility to provide your own changelog template, by: - -- providing one with your customization class -- providing one from the current working directory and setting it: - - as [configuration][template-config] - - as `--template` parameter to both `bump` and `changelog` commands -- either by providing a template with the same name as the default template - -By default, the template used is the `CHANGELOG.md.j2` file from the Commitizen repository. - -### Providing a template with your customization class - -There are 3 parameters available to change the template rendering from your custom `BaseCommitizen`. - -| Parameter | Type | Default | Description | -| ----------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------- | -| `template` | `str` | `None` | Provide your own template name (default to `CHANGELOG.md.j2`) | -| `template_loader` | `str` | `None` | Override the default template loader (so you can provide template from your customization class) | -| `template_extras` | `dict` | `None` | Provide some extra template parameters | - -Let's see an example. - -```python -from commitizen.cz.base import BaseCommitizen -from jinja2 import PackageLoader - - -class MyPlugin(BaseCommitizen): - template = "CHANGELOG.md.jinja" - template_loader = PackageLoader("my_plugin", "templates") - template_extras = {"key": "value"} -``` - -This snippet will: - -- use `CHANGELOG.md.jinja` as template name -- search for it in the `templates` directory for `my_plugin` package -- add the `key=value` variable in the template - -### Providing a template from the current working directory - -Users can provide their own template from their current working directory (your project root) by: - -- providing a template with the same name (`CHANGELOG.md.j2` unless overridden by your custom class) -- setting your template path as `template` configuration -- giving your template path as `--template` parameter to `bump` and `changelog` commands - -!!! note - The path is relative to the current working directory, aka your project root most of the time. - -### Template variables - -The default template use a single `tree` variable which is a list of entries (a release) with the following format: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| version | `str` | The release version | -| date | `datetime` | The release date | -| changes | `list[tuple[str, list[Change]]]` | The release sorted changes list in the form `(type, changes)` | - -Each `Change` has the following fields: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| scope | `str | None` | An optional scope | -| message | `str` | The commit message body | -| sha1 | `str` | The commit `sha1` | -| parents | `list[str]` | The parent commit(s) `sha1`(s) | -| author | `str` | The commit author name | -| author_email | `str` | The commit author email | - -!!! note - The field values depend on the customization class and/or the settings you provide - -The `parents` field can be used to identify merge commits and generate a changelog based on those. Another use case -is listing commits that belong to the same pull request. - -When using another template (either provided by a plugin or by yourself), you can also pass extra template variables -by: - -- defining them in your configuration with the [`extras` settings][extras-config] -- providing them on the command line with the `--extra/-e` parameter to `bump` and `changelog` commands - -[template-config]: config.md#template -[extras-config]: config.md#extras -[changelog-des]: ./commands/changelog.md#description From 6990d51c7e6e04058465b12e8adfb74d371a7b80 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 29 Dec 2025 22:17:39 +0100 Subject: [PATCH 143/221] ci(coverage): restore builds on `master`, fix Codecov coverage report and adds test analytics (fix #1606) --- .github/workflows/pythonpackage.yml | 17 ++++++++++++----- .gitignore | 1 + pyproject.toml | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 7605301822..850cb57c0e 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -1,6 +1,11 @@ name: Python package -on: [workflow_dispatch, pull_request] +on: + push: + branches: + - master + pull_request: + workflow_dispatch: jobs: python-check: @@ -29,10 +34,12 @@ jobs: poetry ci shell: bash - name: Upload coverage to Codecov - if: runner.os == 'Linux' uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - files: ./coverage.xml - flags: unittests - name: codecov-umbrella + - name: Upload test results to Codecov + uses: codecov/codecov-action@v5 + if: ${{ !cancelled() }} + with: + token: ${{ secrets.CODECOV_TOKEN }} + report_type: test_results diff --git a/.gitignore b/.gitignore index be07cf2d93..fb467da46c 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ coverage.xml *.cover .hypothesis/ .pytest_cache +junit.xml # Translations *.mo diff --git a/pyproject.toml b/pyproject.toml index 7b5c5d35a9..76896d3500 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -265,7 +265,7 @@ test.cmd = "pytest -n 3 --dist=loadfile" "test:all".cmd = "tox --parallel" cover.help = "Run the test suite with coverage" -cover.ref = "test --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen" +cover.ref = "test --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen --junitxml=junit.xml -o junit_family=legacy" all.help = "Run all tasks" all.sequence = ["format", "lint", "check-commit", "cover"] From 548621cbf1426c580ad2f015b6befa5cdfd9ed5f Mon Sep 17 00:00:00 2001 From: Yazdan Ranjbar <yazdanra@icloud.com> Date: Tue, 30 Dec 2025 10:06:34 -0500 Subject: [PATCH 144/221] build(uv): switch from `poetry` to `uv` for project management (#1749) Co-authored-by: Wei Lee <weilee.rx@gmail.com> Co-authored-by: Benedikt Ziegler <benediktziegler@gmail.com> --- .github/pull_request_template.md | 6 +- .github/workflows/docspublish.yml | 18 +- .github/workflows/homebrewpublish.yml | 5 +- .github/workflows/pythonpackage.yml | 9 +- .github/workflows/pythonpublish.yml | 13 +- .pre-commit-config.yaml | 16 +- docs/contributing.md | 27 +- docs/contributing_tldr.md | 23 +- poetry.lock | 2136 ------------------------- pyproject.toml | 17 +- uv.lock | 1723 ++++++++++++++++++++ 11 files changed, 1777 insertions(+), 2216 deletions(-) delete mode 100644 poetry.lock create mode 100644 uv.lock diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e37148c0a1..061dce44cb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -14,7 +14,7 @@ Please fill in the following content to let us know better about this change. ### Code Changes - [ ] Add test cases to all the changes you introduce -- [ ] Run `poetry all` locally to ensure this change passes linter check and tests +- [ ] Run `uv run poe all` locally to ensure this change passes linter check and tests - [ ] Manually test the changes: - [ ] Verify the feature/bug fix works as expected in real-world scenarios - [ ] Test edge cases and error conditions @@ -24,10 +24,10 @@ Please fill in the following content to let us know better about this change. ### Documentation Changes -- [ ] Run `poetry doc` locally to ensure the documentation pages renders correctly +- [ ] Run `uv run poe doc` locally to ensure the documentation pages renders correctly - [ ] Check and fix any broken links (internal or external) in the documentation -> When running `poetry doc`, any broken internal documentation links will be reported in the console output like this: +> When running `uv run poe doc`, any broken internal documentation links will be reported in the console output like this: > > ```text > INFO - Doc file 'config.md' contains a link 'commands/bump.md#-post_bump_hooks', but the doc 'commands/bump.md' does not contain an anchor '#-post_bump_hooks'. diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index 0102856cbc..e70da7b9d8 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -15,17 +15,16 @@ jobs: token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v6 + uses: astral-sh/setup-uv@v7 with: python-version: "3.x" - name: Install dependencies run: | - python -m pip install -U pip poetry poethepoet - poetry --version - poetry install --only main,script + uv --version + uv sync --locked --group script - name: Update CLI screenshots run: | - poetry doc:screenshots + uv run poe doc:screenshots - name: Commit and push updated CLI screenshots run: | git config --global user.name "github-actions[bot]" @@ -51,14 +50,13 @@ jobs: run: | git pull origin master - name: Set up Python - uses: actions/setup-python@v6 + uses: astral-sh/setup-uv@v7 with: python-version: "3.x" - name: Install dependencies run: | - python -m pip install -U pip poetry poethepoet - poetry --version - poetry install --no-root --only documentation + uv --version + uv sync --locked --only-group documentation - name: Generate Sponsors 💖 uses: JamesIves/github-sponsors-readme-action@v1 with: @@ -69,7 +67,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - poetry doc:build + uv run poe doc:build - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@v4 with: diff --git a/.github/workflows/homebrewpublish.yml b/.github/workflows/homebrewpublish.yml index 3ca67da811..ae92e28b77 100644 --- a/.github/workflows/homebrewpublish.yml +++ b/.github/workflows/homebrewpublish.yml @@ -14,12 +14,11 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v6 + uses: astral-sh/setup-uv@v7 with: python-version: "3.x" - name: Install dependencies - run: | - python -m pip install -U commitizen + run: uv pip install -U commitizen - name: Set Project version env variable run: | echo "project_version=$(cz version --project)" >> $GITHUB_ENV diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 850cb57c0e..4772e8b5d6 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -19,19 +19,18 @@ jobs: with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + uses: astral-sh/setup-uv@v7 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install -U pip poetry poethepoet - poetry --version - poetry install --only main,linters,test + uv --version + uv sync --locked --dev --group test --group linters - name: Run tests and linters run: | git config --global user.email "action@github.com" git config --global user.name "GitHub Action" - poetry ci + uv run poe ci shell: bash - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index de078815fa..853fc33ccf 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -14,15 +14,10 @@ jobs: token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v6 + uses: astral-sh/setup-uv@v7 with: python-version: "3.x" - - name: Install dependencies - run: | - python -m pip install -U pip poetry - poetry --version + - name: Build + run: uv build - name: Publish - env: - POETRY_HTTP_BASIC_PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} - POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: poetry publish --build + run: uv publish diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c9f437c91..31bc6fb073 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,6 +29,14 @@ repos: args: [ '--unsafe' ] # for mkdocs.yml - id: detect-private-key + - repo: https://github.com/astral-sh/uv-pre-commit + rev: 0.9.18 + hooks: + - id: uv-lock + - id: uv-sync + args: [ --locked, --all-groups ] + stages: [ pre-commit, post-checkout, post-merge, post-rewrite ] + - repo: https://github.com/asottile/blacken-docs rev: 1.19.1 hooks: @@ -63,15 +71,15 @@ repos: - repo: local hooks: - id: format - name: Format Python code via Poetry + name: Format Python code language: system pass_filenames: false - entry: poetry format + entry: uv run poe format types: [ python ] - id: linter and test - name: Linters via Poetry + name: Linters language: system pass_filenames: false - entry: poetry lint + entry: uv run poe lint types: [ python ] diff --git a/docs/contributing.md b/docs/contributing.md index 18d767750c..0e3ae4df0f 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -16,7 +16,7 @@ If you're a first-time contributor, please check out issues labeled [good first 1. **Python Environment** - Python `>=3.10` - - [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.2.0` + - [uv](https://docs.astral.sh/uv/getting-started/installation/) `>=0.9.0` 2. **Version Control & Security** - Git - Commitizen @@ -38,13 +38,13 @@ If you're a first-time contributor, please check out issues labeled [good first ```bash git remote add upstream https://github.com/commitizen-tools/commitizen.git ``` -4. Set up the development environment (nix users go to [nix section](#nix)): +4. Set up the development environment: ```bash - poetry install + uv sync --dev ``` 5. Set up pre-commit hooks: ```bash - poetry setup-pre-commit + uv run poe setup-pre-commit ``` ## Development Workflow @@ -61,15 +61,15 @@ If you're a first-time contributor, please check out issues labeled [good first - Update documentation if needed - Follow the existing code style 3. **Testing** - - Run the full test suite: `poetry all` + - Run the full test suite: `uv run poe all` - Ensure test coverage doesn't drop (we use [CodeCov](https://app.codecov.io/gh/commitizen-tools/commitizen)) - - For documentation changes, run `poetry doc` to check for warnings/errors + - For documentation changes, run `uv run poe doc` to check for warnings/errors 4. **Committing Changes** - Use Commitizen to make commits (we follow [conventional commits](https://www.conventionalcommits.org/)) - Example: `cz commit` 5. **Documentation** - Update `docs/README.md` if needed - - For CLI help screenshots: `poetry doc:screenshots` + - For CLI help screenshots: `uv run poe doc:screenshots` - Prefer [Google style documentation](https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings), which works well with editors like VSCode and PyCharm - **DO NOT** update `CHANGELOG.md` (automatically generated) - **DO NOT** update version numbers (automatically handled) @@ -154,16 +154,3 @@ flowchart TD --modification-received--> review ``` - -## Nix - -If you have installed poetry globally, the project won't work because it requires `poethepoet` for command management. - -You'll have to install poetry locally. - -```sh -python -m venv .venv -. .venv/bin/activate -pip install -U pip && pip install poetry -poetry install -``` diff --git a/docs/contributing_tldr.md b/docs/contributing_tldr.md index b7c1c94762..cbb83fb3c0 100644 --- a/docs/contributing_tldr.md +++ b/docs/contributing_tldr.md @@ -3,7 +3,7 @@ Feel free to send a PR to update this file if you find anything useful. 🙇 ## Environment - Python `>=3.10` -- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) `>=2.2.0` +- [uv](https://docs.astral.sh/uv/getting-started/installation/) `>=0.9.0` ## Useful commands @@ -12,14 +12,14 @@ Please check the [pyproject.toml](https://github.com/commitizen-tools/commitizen ### Code Changes ```bash -# Ensure you have the correct dependencies, for nix user's see below -poetry install +# Ensure you have the correct dependencies +uv sync --dev # Make ruff happy -poetry format +uv run poe format # Check if ruff and mypy are happy -poetry lint +uv run poe lint # Check if mypy is happy in python 3.10 mypy --python-version 3.10 @@ -33,16 +33,5 @@ pytest -n auto <test_suite> ```bash # Build the documentation locally and check for broken links -poetry doc -``` - -### Nix Users - -If you are using Nix, you can install poetry locally by running: - -```sh -python -m venv .venv -. .venv/bin/activate -pip install -U pip && pip install poetry -poetry install +uv run poe doc ``` diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index bc6a9d27f9..0000000000 --- a/poetry.lock +++ /dev/null @@ -1,2136 +0,0 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. - -[[package]] -name = "argcomplete" -version = "3.6.3" -description = "Bash tab completion for argparse" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce"}, - {file = "argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c"}, -] - -[package.extras] -test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] - -[[package]] -name = "asttokens" -version = "3.0.1" -description = "Annotate AST trees with source code positions" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"}, - {file = "asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"}, -] - -[package.extras] -astroid = ["astroid (>=2,<5)"] -test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] - -[[package]] -name = "babel" -version = "2.17.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.8" -groups = ["documentation"] -files = [ - {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, - {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, -] - -[package.extras] -dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] - -[[package]] -name = "backrefs" -version = "6.1" -description = "A wrapper around re and regex that adds additional back references." -optional = false -python-versions = ">=3.9" -groups = ["documentation"] -files = [ - {file = "backrefs-6.1-py310-none-any.whl", hash = "sha256:2a2ccb96302337ce61ee4717ceacfbf26ba4efb1d55af86564b8bbaeda39cac1"}, - {file = "backrefs-6.1-py311-none-any.whl", hash = "sha256:e82bba3875ee4430f4de4b6db19429a27275d95a5f3773c57e9e18abc23fd2b7"}, - {file = "backrefs-6.1-py312-none-any.whl", hash = "sha256:c64698c8d2269343d88947c0735cb4b78745bd3ba590e10313fbf3f78c34da5a"}, - {file = "backrefs-6.1-py313-none-any.whl", hash = "sha256:4c9d3dc1e2e558965202c012304f33d4e0e477e1c103663fd2c3cc9bb18b0d05"}, - {file = "backrefs-6.1-py314-none-any.whl", hash = "sha256:13eafbc9ccd5222e9c1f0bec563e6d2a6d21514962f11e7fc79872fd56cbc853"}, - {file = "backrefs-6.1-py39-none-any.whl", hash = "sha256:a9e99b8a4867852cad177a6430e31b0f6e495d65f8c6c134b68c14c3c95bf4b0"}, - {file = "backrefs-6.1.tar.gz", hash = "sha256:3bba1749aafe1db9b915f00e0dd166cba613b6f788ffd63060ac3485dc9be231"}, -] - -[package.extras] -extras = ["regex"] - -[[package]] -name = "cachetools" -version = "6.2.2" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "cachetools-6.2.2-py3-none-any.whl", hash = "sha256:6c09c98183bf58560c97b2abfcedcbaf6a896a490f534b031b661d3723b45ace"}, - {file = "cachetools-6.2.2.tar.gz", hash = "sha256:8e6d266b25e539df852251cfd6f990b4bc3a141db73b939058d809ebd2590fc6"}, -] - -[[package]] -name = "certifi" -version = "2025.11.12" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.7" -groups = ["documentation"] -files = [ - {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, - {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, -] - -[[package]] -name = "cfgv" -version = "3.5.0" -description = "Validate configuration and produce human readable error messages." -optional = false -python-versions = ">=3.10" -groups = ["linters"] -files = [ - {file = "cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}, - {file = "cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}, -] - -[[package]] -name = "chardet" -version = "5.2.0" -description = "Universal encoding detector for Python 3" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, - {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.4" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main", "documentation"] -files = [ - {file = "charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-win32.whl", hash = "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50"}, - {file = "charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f"}, - {file = "charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a"}, -] - -[[package]] -name = "click" -version = "8.3.1" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -groups = ["documentation"] -files = [ - {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, - {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev", "documentation", "test"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "coverage" -version = "7.13.0" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=3.10" -groups = ["test"] -files = [ - {file = "coverage-7.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:02d9fb9eccd48f6843c98a37bd6817462f130b86da8660461e8f5e54d4c06070"}, - {file = "coverage-7.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:367449cf07d33dc216c083f2036bb7d976c6e4903ab31be400ad74ad9f85ce98"}, - {file = "coverage-7.13.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cdb3c9f8fef0a954c632f64328a3935988d33a6604ce4bf67ec3e39670f12ae5"}, - {file = "coverage-7.13.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d10fd186aac2316f9bbb46ef91977f9d394ded67050ad6d84d94ed6ea2e8e54e"}, - {file = "coverage-7.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f88ae3e69df2ab62fb0bc5219a597cb890ba5c438190ffa87490b315190bb33"}, - {file = "coverage-7.13.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4be718e51e86f553bcf515305a158a1cd180d23b72f07ae76d6017c3cc5d791"}, - {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a00d3a393207ae12f7c49bb1c113190883b500f48979abb118d8b72b8c95c032"}, - {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a7b1cd820e1b6116f92c6128f1188e7afe421c7e1b35fa9836b11444e53ebd9"}, - {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:37eee4e552a65866f15dedd917d5e5f3d59805994260720821e2c1b51ac3248f"}, - {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62d7c4f13102148c78d7353c6052af6d899a7f6df66a32bddcc0c0eb7c5326f8"}, - {file = "coverage-7.13.0-cp310-cp310-win32.whl", hash = "sha256:24e4e56304fdb56f96f80eabf840eab043b3afea9348b88be680ec5986780a0f"}, - {file = "coverage-7.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:74c136e4093627cf04b26a35dab8cbfc9b37c647f0502fc313376e11726ba303"}, - {file = "coverage-7.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820"}, - {file = "coverage-7.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f"}, - {file = "coverage-7.13.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96"}, - {file = "coverage-7.13.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259"}, - {file = "coverage-7.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb"}, - {file = "coverage-7.13.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9"}, - {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030"}, - {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833"}, - {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8"}, - {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753"}, - {file = "coverage-7.13.0-cp311-cp311-win32.whl", hash = "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b"}, - {file = "coverage-7.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe"}, - {file = "coverage-7.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7"}, - {file = "coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf"}, - {file = "coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f"}, - {file = "coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb"}, - {file = "coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621"}, - {file = "coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74"}, - {file = "coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57"}, - {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8"}, - {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d"}, - {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b"}, - {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd"}, - {file = "coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef"}, - {file = "coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae"}, - {file = "coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080"}, - {file = "coverage-7.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:28ee1c96109974af104028a8ef57cec21447d42d0e937c0275329272e370ebcf"}, - {file = "coverage-7.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e97353dcc5587b85986cda4ff3ec98081d7e84dd95e8b2a6d59820f0545f8a"}, - {file = "coverage-7.13.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:99acd4dfdfeb58e1937629eb1ab6ab0899b131f183ee5f23e0b5da5cba2fec74"}, - {file = "coverage-7.13.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff45e0cd8451e293b63ced93161e189780baf444119391b3e7d25315060368a6"}, - {file = "coverage-7.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4f72a85316d8e13234cafe0a9f81b40418ad7a082792fa4165bd7d45d96066b"}, - {file = "coverage-7.13.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11c21557d0e0a5a38632cbbaca5f008723b26a89d70db6315523df6df77d6232"}, - {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76541dc8d53715fb4f7a3a06b34b0dc6846e3c69bc6204c55653a85dd6220971"}, - {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6e9e451dee940a86789134b6b0ffbe31c454ade3b849bb8a9d2cca2541a8e91d"}, - {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5c67dace46f361125e6b9cace8fe0b729ed8479f47e70c89b838d319375c8137"}, - {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f59883c643cb19630500f57016f76cfdcd6845ca8c5b5ea1f6e17f74c8e5f511"}, - {file = "coverage-7.13.0-cp313-cp313-win32.whl", hash = "sha256:58632b187be6f0be500f553be41e277712baa278147ecb7559983c6d9faf7ae1"}, - {file = "coverage-7.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:73419b89f812f498aca53f757dd834919b48ce4799f9d5cad33ca0ae442bdb1a"}, - {file = "coverage-7.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb76670874fdd6091eedcc856128ee48c41a9bbbb9c3f1c7c3cf169290e3ffd6"}, - {file = "coverage-7.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6e63ccc6e0ad8986386461c3c4b737540f20426e7ec932f42e030320896c311a"}, - {file = "coverage-7.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:494f5459ffa1bd45e18558cd98710c36c0b8fbfa82a5eabcbe671d80ecffbfe8"}, - {file = "coverage-7.13.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:06cac81bf10f74034e055e903f5f946e3e26fc51c09fc9f584e4a1605d977053"}, - {file = "coverage-7.13.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f2ffc92b46ed6e6760f1d47a71e56b5664781bc68986dbd1836b2b70c0ce2071"}, - {file = "coverage-7.13.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0602f701057c6823e5db1b74530ce85f17c3c5be5c85fc042ac939cbd909426e"}, - {file = "coverage-7.13.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:25dc33618d45456ccb1d37bce44bc78cf269909aa14c4db2e03d63146a8a1493"}, - {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:71936a8b3b977ddd0b694c28c6a34f4fff2e9dd201969a4ff5d5fc7742d614b0"}, - {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:936bc20503ce24770c71938d1369461f0c5320830800933bc3956e2a4ded930e"}, - {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:af0a583efaacc52ae2521f8d7910aff65cdb093091d76291ac5820d5e947fc1c"}, - {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f1c23e24a7000da892a312fb17e33c5f94f8b001de44b7cf8ba2e36fbd15859e"}, - {file = "coverage-7.13.0-cp313-cp313t-win32.whl", hash = "sha256:5f8a0297355e652001015e93be345ee54393e45dc3050af4a0475c5a2b767d46"}, - {file = "coverage-7.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6abb3a4c52f05e08460bd9acf04fec027f8718ecaa0d09c40ffbc3fbd70ecc39"}, - {file = "coverage-7.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:3ad968d1e3aa6ce5be295ab5fe3ae1bf5bb4769d0f98a80a0252d543a2ef2e9e"}, - {file = "coverage-7.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:453b7ec753cf5e4356e14fe858064e5520c460d3bbbcb9c35e55c0d21155c256"}, - {file = "coverage-7.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af827b7cbb303e1befa6c4f94fd2bf72f108089cfa0f8abab8f4ca553cf5ca5a"}, - {file = "coverage-7.13.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9987a9e4f8197a1000280f7cc089e3ea2c8b3c0a64d750537809879a7b4ceaf9"}, - {file = "coverage-7.13.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3188936845cd0cb114fa6a51842a304cdbac2958145d03be2377ec41eb285d19"}, - {file = "coverage-7.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2bdb3babb74079f021696cb46b8bb5f5661165c385d3a238712b031a12355be"}, - {file = "coverage-7.13.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7464663eaca6adba4175f6c19354feea61ebbdd735563a03d1e472c7072d27bb"}, - {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8069e831f205d2ff1f3d355e82f511eb7c5522d7d413f5db5756b772ec8697f8"}, - {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6fb2d5d272341565f08e962cce14cdf843a08ac43bd621783527adb06b089c4b"}, - {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5e70f92ef89bac1ac8a99b3324923b4749f008fdbd7aa9cb35e01d7a284a04f9"}, - {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4b5de7d4583e60d5fd246dd57fcd3a8aa23c6e118a8c72b38adf666ba8e7e927"}, - {file = "coverage-7.13.0-cp314-cp314-win32.whl", hash = "sha256:a6c6e16b663be828a8f0b6c5027d36471d4a9f90d28444aa4ced4d48d7d6ae8f"}, - {file = "coverage-7.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:0900872f2fdb3ee5646b557918d02279dc3af3dfb39029ac4e945458b13f73bc"}, - {file = "coverage-7.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:3a10260e6a152e5f03f26db4a407c4c62d3830b9af9b7c0450b183615f05d43b"}, - {file = "coverage-7.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9097818b6cc1cfb5f174e3263eba4a62a17683bcfe5c4b5d07f4c97fa51fbf28"}, - {file = "coverage-7.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0018f73dfb4301a89292c73be6ba5f58722ff79f51593352759c1790ded1cabe"}, - {file = "coverage-7.13.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:166ad2a22ee770f5656e1257703139d3533b4a0b6909af67c6b4a3adc1c98657"}, - {file = "coverage-7.13.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f6aaef16d65d1787280943f1c8718dc32e9cf141014e4634d64446702d26e0ff"}, - {file = "coverage-7.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e999e2dcc094002d6e2c7bbc1fb85b58ba4f465a760a8014d97619330cdbbbf3"}, - {file = "coverage-7.13.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:00c3d22cf6fb1cf3bf662aaaa4e563be8243a5ed2630339069799835a9cc7f9b"}, - {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22ccfe8d9bb0d6134892cbe1262493a8c70d736b9df930f3f3afae0fe3ac924d"}, - {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9372dff5ea15930fea0445eaf37bbbafbc771a49e70c0aeed8b4e2c2614cc00e"}, - {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:69ac2c492918c2461bc6ace42d0479638e60719f2a4ef3f0815fa2df88e9f940"}, - {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:739c6c051a7540608d097b8e13c76cfa85263ced467168dc6b477bae3df7d0e2"}, - {file = "coverage-7.13.0-cp314-cp314t-win32.whl", hash = "sha256:fe81055d8c6c9de76d60c94ddea73c290b416e061d40d542b24a5871bad498b7"}, - {file = "coverage-7.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:445badb539005283825959ac9fa4a28f712c214b65af3a2c464f1adc90f5fcbc"}, - {file = "coverage-7.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:de7f6748b890708578fc4b7bb967d810aeb6fcc9bff4bb77dbca77dab2f9df6a"}, - {file = "coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904"}, - {file = "coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936"}, -] - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] - -[[package]] -name = "decli" -version = "0.6.3" -description = "Minimal, easy-to-use, declarative cli tool" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "decli-0.6.3-py3-none-any.whl", hash = "sha256:5152347c7bb8e3114ad65db719e5709b28d7f7f45bdb709f70167925e55640f3"}, - {file = "decli-0.6.3.tar.gz", hash = "sha256:87f9d39361adf7f16b9ca6e3b614badf7519da13092f2db3c80ca223c53c7656"}, -] - -[[package]] -name = "decorator" -version = "5.2.1" -description = "Decorators for Humans" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, - {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, -] - -[[package]] -name = "deprecated" -version = "1.3.1" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["main"] -files = [ - {file = "deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f"}, - {file = "deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223"}, -] - -[package.dependencies] -wrapt = ">=1.10,<3" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version >= \"3.12\"", "tox"] - -[[package]] -name = "distlib" -version = "0.4.0" -description = "Distribution utilities" -optional = false -python-versions = "*" -groups = ["dev", "linters"] -files = [ - {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, - {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.3.1" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -groups = ["dev", "test"] -markers = "python_version == \"3.10\"" -files = [ - {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, - {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "execnet" -version = "2.1.2" -description = "execnet: rapid multi-Python deployment" -optional = false -python-versions = ">=3.8" -groups = ["test"] -files = [ - {file = "execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec"}, - {file = "execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd"}, -] - -[package.extras] -testing = ["hatch", "pre-commit", "pytest", "tox"] - -[[package]] -name = "executing" -version = "2.2.1" -description = "Get the currently executing AST node of a frame, and other information" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017"}, - {file = "executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4"}, -] - -[package.extras] -tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich ; python_version >= \"3.11\""] - -[[package]] -name = "filelock" -version = "3.20.0" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.10" -groups = ["dev", "linters"] -files = [ - {file = "filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2"}, - {file = "filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4"}, -] - -[[package]] -name = "freezegun" -version = "1.5.5" -description = "Let your Python tests travel through time" -optional = false -python-versions = ">=3.8" -groups = ["test"] -files = [ - {file = "freezegun-1.5.5-py3-none-any.whl", hash = "sha256:cd557f4a75cf074e84bc374249b9dd491eaeacd61376b9eb3c423282211619d2"}, - {file = "freezegun-1.5.5.tar.gz", hash = "sha256:ac7742a6cc6c25a2c35e9292dfd554b897b517d2dec26891a2e8debf205cb94a"}, -] - -[package.dependencies] -python-dateutil = ">=2.7" - -[[package]] -name = "ghp-import" -version = "2.1.0" -description = "Copy your docs directly to the gh-pages branch." -optional = false -python-versions = "*" -groups = ["documentation"] -files = [ - {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, - {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.1" - -[package.extras] -dev = ["flake8", "markdown", "twine", "wheel"] - -[[package]] -name = "identify" -version = "2.6.15" -description = "File identification library for Python" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757"}, - {file = "identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf"}, -] - -[package.extras] -license = ["ukkonen"] - -[[package]] -name = "idna" -version = "3.11" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.8" -groups = ["documentation"] -files = [ - {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, - {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "iniconfig" -version = "2.3.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.10" -groups = ["test"] -files = [ - {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, - {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, -] - -[[package]] -name = "ipython" -version = "8.37.0" -description = "IPython: Productive Interactive Computing" -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2"}, - {file = "ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -decorator = "*" -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} -jedi = ">=0.16" -matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} -prompt_toolkit = ">=3.0.41,<3.1.0" -pygments = ">=2.4.0" -stack_data = "*" -traitlets = ">=5.13.0" -typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} - -[package.extras] -all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] -black = ["black"] -doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli ; python_version < \"3.11\"", "typing_extensions"] -kernel = ["ipykernel"] -matplotlib = ["matplotlib"] -nbconvert = ["nbconvert"] -nbformat = ["nbformat"] -notebook = ["ipywidgets", "notebook"] -parallel = ["ipyparallel"] -qtconsole = ["qtconsole"] -test = ["packaging", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] - -[[package]] -name = "jedi" -version = "0.19.2" -description = "An autocompletion tool for Python that can be used for text editors." -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, - {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, -] - -[package.dependencies] -parso = ">=0.8.4,<0.9.0" - -[package.extras] -docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] - -[[package]] -name = "jinja2" -version = "3.1.6" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -groups = ["main", "documentation"] -files = [ - {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, - {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "librt" -version = "0.7.3" -description = "Mypyc runtime library" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "librt-0.7.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2682162855a708e3270eba4b92026b93f8257c3e65278b456c77631faf0f4f7a"}, - {file = "librt-0.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:440c788f707c061d237c1e83edf6164ff19f5c0f823a3bf054e88804ebf971ec"}, - {file = "librt-0.7.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399938edbd3d78339f797d685142dd8a623dfaded023cf451033c85955e4838a"}, - {file = "librt-0.7.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1975eda520957c6e0eb52d12968dd3609ffb7eef05d4223d097893d6daf1d8a7"}, - {file = "librt-0.7.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9da128d0edf990cf0d2ca011b02cd6f639e79286774bd5b0351245cbb5a6e51"}, - {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19acfde38cb532a560b98f473adc741c941b7a9bc90f7294bc273d08becb58b"}, - {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:7b4f57f7a0c65821c5441d98c47ff7c01d359b1e12328219709bdd97fdd37f90"}, - {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:256793988bff98040de23c57cf36e1f4c2f2dc3dcd17537cdac031d3b681db71"}, - {file = "librt-0.7.3-cp310-cp310-win32.whl", hash = "sha256:fcb72249ac4ea81a7baefcbff74df7029c3cb1cf01a711113fa052d563639c9c"}, - {file = "librt-0.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:4887c29cadbdc50640179e3861c276325ff2986791e6044f73136e6e798ff806"}, - {file = "librt-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:687403cced6a29590e6be6964463835315905221d797bc5c934a98750fe1a9af"}, - {file = "librt-0.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24d70810f6e2ea853ff79338001533716b373cc0f63e2a0be5bc96129edb5fb5"}, - {file = "librt-0.7.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf8c7735fbfc0754111f00edda35cf9e98a8d478de6c47b04eaa9cef4300eaa7"}, - {file = "librt-0.7.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32d43610dff472eab939f4d7fbdd240d1667794192690433672ae22d7af8445"}, - {file = "librt-0.7.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:adeaa886d607fb02563c1f625cf2ee58778a2567c0c109378da8f17ec3076ad7"}, - {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:572a24fc5958c61431da456a0ef1eeea6b4989d81eeb18b8e5f1f3077592200b"}, - {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6488e69d408b492e08bfb68f20c4a899a354b4386a446ecd490baff8d0862720"}, - {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed028fc3d41adda916320712838aec289956c89b4f0a361ceadf83a53b4c047a"}, - {file = "librt-0.7.3-cp311-cp311-win32.whl", hash = "sha256:2cf9d73499486ce39eebbff5f42452518cc1f88d8b7ea4a711ab32962b176ee2"}, - {file = "librt-0.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:35f1609e3484a649bb80431310ddbec81114cd86648f1d9482bc72a3b86ded2e"}, - {file = "librt-0.7.3-cp311-cp311-win_arm64.whl", hash = "sha256:550fdbfbf5bba6a2960b27376ca76d6aaa2bd4b1a06c4255edd8520c306fcfc0"}, - {file = "librt-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fa9ac2e49a6bee56e47573a6786cb635e128a7b12a0dc7851090037c0d397a3"}, - {file = "librt-0.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e980cf1ed1a2420a6424e2ed884629cdead291686f1048810a817de07b5eb18"}, - {file = "librt-0.7.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e094e445c37c57e9ec612847812c301840239d34ccc5d153a982fa9814478c60"}, - {file = "librt-0.7.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aca73d70c3f553552ba9133d4a09e767dcfeee352d8d8d3eb3f77e38a3beb3ed"}, - {file = "librt-0.7.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c634a0a6db395fdaba0361aa78395597ee72c3aad651b9a307a3a7eaf5efd67e"}, - {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a59a69deeb458c858b8fea6acf9e2acd5d755d76cd81a655256bc65c20dfff5b"}, - {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d91e60ac44bbe3a77a67af4a4c13114cbe9f6d540337ce22f2c9eaf7454ca71f"}, - {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:703456146dc2bf430f7832fd1341adac5c893ec3c1430194fdcefba00012555c"}, - {file = "librt-0.7.3-cp312-cp312-win32.whl", hash = "sha256:b7c1239b64b70be7759554ad1a86288220bbb04d68518b527783c4ad3fb4f80b"}, - {file = "librt-0.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef59c938f72bdbc6ab52dc50f81d0637fde0f194b02d636987cea2ab30f8f55a"}, - {file = "librt-0.7.3-cp312-cp312-win_arm64.whl", hash = "sha256:ff21c554304e8226bf80c3a7754be27c6c3549a9fec563a03c06ee8f494da8fc"}, - {file = "librt-0.7.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56f2a47beda8409061bc1c865bef2d4bd9ff9255219402c0817e68ab5ad89aed"}, - {file = "librt-0.7.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14569ac5dd38cfccf0a14597a88038fb16811a6fede25c67b79c6d50fc2c8fdc"}, - {file = "librt-0.7.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6038ccbd5968325a5d6fd393cf6e00b622a8de545f0994b89dd0f748dcf3e19e"}, - {file = "librt-0.7.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d39079379a9a28e74f4d57dc6357fa310a1977b51ff12239d7271ec7e71d67f5"}, - {file = "librt-0.7.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8837d5a52a2d7aa9f4c3220a8484013aed1d8ad75240d9a75ede63709ef89055"}, - {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:399bbd7bcc1633c3e356ae274a1deb8781c7bf84d9c7962cc1ae0c6e87837292"}, - {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8d8cf653e798ee4c4e654062b633db36984a1572f68c3aa25e364a0ddfbbb910"}, - {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2f03484b54bf4ae80ab2e504a8d99d20d551bfe64a7ec91e218010b467d77093"}, - {file = "librt-0.7.3-cp313-cp313-win32.whl", hash = "sha256:44b3689b040df57f492e02cd4f0bacd1b42c5400e4b8048160c9d5e866de8abe"}, - {file = "librt-0.7.3-cp313-cp313-win_amd64.whl", hash = "sha256:6b407c23f16ccc36614c136251d6b32bf30de7a57f8e782378f1107be008ddb0"}, - {file = "librt-0.7.3-cp313-cp313-win_arm64.whl", hash = "sha256:abfc57cab3c53c4546aee31859ef06753bfc136c9d208129bad23e2eca39155a"}, - {file = "librt-0.7.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:120dd21d46ff875e849f1aae19346223cf15656be489242fe884036b23d39e93"}, - {file = "librt-0.7.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1617bea5ab31266e152871208502ee943cb349c224846928a1173c864261375e"}, - {file = "librt-0.7.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93b2a1f325fefa1482516ced160c8c7b4b8d53226763fa6c93d151fa25164207"}, - {file = "librt-0.7.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d4801db8354436fd3936531e7f0e4feb411f62433a6b6cb32bb416e20b529f"}, - {file = "librt-0.7.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11ad45122bbed42cfc8b0597450660126ef28fd2d9ae1a219bc5af8406f95678"}, - {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6b4e7bff1d76dd2b46443078519dc75df1b5e01562345f0bb740cea5266d8218"}, - {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:d86f94743a11873317094326456b23f8a5788bad9161fd2f0e52088c33564620"}, - {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:754a0d09997095ad764ccef050dd5bf26cbf457aab9effcba5890dad081d879e"}, - {file = "librt-0.7.3-cp314-cp314-win32.whl", hash = "sha256:fbd7351d43b80d9c64c3cfcb50008f786cc82cba0450e8599fdd64f264320bd3"}, - {file = "librt-0.7.3-cp314-cp314-win_amd64.whl", hash = "sha256:d376a35c6561e81d2590506804b428fc1075fcc6298fc5bb49b771534c0ba010"}, - {file = "librt-0.7.3-cp314-cp314-win_arm64.whl", hash = "sha256:cbdb3f337c88b43c3b49ca377731912c101178be91cb5071aac48faa898e6f8e"}, - {file = "librt-0.7.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9f0e0927efe87cd42ad600628e595a1a0aa1c64f6d0b55f7e6059079a428641a"}, - {file = "librt-0.7.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:020c6db391268bcc8ce75105cb572df8cb659a43fd347366aaa407c366e5117a"}, - {file = "librt-0.7.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7af7785f5edd1f418da09a8cdb9ec84b0213e23d597413e06525340bcce1ea4f"}, - {file = "librt-0.7.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ccadf260bb46a61b9c7e89e2218f6efea9f3eeaaab4e3d1f58571890e54858e"}, - {file = "librt-0.7.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9883b2d819ce83f87ba82a746c81d14ada78784db431e57cc9719179847376e"}, - {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:59cb0470612d21fa1efddfa0dd710756b50d9c7fb6c1236bbf8ef8529331dc70"}, - {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1fe603877e1865b5fd047a5e40379509a4a60204aa7aa0f72b16f7a41c3f0712"}, - {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5460d99ed30f043595bbdc888f542bad2caeb6226b01c33cda3ae444e8f82d42"}, - {file = "librt-0.7.3-cp314-cp314t-win32.whl", hash = "sha256:d09f677693328503c9e492e33e9601464297c01f9ebd966ea8fc5308f3069bfd"}, - {file = "librt-0.7.3-cp314-cp314t-win_amd64.whl", hash = "sha256:25711f364c64cab2c910a0247e90b51421e45dbc8910ceeb4eac97a9e132fc6f"}, - {file = "librt-0.7.3-cp314-cp314t-win_arm64.whl", hash = "sha256:a9f9b661f82693eb56beb0605156c7fca57f535704ab91837405913417d6990b"}, - {file = "librt-0.7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd8551aa21df6c60baa2624fd086ae7486bdde00c44097b32e1d1b1966e365e0"}, - {file = "librt-0.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6eb9295c730e26b849ed1f4022735f36863eb46b14b6e10604c1c39b8b5efaea"}, - {file = "librt-0.7.3-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3edbf257c40d21a42615e9e332a6b10a8bacaaf58250aed8552a14a70efd0d65"}, - {file = "librt-0.7.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b29e97273bd6999e2bfe9fe3531b1f4f64effd28327bced048a33e49b99674a"}, - {file = "librt-0.7.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e40520c37926166c24d0c2e0f3bc3a5f46646c34bdf7b4ea9747c297d6ee809"}, - {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6bdd9adfca615903578d2060ee8a6eb1c24eaf54919ff0ddc820118e5718931b"}, - {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f57aca20e637750a2c18d979f7096e2c2033cc40cf7ed201494318de1182f135"}, - {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cad9971881e4fec00d96af7eaf4b63aa7a595696fc221808b0d3ce7ca9743258"}, - {file = "librt-0.7.3-cp39-cp39-win32.whl", hash = "sha256:170cdb8436188347af17bf9cccf3249ba581c933ed56d926497119d4cf730cec"}, - {file = "librt-0.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:b278a9248a4e3260fee3db7613772ca9ab6763a129d6d6f29555e2f9b168216d"}, - {file = "librt-0.7.3.tar.gz", hash = "sha256:3ec50cf65235ff5c02c5b747748d9222e564ad48597122a361269dd3aa808798"}, -] - -[[package]] -name = "markdown" -version = "3.10" -description = "Python implementation of John Gruber's Markdown." -optional = false -python-versions = ">=3.10" -groups = ["documentation"] -files = [ - {file = "markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c"}, - {file = "markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e"}, -] - -[package.extras] -docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] -testing = ["coverage", "pyyaml"] - -[[package]] -name = "markdown-it-py" -version = "4.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.10" -groups = ["script"] -files = [ - {file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}, - {file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "markdown-it-pyrs", "mistletoe (>=1.0,<2.0)", "mistune (>=3.0,<4.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins (>=0.5.0)"] -profiling = ["gprof2dot"] -rtd = ["ipykernel", "jupyter_sphinx", "mdit-py-plugins (>=0.5.0)", "myst-parser", "pyyaml", "sphinx", "sphinx-book-theme (>=1.0,<2.0)", "sphinx-copybutton", "sphinx-design"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "requests"] - -[[package]] -name = "markupsafe" -version = "3.0.3" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.9" -groups = ["main", "documentation"] -files = [ - {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, - {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, - {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, - {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, - {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, - {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, - {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, - {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, - {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, - {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, - {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, - {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, - {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, - {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, - {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, - {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, - {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, - {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, - {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, - {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, - {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, - {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, - {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, - {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, - {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, - {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, - {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, - {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, - {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, - {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, - {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, - {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, - {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, - {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, - {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, - {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, - {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, - {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, - {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, - {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, - {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, - {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, - {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, - {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, - {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, - {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, - {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, - {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, - {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, - {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, - {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, - {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, - {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, - {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, - {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, - {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, - {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, - {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, - {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, - {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, - {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, - {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, - {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, - {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, - {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, - {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, - {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, - {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, - {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, - {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, - {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, - {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, - {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, - {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, - {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, - {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, - {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, - {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, - {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, - {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, - {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, - {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, - {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, - {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, - {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, - {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, - {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, - {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, - {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, -] - -[[package]] -name = "matplotlib-inline" -version = "0.2.1" -description = "Inline Matplotlib backend for Jupyter" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76"}, - {file = "matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe"}, -] - -[package.dependencies] -traitlets = "*" - -[package.extras] -test = ["flake8", "nbdime", "nbval", "notebook", "pytest"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["script"] -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "mergedeep" -version = "1.3.4" -description = "A deep merge function for 🐍." -optional = false -python-versions = ">=3.6" -groups = ["documentation"] -files = [ - {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, - {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, -] - -[[package]] -name = "mkdocs" -version = "1.6.1" -description = "Project documentation with Markdown." -optional = false -python-versions = ">=3.8" -groups = ["documentation"] -files = [ - {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"}, - {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} -ghp-import = ">=1.0" -jinja2 = ">=2.11.1" -markdown = ">=3.3.6" -markupsafe = ">=2.0.1" -mergedeep = ">=1.3.4" -mkdocs-get-deps = ">=0.2.0" -packaging = ">=20.5" -pathspec = ">=0.11.1" -pyyaml = ">=5.1" -pyyaml-env-tag = ">=0.1" -watchdog = ">=2.0" - -[package.extras] -i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform_system == \"Windows\"", "ghp-import (==1.0)", "importlib-metadata (==4.4) ; python_version < \"3.10\"", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] - -[[package]] -name = "mkdocs-get-deps" -version = "0.2.0" -description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" -optional = false -python-versions = ">=3.8" -groups = ["documentation"] -files = [ - {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, - {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, -] - -[package.dependencies] -mergedeep = ">=1.3.4" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" - -[[package]] -name = "mkdocs-material" -version = "9.7.0" -description = "Documentation that simply works" -optional = false -python-versions = ">=3.8" -groups = ["documentation"] -files = [ - {file = "mkdocs_material-9.7.0-py3-none-any.whl", hash = "sha256:da2866ea53601125ff5baa8aa06404c6e07af3c5ce3d5de95e3b52b80b442887"}, - {file = "mkdocs_material-9.7.0.tar.gz", hash = "sha256:602b359844e906ee402b7ed9640340cf8a474420d02d8891451733b6b02314ec"}, -] - -[package.dependencies] -babel = ">=2.10" -backrefs = ">=5.7.post1" -colorama = ">=0.4" -jinja2 = ">=3.1" -markdown = ">=3.2" -mkdocs = ">=1.6" -mkdocs-material-extensions = ">=1.3" -paginate = ">=0.5" -pygments = ">=2.16" -pymdown-extensions = ">=10.2" -requests = ">=2.26" - -[package.extras] -git = ["mkdocs-git-committers-plugin-2 (>=1.1,<3)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] -imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<12.0)"] -recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -description = "Extension pack for Python Markdown and MkDocs Material." -optional = false -python-versions = ">=3.8" -groups = ["documentation"] -files = [ - {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, - {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, -] - -[[package]] -name = "mypy" -version = "1.19.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "mypy-1.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6148ede033982a8c5ca1143de34c71836a09f105068aaa8b7d5edab2b053e6c8"}, - {file = "mypy-1.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a9ac09e52bb0f7fb912f5d2a783345c72441a08ef56ce3e17c1752af36340a39"}, - {file = "mypy-1.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f7254c15ab3f8ed68f8e8f5cbe88757848df793e31c36aaa4d4f9783fd08ab"}, - {file = "mypy-1.19.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318ba74f75899b0e78b847d8c50821e4c9637c79d9a59680fc1259f29338cb3e"}, - {file = "mypy-1.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf7d84f497f78b682edd407f14a7b6e1a2212b433eedb054e2081380b7395aa3"}, - {file = "mypy-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:c3385246593ac2b97f155a0e9639be906e73534630f663747c71908dfbf26134"}, - {file = "mypy-1.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a31e4c28e8ddb042c84c5e977e28a21195d086aaffaf08b016b78e19c9ef8106"}, - {file = "mypy-1.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34ec1ac66d31644f194b7c163d7f8b8434f1b49719d403a5d26c87fff7e913f7"}, - {file = "mypy-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb64b0ba5980466a0f3f9990d1c582bcab8db12e29815ecb57f1408d99b4bff7"}, - {file = "mypy-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:120cffe120cca5c23c03c77f84abc0c14c5d2e03736f6c312480020082f1994b"}, - {file = "mypy-1.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a500ab5c444268a70565e374fc803972bfd1f09545b13418a5174e29883dab7"}, - {file = "mypy-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:c14a98bc63fd867530e8ec82f217dae29d0550c86e70debc9667fff1ec83284e"}, - {file = "mypy-1.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fb3115cb8fa7c5f887c8a8d81ccdcb94cff334684980d847e5a62e926910e1d"}, - {file = "mypy-1.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3e19e3b897562276bb331074d64c076dbdd3e79213f36eed4e592272dabd760"}, - {file = "mypy-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9d491295825182fba01b6ffe2c6fe4e5a49dbf4e2bb4d1217b6ced3b4797bc6"}, - {file = "mypy-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6016c52ab209919b46169651b362068f632efcd5eb8ef9d1735f6f86da7853b2"}, - {file = "mypy-1.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f188dcf16483b3e59f9278c4ed939ec0254aa8a60e8fc100648d9ab5ee95a431"}, - {file = "mypy-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:0e3c3d1e1d62e678c339e7ade72746a9e0325de42cd2cccc51616c7b2ed1a018"}, - {file = "mypy-1.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7686ed65dbabd24d20066f3115018d2dce030d8fa9db01aa9f0a59b6813e9f9e"}, - {file = "mypy-1.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fd4a985b2e32f23bead72e2fb4bbe5d6aceee176be471243bd831d5b2644672d"}, - {file = "mypy-1.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc51a5b864f73a3a182584b1ac75c404396a17eced54341629d8bdcb644a5bba"}, - {file = "mypy-1.19.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37af5166f9475872034b56c5efdcf65ee25394e9e1d172907b84577120714364"}, - {file = "mypy-1.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:510c014b722308c9bd377993bcbf9a07d7e0692e5fa8fc70e639c1eb19fc6bee"}, - {file = "mypy-1.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:cabbee74f29aa9cd3b444ec2f1e4fa5a9d0d746ce7567a6a609e224429781f53"}, - {file = "mypy-1.19.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f2e36bed3c6d9b5f35d28b63ca4b727cb0228e480826ffc8953d1892ddc8999d"}, - {file = "mypy-1.19.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a18d8abdda14035c5718acb748faec09571432811af129bf0d9e7b2d6699bf18"}, - {file = "mypy-1.19.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75e60aca3723a23511948539b0d7ed514dda194bc3755eae0bfc7a6b4887aa7"}, - {file = "mypy-1.19.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f44f2ae3c58421ee05fe609160343c25f70e3967f6e32792b5a78006a9d850f"}, - {file = "mypy-1.19.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63ea6a00e4bd6822adbfc75b02ab3653a17c02c4347f5bb0cf1d5b9df3a05835"}, - {file = "mypy-1.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ad925b14a0bb99821ff6f734553294aa6a3440a8cb082fe1f5b84dfb662afb1"}, - {file = "mypy-1.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0dde5cb375cb94deff0d4b548b993bec52859d1651e073d63a1386d392a95495"}, - {file = "mypy-1.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1cf9c59398db1c68a134b0b5354a09a1e124523f00bacd68e553b8bd16ff3299"}, - {file = "mypy-1.19.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3210d87b30e6af9c8faed61be2642fcbe60ef77cec64fa1ef810a630a4cf671c"}, - {file = "mypy-1.19.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2c1101ab41d01303103ab6ef82cbbfedb81c1a060c868fa7cc013d573d37ab5"}, - {file = "mypy-1.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ea4fd21bb48f0da49e6d3b37ef6bd7e8228b9fe41bbf4d80d9364d11adbd43c"}, - {file = "mypy-1.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:16f76ff3f3fd8137aadf593cb4607d82634fca675e8211ad75c43d86033ee6c6"}, - {file = "mypy-1.19.0-py3-none-any.whl", hash = "sha256:0c01c99d626380752e527d5ce8e69ffbba2046eb8a060db0329690849cf9b6f9"}, - {file = "mypy-1.19.0.tar.gz", hash = "sha256:f6b874ca77f733222641e5c46e4711648c4037ea13646fd0cdc814c2eaec2528"}, -] - -[package.dependencies] -librt = ">=0.6.2" -mypy_extensions = ">=1.0.0" -pathspec = ">=0.9.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["linters"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "nodeenv" -version = "1.9.1" -description = "Node.js virtual environment builder" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["linters"] -files = [ - {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, - {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, -] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "documentation", "test"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "paginate" -version = "0.5.7" -description = "Divides large result sets into pages for easier browsing" -optional = false -python-versions = "*" -groups = ["documentation"] -files = [ - {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"}, - {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"}, -] - -[package.extras] -dev = ["pytest", "tox"] -lint = ["black"] - -[[package]] -name = "parso" -version = "0.8.5" -description = "A Python Parser" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887"}, - {file = "parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a"}, -] - -[package.extras] -qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["docopt", "pytest"] - -[[package]] -name = "pastel" -version = "0.2.1" -description = "Bring colors to your terminal." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, - {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["documentation", "linters"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "pexpect" -version = "4.9.0" -description = "Pexpect allows easy control of interactive console applications." -optional = false -python-versions = "*" -groups = ["dev"] -markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" -files = [ - {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, - {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, -] - -[package.dependencies] -ptyprocess = ">=0.5" - -[[package]] -name = "platformdirs" -version = "4.5.1" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.10" -groups = ["dev", "documentation", "linters"] -files = [ - {file = "platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"}, - {file = "platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda"}, -] - -[package.extras] -docs = ["furo (>=2025.9.25)", "proselint (>=0.14)", "sphinx (>=8.2.3)", "sphinx-autodoc-typehints (>=3.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)"] -type = ["mypy (>=1.18.2)"] - -[[package]] -name = "pluggy" -version = "1.6.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.9" -groups = ["dev", "test"] -files = [ - {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, - {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["coverage", "pytest", "pytest-benchmark"] - -[[package]] -name = "poethepoet" -version = "0.38.0" -description = "A task runner that works well with poetry and uv." -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "poethepoet-0.38.0-py3-none-any.whl", hash = "sha256:214bd9fcb348ff3dfd1466579d67e0c02242451a7044aced1a79641adef9cad0"}, - {file = "poethepoet-0.38.0.tar.gz", hash = "sha256:aeeb2f0a2cf0d3afa833976eff3ac7b8f5e472ae64171824900d79d3c68163c7"}, -] - -[package.dependencies] -pastel = ">=0.2.1,<0.3.0" -pyyaml = ">=6.0.3,<7.0" -tomli = {version = ">=1.3.0", markers = "python_version < \"3.11\""} - -[package.extras] -poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""] - -[[package]] -name = "pre-commit" -version = "4.5.0" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -optional = false -python-versions = ">=3.10" -groups = ["linters"] -files = [ - {file = "pre_commit-4.5.0-py2.py3-none-any.whl", hash = "sha256:25e2ce09595174d9c97860a95609f9f852c0614ba602de3561e267547f2335e1"}, - {file = "pre_commit-4.5.0.tar.gz", hash = "sha256:dc5a065e932b19fc1d4c653c6939068fe54325af8e741e74e88db4d28a4dd66b"}, -] - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - -[[package]] -name = "prompt-toolkit" -version = "3.0.51" -description = "Library for building powerful interactive command lines in Python" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, - {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, -] - -[package.dependencies] -wcwidth = "*" - -[[package]] -name = "ptyprocess" -version = "0.7.0" -description = "Run a subprocess in a pseudo terminal" -optional = false -python-versions = "*" -groups = ["dev"] -markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" -files = [ - {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, - {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, -] - -[[package]] -name = "pure-eval" -version = "0.2.3" -description = "Safely evaluate AST nodes without side effects" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, - {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, -] - -[package.extras] -tests = ["pytest"] - -[[package]] -name = "pygments" -version = "2.19.2" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["dev", "documentation", "script", "test"] -files = [ - {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, - {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pymdown-extensions" -version = "10.19" -description = "Extension pack for Python Markdown." -optional = false -python-versions = ">=3.9" -groups = ["documentation"] -files = [ - {file = "pymdown_extensions-10.19-py3-none-any.whl", hash = "sha256:dc5f249fc3a1b6d8a6de4634ba8336b88d0942cee75e92b18ac79eaf3503bf7c"}, - {file = "pymdown_extensions-10.19.tar.gz", hash = "sha256:01bb917ea231f9ce14456fa9092cdb95ac3e5bd32202a3ee61dbd5ad2dd9ef9b"}, -] - -[package.dependencies] -markdown = ">=3.6" -pyyaml = "*" - -[package.extras] -extra = ["pygments (>=2.19.1)"] - -[[package]] -name = "pyproject-api" -version = "1.10.0" -description = "API to interact with the python pyproject.toml based projects" -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "pyproject_api-1.10.0-py3-none-any.whl", hash = "sha256:8757c41a79c0f4ab71b99abed52b97ecf66bd20b04fa59da43b5840bac105a09"}, - {file = "pyproject_api-1.10.0.tar.gz", hash = "sha256:40c6f2d82eebdc4afee61c773ed208c04c19db4c4a60d97f8d7be3ebc0bbb330"}, -] - -[package.dependencies] -packaging = ">=25" -tomli = {version = ">=2.3", markers = "python_version < \"3.11\""} - -[package.extras] -docs = ["furo (>=2025.9.25)", "sphinx-autodoc-typehints (>=3.5.1)"] -testing = ["covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)", "setuptools (>=80.9)"] - -[[package]] -name = "pytest" -version = "9.0.2" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.10" -groups = ["test"] -files = [ - {file = "pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b"}, - {file = "pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11"}, -] - -[package.dependencies] -colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} -iniconfig = ">=1.0.1" -packaging = ">=22" -pluggy = ">=1.5,<2" -pygments = ">=2.7.2" -tomli = {version = ">=1", markers = "python_version < \"3.11\""} - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-cov" -version = "7.0.0" -description = "Pytest plugin for measuring coverage." -optional = false -python-versions = ">=3.9" -groups = ["test"] -files = [ - {file = "pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861"}, - {file = "pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1"}, -] - -[package.dependencies] -coverage = {version = ">=7.10.6", extras = ["toml"]} -pluggy = ">=1.2" -pytest = ">=7" - -[package.extras] -testing = ["process-tests", "pytest-xdist", "virtualenv"] - -[[package]] -name = "pytest-datadir" -version = "1.8.0" -description = "pytest plugin for test data directories and files" -optional = false -python-versions = ">=3.8" -groups = ["test"] -files = [ - {file = "pytest_datadir-1.8.0-py3-none-any.whl", hash = "sha256:5c677bc097d907ac71ca418109adc3abe34cf0bddfe6cf78aecfbabd96a15cf0"}, - {file = "pytest_datadir-1.8.0.tar.gz", hash = "sha256:7a15faed76cebe87cc91941dd1920a9a38eba56a09c11e9ddf1434d28a0f78eb"}, -] - -[package.dependencies] -pytest = ">=7.0" - -[package.extras] -dev = ["pre-commit", "pytest-datadir[testing]"] -testing = ["pytest", "tox"] - -[[package]] -name = "pytest-freezer" -version = "0.4.9" -description = "Pytest plugin providing a fixture interface for spulec/freezegun" -optional = false -python-versions = ">=3.6" -groups = ["test"] -files = [ - {file = "pytest_freezer-0.4.9-py3-none-any.whl", hash = "sha256:8b6c50523b7d4aec4590b52bfa5ff766d772ce506e2bf4846c88041ea9ccae59"}, - {file = "pytest_freezer-0.4.9.tar.gz", hash = "sha256:21bf16bc9cc46bf98f94382c4b5c3c389be7056ff0be33029111ae11b3f1c82a"}, -] - -[package.dependencies] -freezegun = ">=1.1" -pytest = ">=3.6" - -[[package]] -name = "pytest-gitconfig" -version = "0.9.0" -description = "Provide a Git config sandbox for testing" -optional = false -python-versions = ">=3.10" -groups = ["test"] -files = [ - {file = "pytest_gitconfig-0.9.0-py3-none-any.whl", hash = "sha256:3d855a9dd5fb3906010dbb1f8161366d4d86b34df8c14021fa012f23de3e5354"}, - {file = "pytest_gitconfig-0.9.0.tar.gz", hash = "sha256:5f9e8a29b4a8e55ddd740216ddb0a8a5e97f1c9c7f6bfdac91863473a8c60f9c"}, -] - -[package.dependencies] -pytest = ">=7.1.2" - -[[package]] -name = "pytest-mock" -version = "3.15.1" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.9" -groups = ["test"] -files = [ - {file = "pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d"}, - {file = "pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "pytest-regressions" -version = "2.8.3" -description = "Easy to use fixtures to write regression tests." -optional = false -python-versions = ">=3.9" -groups = ["test"] -files = [ - {file = "pytest_regressions-2.8.3-py3-none-any.whl", hash = "sha256:72500dd95bde418c850f290a3108dacb56427067f364f7112cb5b16f6d6cc29c"}, - {file = "pytest_regressions-2.8.3.tar.gz", hash = "sha256:1ad90708bee02a3d36c78ef0b6f9692a9a30d312dd828680fd6d2a7235fcd221"}, -] - -[package.dependencies] -pytest = ">=6.2.0" -pytest-datadir = ">=1.7.0" -pyyaml = "*" - -[package.extras] -dataframe = ["numpy", "pandas"] -dev = ["matplotlib", "mypy", "numpy", "pandas", "pillow", "pre-commit", "pyarrow", "restructuredtext-lint", "tox"] -image = ["numpy", "pillow"] -num = ["numpy", "pandas"] - -[[package]] -name = "pytest-xdist" -version = "3.8.0" -description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" -optional = false -python-versions = ">=3.9" -groups = ["test"] -files = [ - {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, - {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, -] - -[package.dependencies] -execnet = ">=2.1" -pytest = ">=7.0.0" - -[package.extras] -psutil = ["psutil (>=3.0)"] -setproctitle = ["setproctitle"] -testing = ["filelock"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["documentation", "test"] -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pyyaml" -version = "6.0.3" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "documentation", "linters", "test"] -files = [ - {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, - {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, - {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, - {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, - {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, - {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, - {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, - {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, - {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, - {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, - {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198"}, - {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b"}, - {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0"}, - {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69"}, - {file = "pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e"}, - {file = "pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c"}, - {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, - {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, - {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, - {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, - {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, - {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, - {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, - {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, - {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, - {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, - {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, - {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, - {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, - {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, - {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, - {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, - {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, - {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, - {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, - {file = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}, - {file = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}, - {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}, - {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}, - {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}, - {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}, - {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}, - {file = "pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}, - {file = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}, - {file = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}, - {file = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}, - {file = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}, - {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}, - {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}, - {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}, - {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}, - {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}, - {file = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}, - {file = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}, - {file = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}, - {file = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}, - {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}, - {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}, - {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}, - {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}, - {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}, - {file = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}, - {file = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}, - {file = "pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da"}, - {file = "pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917"}, - {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9"}, - {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5"}, - {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a"}, - {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926"}, - {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7"}, - {file = "pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0"}, - {file = "pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007"}, - {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, -] - -[[package]] -name = "pyyaml-env-tag" -version = "1.1" -description = "A custom YAML tag for referencing environment variables in YAML files." -optional = false -python-versions = ">=3.9" -groups = ["documentation"] -files = [ - {file = "pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04"}, - {file = "pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff"}, -] - -[package.dependencies] -pyyaml = "*" - -[[package]] -name = "questionary" -version = "2.1.1" -description = "Python library to build pretty command line user prompts ⭐️" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59"}, - {file = "questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d"}, -] - -[package.dependencies] -prompt_toolkit = ">=2.0,<4.0" - -[[package]] -name = "requests" -version = "2.32.5" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.9" -groups = ["documentation"] -files = [ - {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, - {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset_normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rich" -version = "14.2.0" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -groups = ["script"] -files = [ - {file = "rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd"}, - {file = "rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "ruff" -version = "0.14.9" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["linters"] -files = [ - {file = "ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75"}, - {file = "ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2"}, - {file = "ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a"}, - {file = "ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed"}, - {file = "ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b"}, - {file = "ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567"}, - {file = "ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a"}, - {file = "ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8"}, - {file = "ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197"}, - {file = "ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2"}, - {file = "ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84"}, - {file = "ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b"}, -] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["documentation", "test"] -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "stack-data" -version = "0.6.3" -description = "Extract data from python stack frames and tracebacks for informative displays" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, - {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, -] - -[package.dependencies] -asttokens = ">=2.1.0" -executing = ">=1.2.0" -pure-eval = "*" - -[package.extras] -tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] - -[[package]] -name = "termcolor" -version = "3.2.0" -description = "ANSI color formatting for output in terminal" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "termcolor-3.2.0-py3-none-any.whl", hash = "sha256:a10343879eba4da819353c55cb8049b0933890c2ebf9ad5d3ecd2bb32ea96ea6"}, - {file = "termcolor-3.2.0.tar.gz", hash = "sha256:610e6456feec42c4bcd28934a8c87a06c3fa28b01561d46aa09a9881b8622c58"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "tomli" -version = "2.3.0" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.8" -groups = ["dev", "linters", "test"] -files = [ - {file = "tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45"}, - {file = "tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba"}, - {file = "tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf"}, - {file = "tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441"}, - {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845"}, - {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c"}, - {file = "tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456"}, - {file = "tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be"}, - {file = "tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac"}, - {file = "tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22"}, - {file = "tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f"}, - {file = "tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52"}, - {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8"}, - {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6"}, - {file = "tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876"}, - {file = "tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878"}, - {file = "tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b"}, - {file = "tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae"}, - {file = "tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b"}, - {file = "tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf"}, - {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f"}, - {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05"}, - {file = "tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606"}, - {file = "tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999"}, - {file = "tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e"}, - {file = "tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3"}, - {file = "tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc"}, - {file = "tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0"}, - {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879"}, - {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005"}, - {file = "tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463"}, - {file = "tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8"}, - {file = "tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77"}, - {file = "tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf"}, - {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530"}, - {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b"}, - {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67"}, - {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f"}, - {file = "tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0"}, - {file = "tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba"}, - {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"}, - {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, -] -markers = {dev = "python_version == \"3.10\"", linters = "python_version == \"3.10\"", test = "python_full_version <= \"3.11.0a6\""} - -[[package]] -name = "tomlkit" -version = "0.13.3" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"}, - {file = "tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1"}, -] - -[[package]] -name = "tox" -version = "4.32.0" -description = "tox is a generic virtualenv management and test command line tool" -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "tox-4.32.0-py3-none-any.whl", hash = "sha256:451e81dc02ba8d1ed20efd52ee409641ae4b5d5830e008af10fe8823ef1bd551"}, - {file = "tox-4.32.0.tar.gz", hash = "sha256:1ad476b5f4d3679455b89a992849ffc3367560bbc7e9495ee8a3963542e7c8ff"}, -] - -[package.dependencies] -cachetools = ">=6.2" -chardet = ">=5.2" -colorama = ">=0.4.6" -filelock = ">=3.20" -packaging = ">=25" -platformdirs = ">=4.5" -pluggy = ">=1.6" -pyproject-api = ">=1.9.1" -tomli = {version = ">=2.3", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.15", markers = "python_version < \"3.11\""} -virtualenv = ">=20.34" - -[[package]] -name = "traitlets" -version = "5.14.3" -description = "Traitlets Python configuration system" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, - {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, -] - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] - -[[package]] -name = "types-colorama" -version = "0.4.15.20250801" -description = "Typing stubs for colorama" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "types_colorama-0.4.15.20250801-py3-none-any.whl", hash = "sha256:b6e89bd3b250fdad13a8b6a465c933f4a5afe485ea2e2f104d739be50b13eea9"}, - {file = "types_colorama-0.4.15.20250801.tar.gz", hash = "sha256:02565d13d68963d12237d3f330f5ecd622a3179f7b5b14ee7f16146270c357f5"}, -] - -[[package]] -name = "types-deprecated" -version = "1.3.1.20251101" -description = "Typing stubs for Deprecated" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "types_deprecated-1.3.1.20251101-py3-none-any.whl", hash = "sha256:274edcc2a084d3fe31802d3c1379abd630716d3db34e40577e12ad84d6b73134"}, - {file = "types_deprecated-1.3.1.20251101.tar.gz", hash = "sha256:f002d266b73201f46ec6fc712c1f016067ec6cb44357559cdb50c86b010951a7"}, -] - -[[package]] -name = "types-python-dateutil" -version = "2.9.0.20251115" -description = "Typing stubs for python-dateutil" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "types_python_dateutil-2.9.0.20251115-py3-none-any.whl", hash = "sha256:9cf9c1c582019753b8639a081deefd7e044b9fa36bd8217f565c6c4e36ee0624"}, - {file = "types_python_dateutil-2.9.0.20251115.tar.gz", hash = "sha256:8a47f2c3920f52a994056b8786309b43143faa5a64d4cbb2722d6addabdf1a58"}, -] - -[[package]] -name = "types-pyyaml" -version = "6.0.12.20250915" -description = "Typing stubs for PyYAML" -optional = false -python-versions = ">=3.9" -groups = ["linters"] -files = [ - {file = "types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6"}, - {file = "types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3"}, -] - -[[package]] -name = "types-termcolor" -version = "1.1.6.2" -description = "Typing stubs for termcolor" -optional = false -python-versions = "*" -groups = ["linters"] -files = [ - {file = "types-termcolor-1.1.6.2.tar.gz", hash = "sha256:d8f0f69cf5552cc59ce75aa5172937cec9b320c17453adefe4168b93d16daad6"}, - {file = "types_termcolor-1.1.6.2-py3-none-any.whl", hash = "sha256:44c4c762c54a90d99b5c1033ef008aaa5610056d31d5c66b9288a942682a64d7"}, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -description = "Backported and Experimental Type Hints for Python 3.9+" -optional = false -python-versions = ">=3.9" -groups = ["main", "dev", "linters", "test"] -files = [ - {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, - {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, -] -markers = {main = "python_version == \"3.10\"", dev = "python_version < \"3.12\"", test = "python_version == \"3.10\""} - -[[package]] -name = "urllib3" -version = "2.6.2" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -groups = ["documentation"] -files = [ - {file = "urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"}, - {file = "urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797"}, -] - -[package.extras] -brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] - -[[package]] -name = "virtualenv" -version = "20.35.4" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.8" -groups = ["dev", "linters"] -files = [ - {file = "virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b"}, - {file = "virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<5" -typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] - -[[package]] -name = "watchdog" -version = "6.0.0" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.9" -groups = ["documentation"] -files = [ - {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, - {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, - {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, - {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, - {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, - {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, - {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, - {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, - {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, - {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, - {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "wcwidth" -version = "0.2.14" -description = "Measures the displayed width of unicode strings in a terminal" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -files = [ - {file = "wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1"}, - {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"}, -] - -[[package]] -name = "wrapt" -version = "2.0.1" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "wrapt-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:64b103acdaa53b7caf409e8d45d39a8442fe6dcfec6ba3f3d141e0cc2b5b4dbd"}, - {file = "wrapt-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91bcc576260a274b169c3098e9a3519fb01f2989f6d3d386ef9cbf8653de1374"}, - {file = "wrapt-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab594f346517010050126fcd822697b25a7031d815bb4fbc238ccbe568216489"}, - {file = "wrapt-2.0.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:36982b26f190f4d737f04a492a68accbfc6fa042c3f42326fdfbb6c5b7a20a31"}, - {file = "wrapt-2.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23097ed8bc4c93b7bf36fa2113c6c733c976316ce0ee2c816f64ca06102034ef"}, - {file = "wrapt-2.0.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8bacfe6e001749a3b64db47bcf0341da757c95959f592823a93931a422395013"}, - {file = "wrapt-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8ec3303e8a81932171f455f792f8df500fc1a09f20069e5c16bd7049ab4e8e38"}, - {file = "wrapt-2.0.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:3f373a4ab5dbc528a94334f9fe444395b23c2f5332adab9ff4ea82f5a9e33bc1"}, - {file = "wrapt-2.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f49027b0b9503bf6c8cdc297ca55006b80c2f5dd36cecc72c6835ab6e10e8a25"}, - {file = "wrapt-2.0.1-cp310-cp310-win32.whl", hash = "sha256:8330b42d769965e96e01fa14034b28a2a7600fbf7e8f0cc90ebb36d492c993e4"}, - {file = "wrapt-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:1218573502a8235bb8a7ecaed12736213b22dcde9feab115fa2989d42b5ded45"}, - {file = "wrapt-2.0.1-cp310-cp310-win_arm64.whl", hash = "sha256:eda8e4ecd662d48c28bb86be9e837c13e45c58b8300e43ba3c9b4fa9900302f7"}, - {file = "wrapt-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e17283f533a0d24d6e5429a7d11f250a58d28b4ae5186f8f47853e3e70d2590"}, - {file = "wrapt-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85df8d92158cb8f3965aecc27cf821461bb5f40b450b03facc5d9f0d4d6ddec6"}, - {file = "wrapt-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1be685ac7700c966b8610ccc63c3187a72e33cab53526a27b2a285a662cd4f7"}, - {file = "wrapt-2.0.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:df0b6d3b95932809c5b3fecc18fda0f1e07452d05e2662a0b35548985f256e28"}, - {file = "wrapt-2.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da7384b0e5d4cae05c97cd6f94faaf78cc8b0f791fc63af43436d98c4ab37bb"}, - {file = "wrapt-2.0.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ec65a78fbd9d6f083a15d7613b2800d5663dbb6bb96003899c834beaa68b242c"}, - {file = "wrapt-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7de3cc939be0e1174969f943f3b44e0d79b6f9a82198133a5b7fc6cc92882f16"}, - {file = "wrapt-2.0.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fb1a5b72cbd751813adc02ef01ada0b0d05d3dcbc32976ce189a1279d80ad4a2"}, - {file = "wrapt-2.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3fa272ca34332581e00bf7773e993d4f632594eb2d1b0b162a9038df0fd971dd"}, - {file = "wrapt-2.0.1-cp311-cp311-win32.whl", hash = "sha256:fc007fdf480c77301ab1afdbb6ab22a5deee8885f3b1ed7afcb7e5e84a0e27be"}, - {file = "wrapt-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:47434236c396d04875180171ee1f3815ca1eada05e24a1ee99546320d54d1d1b"}, - {file = "wrapt-2.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:837e31620e06b16030b1d126ed78e9383815cbac914693f54926d816d35d8edf"}, - {file = "wrapt-2.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1fdbb34da15450f2b1d735a0e969c24bdb8d8924892380126e2a293d9902078c"}, - {file = "wrapt-2.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d32794fe940b7000f0519904e247f902f0149edbe6316c710a8562fb6738841"}, - {file = "wrapt-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:386fb54d9cd903ee0012c09291336469eb7b244f7183d40dc3e86a16a4bace62"}, - {file = "wrapt-2.0.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7b219cb2182f230676308cdcacd428fa837987b89e4b7c5c9025088b8a6c9faf"}, - {file = "wrapt-2.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:641e94e789b5f6b4822bb8d8ebbdfc10f4e4eae7756d648b717d980f657a9eb9"}, - {file = "wrapt-2.0.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe21b118b9f58859b5ebaa4b130dee18669df4bd111daad082b7beb8799ad16b"}, - {file = "wrapt-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17fb85fa4abc26a5184d93b3efd2dcc14deb4b09edcdb3535a536ad34f0b4dba"}, - {file = "wrapt-2.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b89ef9223d665ab255ae42cc282d27d69704d94be0deffc8b9d919179a609684"}, - {file = "wrapt-2.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a453257f19c31b31ba593c30d997d6e5be39e3b5ad9148c2af5a7314061c63eb"}, - {file = "wrapt-2.0.1-cp312-cp312-win32.whl", hash = "sha256:3e271346f01e9c8b1130a6a3b0e11908049fe5be2d365a5f402778049147e7e9"}, - {file = "wrapt-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:2da620b31a90cdefa9cd0c2b661882329e2e19d1d7b9b920189956b76c564d75"}, - {file = "wrapt-2.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:aea9c7224c302bc8bfc892b908537f56c430802560e827b75ecbde81b604598b"}, - {file = "wrapt-2.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:47b0f8bafe90f7736151f61482c583c86b0693d80f075a58701dd1549b0010a9"}, - {file = "wrapt-2.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cbeb0971e13b4bd81d34169ed57a6dda017328d1a22b62fda45e1d21dd06148f"}, - {file = "wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218"}, - {file = "wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9"}, - {file = "wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c"}, - {file = "wrapt-2.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:98d873ed6c8b4ee2418f7afce666751854d6d03e3c0ec2a399bb039cd2ae89db"}, - {file = "wrapt-2.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9e850f5b7fc67af856ff054c71690d54fa940c3ef74209ad9f935b4f66a0233"}, - {file = "wrapt-2.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e505629359cb5f751e16e30cf3f91a1d3ddb4552480c205947da415d597f7ac2"}, - {file = "wrapt-2.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2879af909312d0baf35f08edeea918ee3af7ab57c37fe47cb6a373c9f2749c7b"}, - {file = "wrapt-2.0.1-cp313-cp313-win32.whl", hash = "sha256:d67956c676be5a24102c7407a71f4126d30de2a569a1c7871c9f3cabc94225d7"}, - {file = "wrapt-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9ca66b38dd642bf90c59b6738af8070747b610115a39af2498535f62b5cdc1c3"}, - {file = "wrapt-2.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:5a4939eae35db6b6cec8e7aa0e833dcca0acad8231672c26c2a9ab7a0f8ac9c8"}, - {file = "wrapt-2.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a52f93d95c8d38fed0669da2ebdb0b0376e895d84596a976c15a9eb45e3eccb3"}, - {file = "wrapt-2.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e54bbf554ee29fcceee24fa41c4d091398b911da6e7f5d7bffda963c9aed2e1"}, - {file = "wrapt-2.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:908f8c6c71557f4deaa280f55d0728c3bca0960e8c3dd5ceeeafb3c19942719d"}, - {file = "wrapt-2.0.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e2f84e9af2060e3904a32cea9bb6db23ce3f91cfd90c6b426757cf7cc01c45c7"}, - {file = "wrapt-2.0.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3612dc06b436968dfb9142c62e5dfa9eb5924f91120b3c8ff501ad878f90eb3"}, - {file = "wrapt-2.0.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d2d947d266d99a1477cd005b23cbd09465276e302515e122df56bb9511aca1b"}, - {file = "wrapt-2.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7d539241e87b650cbc4c3ac9f32c8d1ac8a54e510f6dca3f6ab60dcfd48c9b10"}, - {file = "wrapt-2.0.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4811e15d88ee62dbf5c77f2c3ff3932b1e3ac92323ba3912f51fc4016ce81ecf"}, - {file = "wrapt-2.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c1c91405fcf1d501fa5d55df21e58ea49e6b879ae829f1039faaf7e5e509b41e"}, - {file = "wrapt-2.0.1-cp313-cp313t-win32.whl", hash = "sha256:e76e3f91f864e89db8b8d2a8311d57df93f01ad6bb1e9b9976d1f2e83e18315c"}, - {file = "wrapt-2.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:83ce30937f0ba0d28818807b303a412440c4b63e39d3d8fc036a94764b728c92"}, - {file = "wrapt-2.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:4b55cacc57e1dc2d0991dbe74c6419ffd415fb66474a02335cb10efd1aa3f84f"}, - {file = "wrapt-2.0.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5e53b428f65ece6d9dad23cb87e64506392b720a0b45076c05354d27a13351a1"}, - {file = "wrapt-2.0.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ad3ee9d0f254851c71780966eb417ef8e72117155cff04821ab9b60549694a55"}, - {file = "wrapt-2.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7b822c61ed04ee6ad64bc90d13368ad6eb094db54883b5dde2182f67a7f22c0"}, - {file = "wrapt-2.0.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7164a55f5e83a9a0b031d3ffab4d4e36bbec42e7025db560f225489fa929e509"}, - {file = "wrapt-2.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e60690ba71a57424c8d9ff28f8d006b7ad7772c22a4af432188572cd7fa004a1"}, - {file = "wrapt-2.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3cd1a4bd9a7a619922a8557e1318232e7269b5fb69d4ba97b04d20450a6bf970"}, - {file = "wrapt-2.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b4c2e3d777e38e913b8ce3a6257af72fb608f86a1df471cb1d4339755d0a807c"}, - {file = "wrapt-2.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3d366aa598d69416b5afedf1faa539fac40c1d80a42f6b236c88c73a3c8f2d41"}, - {file = "wrapt-2.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c235095d6d090aa903f1db61f892fffb779c1eaeb2a50e566b52001f7a0f66ed"}, - {file = "wrapt-2.0.1-cp314-cp314-win32.whl", hash = "sha256:bfb5539005259f8127ea9c885bdc231978c06b7a980e63a8a61c8c4c979719d0"}, - {file = "wrapt-2.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:4ae879acc449caa9ed43fc36ba08392b9412ee67941748d31d94e3cedb36628c"}, - {file = "wrapt-2.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:8639b843c9efd84675f1e100ed9e99538ebea7297b62c4b45a7042edb84db03e"}, - {file = "wrapt-2.0.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:9219a1d946a9b32bb23ccae66bdb61e35c62773ce7ca6509ceea70f344656b7b"}, - {file = "wrapt-2.0.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fa4184e74197af3adad3c889a1af95b53bb0466bced92ea99a0c014e48323eec"}, - {file = "wrapt-2.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c5ef2f2b8a53b7caee2f797ef166a390fef73979b15778a4a153e4b5fedce8fa"}, - {file = "wrapt-2.0.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e042d653a4745be832d5aa190ff80ee4f02c34b21f4b785745eceacd0907b815"}, - {file = "wrapt-2.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2afa23318136709c4b23d87d543b425c399887b4057936cd20386d5b1422b6fa"}, - {file = "wrapt-2.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c72328f668cf4c503ffcf9434c2b71fdd624345ced7941bc6693e61bbe36bef"}, - {file = "wrapt-2.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3793ac154afb0e5b45d1233cb94d354ef7a983708cc3bb12563853b1d8d53747"}, - {file = "wrapt-2.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:fec0d993ecba3991645b4857837277469c8cc4c554a7e24d064d1ca291cfb81f"}, - {file = "wrapt-2.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:949520bccc1fa227274da7d03bf238be15389cd94e32e4297b92337df9b7a349"}, - {file = "wrapt-2.0.1-cp314-cp314t-win32.whl", hash = "sha256:be9e84e91d6497ba62594158d3d31ec0486c60055c49179edc51ee43d095f79c"}, - {file = "wrapt-2.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:61c4956171c7434634401db448371277d07032a81cc21c599c22953374781395"}, - {file = "wrapt-2.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:35cdbd478607036fee40273be8ed54a451f5f23121bd9d4be515158f9498f7ad"}, - {file = "wrapt-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:90897ea1cf0679763b62e79657958cd54eae5659f6360fc7d2ccc6f906342183"}, - {file = "wrapt-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:50844efc8cdf63b2d90cd3d62d4947a28311e6266ce5235a219d21b195b4ec2c"}, - {file = "wrapt-2.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49989061a9977a8cbd6d20f2efa813f24bf657c6990a42967019ce779a878dbf"}, - {file = "wrapt-2.0.1-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:09c7476ab884b74dce081ad9bfd07fe5822d8600abade571cb1f66d5fc915af6"}, - {file = "wrapt-2.0.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1a8a09a004ef100e614beec82862d11fc17d601092c3599afd22b1f36e4137e"}, - {file = "wrapt-2.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:89a82053b193837bf93c0f8a57ded6e4b6d88033a499dadff5067e912c2a41e9"}, - {file = "wrapt-2.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f26f8e2ca19564e2e1fdbb6a0e47f36e0efbab1acc31e15471fad88f828c75f6"}, - {file = "wrapt-2.0.1-cp38-cp38-win32.whl", hash = "sha256:115cae4beed3542e37866469a8a1f2b9ec549b4463572b000611e9946b86e6f6"}, - {file = "wrapt-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:c4012a2bd37059d04f8209916aa771dfb564cccb86079072bdcd48a308b6a5c5"}, - {file = "wrapt-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:68424221a2dc00d634b54f92441914929c5ffb1c30b3b837343978343a3512a3"}, - {file = "wrapt-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd1a18f5a797fe740cb3d7a0e853a8ce6461cc62023b630caec80171a6b8097"}, - {file = "wrapt-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fb3a86e703868561c5cad155a15c36c716e1ab513b7065bd2ac8ed353c503333"}, - {file = "wrapt-2.0.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5dc1b852337c6792aa111ca8becff5bacf576bf4a0255b0f05eb749da6a1643e"}, - {file = "wrapt-2.0.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c046781d422f0830de6329fa4b16796096f28a92c8aef3850674442cdcb87b7f"}, - {file = "wrapt-2.0.1-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f73f9f7a0ebd0db139253d27e5fc8d2866ceaeef19c30ab5d69dcbe35e1a6981"}, - {file = "wrapt-2.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b667189cf8efe008f55bbda321890bef628a67ab4147ebf90d182f2dadc78790"}, - {file = "wrapt-2.0.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:a9a83618c4f0757557c077ef71d708ddd9847ed66b7cc63416632af70d3e2308"}, - {file = "wrapt-2.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e9b121e9aeb15df416c2c960b8255a49d44b4038016ee17af03975992d03931"}, - {file = "wrapt-2.0.1-cp39-cp39-win32.whl", hash = "sha256:1f186e26ea0a55f809f232e92cc8556a0977e00183c3ebda039a807a42be1494"}, - {file = "wrapt-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:bf4cb76f36be5de950ce13e22e7fdf462b35b04665a12b64f3ac5c1bbbcf3728"}, - {file = "wrapt-2.0.1-cp39-cp39-win_arm64.whl", hash = "sha256:d6cc985b9c8b235bd933990cdbf0f891f8e010b65a3911f7a55179cd7b0fc57b"}, - {file = "wrapt-2.0.1-py3-none-any.whl", hash = "sha256:4d2ce1bf1a48c5277d7969259232b57645aae5686dba1eaeade39442277afbca"}, - {file = "wrapt-2.0.1.tar.gz", hash = "sha256:9c9c635e78497cacb81e84f8b11b23e0aacac7a136e73b8e5b2109a1d9fc468f"}, -] - -[package.extras] -dev = ["pytest", "setuptools"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.10,<4.0" -content-hash = "694d9328c2fd7b1aaa342efe590802db4ddf915a91020276a8b28b2e025d5842" diff --git a/pyproject.toml b/pyproject.toml index 76896d3500..ec456ed487 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -117,8 +117,8 @@ script = [ ] [build-system] -requires = ["poetry-core>=2.2"] -build-backend = "poetry.core.masonry.api" +requires = ["uv_build >= 0.9.17, <0.10.0"] +build-backend = "uv_build" [tool.commitizen] @@ -132,11 +132,10 @@ version_files = [ version_scheme = "pep440" -[tool.poetry] -packages = [{ include = "commitizen" }, { include = "commitizen/py.typed" }] - -[tool.poetry.requires-plugins] -"poethepoet" = ">=0.32.2" +[tool.uv.build-backend] +module-name = "commitizen" +module-root = "" +include = ["commitizen/py.typed"] [tool.coverage] [tool.coverage.report] @@ -246,7 +245,7 @@ check-hidden = true ignore-words-list = 'asend' [tool.poe] -poetry_command = "" +executor.type = "uv" [tool.poe.tasks] format.help = "Format the code" @@ -256,7 +255,7 @@ lint.help = "Lint the code" lint.sequence = [{ cmd = "ruff check" }, { cmd = "mypy" }] check-commit.help = "Check the commit messages" -check-commit.cmd = "poetry run cz --no-raise 3 check --rev-range origin/master.." +check-commit.cmd = "uv run cz --no-raise 3 check --rev-range origin/master.." test.help = "Run the test suite" test.cmd = "pytest -n 3 --dist=loadfile" diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000000..d7a1b2511c --- /dev/null +++ b/uv.lock @@ -0,0 +1,1723 @@ +version = 1 +revision = 3 +requires-python = ">=3.10, <4.0" +resolution-markers = [ + "python_full_version >= '3.11'", + "python_full_version < '3.11'", +] + +[[package]] +name = "argcomplete" +version = "3.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/61/0b9ae6399dd4a58d8c1b1dc5a27d6f2808023d0b5dd3104bb99f45a33ff6/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c", size = 73754, upload-time = "2025-10-20T03:33:34.741Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce", size = 43846, upload-time = "2025-10-20T03:33:33.021Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "backrefs" +version = "6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/e3/bb3a439d5cb255c4774724810ad8073830fac9c9dee123555820c1bcc806/backrefs-6.1.tar.gz", hash = "sha256:3bba1749aafe1db9b915f00e0dd166cba613b6f788ffd63060ac3485dc9be231", size = 7011962, upload-time = "2025-11-15T14:52:08.323Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/ee/c216d52f58ea75b5e1841022bbae24438b19834a29b163cb32aa3a2a7c6e/backrefs-6.1-py310-none-any.whl", hash = "sha256:2a2ccb96302337ce61ee4717ceacfbf26ba4efb1d55af86564b8bbaeda39cac1", size = 381059, upload-time = "2025-11-15T14:51:59.758Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9a/8da246d988ded941da96c7ed945d63e94a445637eaad985a0ed88787cb89/backrefs-6.1-py311-none-any.whl", hash = "sha256:e82bba3875ee4430f4de4b6db19429a27275d95a5f3773c57e9e18abc23fd2b7", size = 392854, upload-time = "2025-11-15T14:52:01.194Z" }, + { url = "https://files.pythonhosted.org/packages/37/c9/fd117a6f9300c62bbc33bc337fd2b3c6bfe28b6e9701de336b52d7a797ad/backrefs-6.1-py312-none-any.whl", hash = "sha256:c64698c8d2269343d88947c0735cb4b78745bd3ba590e10313fbf3f78c34da5a", size = 398770, upload-time = "2025-11-15T14:52:02.584Z" }, + { url = "https://files.pythonhosted.org/packages/eb/95/7118e935b0b0bd3f94dfec2d852fd4e4f4f9757bdb49850519acd245cd3a/backrefs-6.1-py313-none-any.whl", hash = "sha256:4c9d3dc1e2e558965202c012304f33d4e0e477e1c103663fd2c3cc9bb18b0d05", size = 400726, upload-time = "2025-11-15T14:52:04.093Z" }, + { url = "https://files.pythonhosted.org/packages/1d/72/6296bad135bfafd3254ae3648cd152980a424bd6fed64a101af00cc7ba31/backrefs-6.1-py314-none-any.whl", hash = "sha256:13eafbc9ccd5222e9c1f0bec563e6d2a6d21514962f11e7fc79872fd56cbc853", size = 412584, upload-time = "2025-11-15T14:52:05.233Z" }, + { url = "https://files.pythonhosted.org/packages/02/e3/a4fa1946722c4c7b063cc25043a12d9ce9b4323777f89643be74cef2993c/backrefs-6.1-py39-none-any.whl", hash = "sha256:a9e99b8a4867852cad177a6430e31b0f6e495d65f8c6c134b68c14c3c95bf4b0", size = 381058, upload-time = "2025-11-15T14:52:06.698Z" }, +] + +[[package]] +name = "cachetools" +version = "6.2.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/1d/ede8680603f6016887c062a2cf4fc8fdba905866a3ab8831aa8aa651320c/cachetools-6.2.4.tar.gz", hash = "sha256:82c5c05585e70b6ba2d3ae09ea60b79548872185d2f24ae1f2709d37299fd607", size = 31731, upload-time = "2025-12-15T18:24:53.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/fc/1d7b80d0eb7b714984ce40efc78859c022cd930e402f599d8ca9e39c78a4/cachetools-6.2.4-py3-none-any.whl", hash = "sha256:69a7a52634fed8b8bf6e24a050fb60bff1c9bd8f6d24572b99c32d4e71e62a51", size = 11551, upload-time = "2025-12-15T18:24:52.332Z" }, +] + +[[package]] +name = "certifi" +version = "2025.11.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, +] + +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + +[[package]] +name = "chardet" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, + { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, + { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, + { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, + { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, + { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, + { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, + { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, + { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, + { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, + { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, + { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, + { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, + { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, + { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, + { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, + { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, + { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, + { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, + { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "commitizen" +version = "4.11.0" +source = { editable = "." } +dependencies = [ + { name = "argcomplete" }, + { name = "charset-normalizer" }, + { name = "colorama" }, + { name = "decli" }, + { name = "deprecated" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "prompt-toolkit" }, + { name = "pyyaml" }, + { name = "questionary" }, + { name = "termcolor" }, + { name = "tomlkit" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] + +[package.dev-dependencies] +dev = [ + { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "ipython", version = "9.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "poethepoet" }, + { name = "tox" }, +] +documentation = [ + { name = "mkdocs" }, + { name = "mkdocs-material" }, +] +linters = [ + { name = "mypy" }, + { name = "pre-commit" }, + { name = "ruff" }, + { name = "types-colorama" }, + { name = "types-deprecated" }, + { name = "types-python-dateutil" }, + { name = "types-pyyaml" }, + { name = "types-termcolor" }, +] +script = [ + { name = "rich" }, +] +test = [ + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-freezer" }, + { name = "pytest-gitconfig" }, + { name = "pytest-mock" }, + { name = "pytest-regressions" }, + { name = "pytest-xdist" }, +] + +[package.metadata] +requires-dist = [ + { name = "argcomplete", specifier = ">=1.12.1,<3.7" }, + { name = "charset-normalizer", specifier = ">=2.1.0,<4" }, + { name = "colorama", specifier = ">=0.4.1,<1.0" }, + { name = "decli", specifier = ">=0.6.0,<1.0" }, + { name = "deprecated", specifier = ">=1.2.13,<2" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10'", specifier = ">=8.0.0,<8.7.0" }, + { name = "jinja2", specifier = ">=2.10.3" }, + { name = "packaging", specifier = ">=19" }, + { name = "prompt-toolkit", specifier = "!=3.0.52" }, + { name = "pyyaml", specifier = ">=3.8" }, + { name = "questionary", specifier = ">=2.0,<3.0" }, + { name = "termcolor", specifier = ">=1.1.0,<4.0.0" }, + { name = "tomlkit", specifier = ">=0.8.0,<1.0.0" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.0.1,<5.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "ipython", specifier = ">=8.0" }, + { name = "poethepoet", specifier = ">=0.34.0" }, + { name = "tox", specifier = ">4" }, +] +documentation = [ + { name = "mkdocs", specifier = ">=1.4.2" }, + { name = "mkdocs-material", specifier = ">=9.1.6" }, +] +linters = [ + { name = "mypy", specifier = ">=1.16.0" }, + { name = "pre-commit", specifier = ">=3.2.0" }, + { name = "ruff", specifier = ">=0.11.5" }, + { name = "types-colorama", specifier = ">=0.4.15.20240311" }, + { name = "types-deprecated", specifier = ">=1.2.9.2" }, + { name = "types-python-dateutil", specifier = ">=2.8.19.13" }, + { name = "types-pyyaml", specifier = ">=5.4.3" }, + { name = "types-termcolor", specifier = ">=0.1.1" }, +] +script = [{ name = "rich", specifier = ">=13.7.1" }] +test = [ + { name = "pytest", specifier = ">=7.2" }, + { name = "pytest-cov", specifier = ">=4" }, + { name = "pytest-freezer", specifier = ">=0.4.6" }, + { name = "pytest-gitconfig", specifier = ">=0.9.0" }, + { name = "pytest-mock", specifier = ">=3.10" }, + { name = "pytest-regressions", specifier = ">=2.4.0" }, + { name = "pytest-xdist", specifier = ">=3.1.0" }, +] + +[[package]] +name = "coverage" +version = "7.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/45/2c665ca77ec32ad67e25c77daf1cee28ee4558f3bc571cdbaf88a00b9f23/coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936", size = 820905, upload-time = "2025-12-08T13:14:38.055Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/08/bdd7ccca14096f7eb01412b87ac11e5d16e4cb54b6e328afc9dee8bdaec1/coverage-7.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:02d9fb9eccd48f6843c98a37bd6817462f130b86da8660461e8f5e54d4c06070", size = 217979, upload-time = "2025-12-08T13:12:14.505Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/d1302e3416298a28b5663ae1117546a745d9d19fde7e28402b2c5c3e2109/coverage-7.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:367449cf07d33dc216c083f2036bb7d976c6e4903ab31be400ad74ad9f85ce98", size = 218496, upload-time = "2025-12-08T13:12:16.237Z" }, + { url = "https://files.pythonhosted.org/packages/07/26/d36c354c8b2a320819afcea6bffe72839efd004b98d1d166b90801d49d57/coverage-7.13.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cdb3c9f8fef0a954c632f64328a3935988d33a6604ce4bf67ec3e39670f12ae5", size = 245237, upload-time = "2025-12-08T13:12:17.858Z" }, + { url = "https://files.pythonhosted.org/packages/91/52/be5e85631e0eec547873d8b08dd67a5f6b111ecfe89a86e40b89b0c1c61c/coverage-7.13.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d10fd186aac2316f9bbb46ef91977f9d394ded67050ad6d84d94ed6ea2e8e54e", size = 247061, upload-time = "2025-12-08T13:12:19.132Z" }, + { url = "https://files.pythonhosted.org/packages/0f/45/a5e8fa0caf05fbd8fa0402470377bff09cc1f026d21c05c71e01295e55ab/coverage-7.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f88ae3e69df2ab62fb0bc5219a597cb890ba5c438190ffa87490b315190bb33", size = 248928, upload-time = "2025-12-08T13:12:20.702Z" }, + { url = "https://files.pythonhosted.org/packages/f5/42/ffb5069b6fd1b95fae482e02f3fecf380d437dd5a39bae09f16d2e2e7e01/coverage-7.13.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4be718e51e86f553bcf515305a158a1cd180d23b72f07ae76d6017c3cc5d791", size = 245931, upload-time = "2025-12-08T13:12:22.243Z" }, + { url = "https://files.pythonhosted.org/packages/95/6e/73e809b882c2858f13e55c0c36e94e09ce07e6165d5644588f9517efe333/coverage-7.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a00d3a393207ae12f7c49bb1c113190883b500f48979abb118d8b72b8c95c032", size = 246968, upload-time = "2025-12-08T13:12:23.52Z" }, + { url = "https://files.pythonhosted.org/packages/87/08/64ebd9e64b6adb8b4a4662133d706fbaccecab972e0b3ccc23f64e2678ad/coverage-7.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a7b1cd820e1b6116f92c6128f1188e7afe421c7e1b35fa9836b11444e53ebd9", size = 244972, upload-time = "2025-12-08T13:12:24.781Z" }, + { url = "https://files.pythonhosted.org/packages/12/97/f4d27c6fe0cb375a5eced4aabcaef22de74766fb80a3d5d2015139e54b22/coverage-7.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:37eee4e552a65866f15dedd917d5e5f3d59805994260720821e2c1b51ac3248f", size = 245241, upload-time = "2025-12-08T13:12:28.041Z" }, + { url = "https://files.pythonhosted.org/packages/0c/94/42f8ae7f633bf4c118bf1038d80472f9dade88961a466f290b81250f7ab7/coverage-7.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62d7c4f13102148c78d7353c6052af6d899a7f6df66a32bddcc0c0eb7c5326f8", size = 245847, upload-time = "2025-12-08T13:12:29.337Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2f/6369ca22b6b6d933f4f4d27765d313d8914cc4cce84f82a16436b1a233db/coverage-7.13.0-cp310-cp310-win32.whl", hash = "sha256:24e4e56304fdb56f96f80eabf840eab043b3afea9348b88be680ec5986780a0f", size = 220573, upload-time = "2025-12-08T13:12:30.905Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dc/a6a741e519acceaeccc70a7f4cfe5d030efc4b222595f0677e101af6f1f3/coverage-7.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:74c136e4093627cf04b26a35dab8cbfc9b37c647f0502fc313376e11726ba303", size = 221509, upload-time = "2025-12-08T13:12:32.09Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dc/888bf90d8b1c3d0b4020a40e52b9f80957d75785931ec66c7dfaccc11c7d/coverage-7.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820", size = 218104, upload-time = "2025-12-08T13:12:33.333Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ea/069d51372ad9c380214e86717e40d1a743713a2af191cfba30a0911b0a4a/coverage-7.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f", size = 218606, upload-time = "2025-12-08T13:12:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/68/09/77b1c3a66c2aa91141b6c4471af98e5b1ed9b9e6d17255da5eb7992299e3/coverage-7.13.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96", size = 248999, upload-time = "2025-12-08T13:12:36.02Z" }, + { url = "https://files.pythonhosted.org/packages/0a/32/2e2f96e9d5691eaf1181d9040f850b8b7ce165ea10810fd8e2afa534cef7/coverage-7.13.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259", size = 250925, upload-time = "2025-12-08T13:12:37.221Z" }, + { url = "https://files.pythonhosted.org/packages/7b/45/b88ddac1d7978859b9a39a8a50ab323186148f1d64bc068f86fc77706321/coverage-7.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb", size = 253032, upload-time = "2025-12-08T13:12:38.763Z" }, + { url = "https://files.pythonhosted.org/packages/71/cb/e15513f94c69d4820a34b6bf3d2b1f9f8755fa6021be97c7065442d7d653/coverage-7.13.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9", size = 249134, upload-time = "2025-12-08T13:12:40.382Z" }, + { url = "https://files.pythonhosted.org/packages/09/61/d960ff7dc9e902af3310ce632a875aaa7860f36d2bc8fc8b37ee7c1b82a5/coverage-7.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030", size = 250731, upload-time = "2025-12-08T13:12:41.992Z" }, + { url = "https://files.pythonhosted.org/packages/98/34/c7c72821794afc7c7c2da1db8f00c2c98353078aa7fb6b5ff36aac834b52/coverage-7.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833", size = 248795, upload-time = "2025-12-08T13:12:43.331Z" }, + { url = "https://files.pythonhosted.org/packages/0a/5b/e0f07107987a43b2def9aa041c614ddb38064cbf294a71ef8c67d43a0cdd/coverage-7.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8", size = 248514, upload-time = "2025-12-08T13:12:44.546Z" }, + { url = "https://files.pythonhosted.org/packages/71/c2/c949c5d3b5e9fc6dd79e1b73cdb86a59ef14f3709b1d72bf7668ae12e000/coverage-7.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753", size = 249424, upload-time = "2025-12-08T13:12:45.759Z" }, + { url = "https://files.pythonhosted.org/packages/11/f1/bbc009abd6537cec0dffb2cc08c17a7f03de74c970e6302db4342a6e05af/coverage-7.13.0-cp311-cp311-win32.whl", hash = "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b", size = 220597, upload-time = "2025-12-08T13:12:47.378Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/d9977f2fb51c10fbaed0718ce3d0a8541185290b981f73b1d27276c12d91/coverage-7.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe", size = 221536, upload-time = "2025-12-08T13:12:48.7Z" }, + { url = "https://files.pythonhosted.org/packages/be/ad/3fcf43fd96fb43e337a3073dea63ff148dcc5c41ba7a14d4c7d34efb2216/coverage-7.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7", size = 220206, upload-time = "2025-12-08T13:12:50.365Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f1/2619559f17f31ba00fc40908efd1fbf1d0a5536eb75dc8341e7d660a08de/coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf", size = 218274, upload-time = "2025-12-08T13:12:52.095Z" }, + { url = "https://files.pythonhosted.org/packages/2b/11/30d71ae5d6e949ff93b2a79a2c1b4822e00423116c5c6edfaeef37301396/coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f", size = 218638, upload-time = "2025-12-08T13:12:53.418Z" }, + { url = "https://files.pythonhosted.org/packages/79/c2/fce80fc6ded8d77e53207489d6065d0fed75db8951457f9213776615e0f5/coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb", size = 250129, upload-time = "2025-12-08T13:12:54.744Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b6/51b5d1eb6fcbb9a1d5d6984e26cbe09018475c2922d554fd724dd0f056ee/coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621", size = 252885, upload-time = "2025-12-08T13:12:56.401Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f8/972a5affea41de798691ab15d023d3530f9f56a72e12e243f35031846ff7/coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74", size = 253974, upload-time = "2025-12-08T13:12:57.718Z" }, + { url = "https://files.pythonhosted.org/packages/8a/56/116513aee860b2c7968aa3506b0f59b22a959261d1dbf3aea7b4450a7520/coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57", size = 250538, upload-time = "2025-12-08T13:12:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/d6/75/074476d64248fbadf16dfafbf93fdcede389ec821f74ca858d7c87d2a98c/coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8", size = 251912, upload-time = "2025-12-08T13:13:00.604Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d2/aa4f8acd1f7c06024705c12609d8698c51b27e4d635d717cd1934c9668e2/coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d", size = 250054, upload-time = "2025-12-08T13:13:01.892Z" }, + { url = "https://files.pythonhosted.org/packages/19/98/8df9e1af6a493b03694a1e8070e024e7d2cdc77adedc225a35e616d505de/coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b", size = 249619, upload-time = "2025-12-08T13:13:03.236Z" }, + { url = "https://files.pythonhosted.org/packages/d8/71/f8679231f3353018ca66ef647fa6fe7b77e6bff7845be54ab84f86233363/coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd", size = 251496, upload-time = "2025-12-08T13:13:04.511Z" }, + { url = "https://files.pythonhosted.org/packages/04/86/9cb406388034eaf3c606c22094edbbb82eea1fa9d20c0e9efadff20d0733/coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef", size = 220808, upload-time = "2025-12-08T13:13:06.422Z" }, + { url = "https://files.pythonhosted.org/packages/1c/59/af483673df6455795daf5f447c2f81a3d2fcfc893a22b8ace983791f6f34/coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae", size = 221616, upload-time = "2025-12-08T13:13:07.95Z" }, + { url = "https://files.pythonhosted.org/packages/64/b0/959d582572b30a6830398c60dd419c1965ca4b5fb38ac6b7093a0d50ca8d/coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080", size = 220261, upload-time = "2025-12-08T13:13:09.581Z" }, + { url = "https://files.pythonhosted.org/packages/7c/cc/bce226595eb3bf7d13ccffe154c3c487a22222d87ff018525ab4dd2e9542/coverage-7.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:28ee1c96109974af104028a8ef57cec21447d42d0e937c0275329272e370ebcf", size = 218297, upload-time = "2025-12-08T13:13:10.977Z" }, + { url = "https://files.pythonhosted.org/packages/3b/9f/73c4d34600aae03447dff3d7ad1d0ac649856bfb87d1ca7d681cfc913f9e/coverage-7.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e97353dcc5587b85986cda4ff3ec98081d7e84dd95e8b2a6d59820f0545f8a", size = 218673, upload-time = "2025-12-08T13:13:12.562Z" }, + { url = "https://files.pythonhosted.org/packages/63/ab/8fa097db361a1e8586535ae5073559e6229596b3489ec3ef2f5b38df8cb2/coverage-7.13.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:99acd4dfdfeb58e1937629eb1ab6ab0899b131f183ee5f23e0b5da5cba2fec74", size = 249652, upload-time = "2025-12-08T13:13:13.909Z" }, + { url = "https://files.pythonhosted.org/packages/90/3a/9bfd4de2ff191feb37ef9465855ca56a6f2f30a3bca172e474130731ac3d/coverage-7.13.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff45e0cd8451e293b63ced93161e189780baf444119391b3e7d25315060368a6", size = 252251, upload-time = "2025-12-08T13:13:15.553Z" }, + { url = "https://files.pythonhosted.org/packages/df/61/b5d8105f016e1b5874af0d7c67542da780ccd4a5f2244a433d3e20ceb1ad/coverage-7.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4f72a85316d8e13234cafe0a9f81b40418ad7a082792fa4165bd7d45d96066b", size = 253492, upload-time = "2025-12-08T13:13:16.849Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b8/0fad449981803cc47a4694768b99823fb23632150743f9c83af329bb6090/coverage-7.13.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11c21557d0e0a5a38632cbbaca5f008723b26a89d70db6315523df6df77d6232", size = 249850, upload-time = "2025-12-08T13:13:18.142Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e9/8d68337c3125014d918cf4327d5257553a710a2995a6a6de2ac77e5aa429/coverage-7.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76541dc8d53715fb4f7a3a06b34b0dc6846e3c69bc6204c55653a85dd6220971", size = 251633, upload-time = "2025-12-08T13:13:19.56Z" }, + { url = "https://files.pythonhosted.org/packages/55/14/d4112ab26b3a1bc4b3c1295d8452dcf399ed25be4cf649002fb3e64b2d93/coverage-7.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6e9e451dee940a86789134b6b0ffbe31c454ade3b849bb8a9d2cca2541a8e91d", size = 249586, upload-time = "2025-12-08T13:13:20.883Z" }, + { url = "https://files.pythonhosted.org/packages/2c/a9/22b0000186db663b0d82f86c2f1028099ae9ac202491685051e2a11a5218/coverage-7.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5c67dace46f361125e6b9cace8fe0b729ed8479f47e70c89b838d319375c8137", size = 249412, upload-time = "2025-12-08T13:13:22.22Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2e/42d8e0d9e7527fba439acdc6ed24a2b97613b1dc85849b1dd935c2cffef0/coverage-7.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f59883c643cb19630500f57016f76cfdcd6845ca8c5b5ea1f6e17f74c8e5f511", size = 251191, upload-time = "2025-12-08T13:13:23.899Z" }, + { url = "https://files.pythonhosted.org/packages/a4/af/8c7af92b1377fd8860536aadd58745119252aaaa71a5213e5a8e8007a9f5/coverage-7.13.0-cp313-cp313-win32.whl", hash = "sha256:58632b187be6f0be500f553be41e277712baa278147ecb7559983c6d9faf7ae1", size = 220829, upload-time = "2025-12-08T13:13:25.182Z" }, + { url = "https://files.pythonhosted.org/packages/58/f9/725e8bf16f343d33cbe076c75dc8370262e194ff10072c0608b8e5cf33a3/coverage-7.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:73419b89f812f498aca53f757dd834919b48ce4799f9d5cad33ca0ae442bdb1a", size = 221640, upload-time = "2025-12-08T13:13:26.836Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ff/e98311000aa6933cc79274e2b6b94a2fe0fe3434fca778eba82003675496/coverage-7.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb76670874fdd6091eedcc856128ee48c41a9bbbb9c3f1c7c3cf169290e3ffd6", size = 220269, upload-time = "2025-12-08T13:13:28.116Z" }, + { url = "https://files.pythonhosted.org/packages/cf/cf/bbaa2e1275b300343ea865f7d424cc0a2e2a1df6925a070b2b2d5d765330/coverage-7.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6e63ccc6e0ad8986386461c3c4b737540f20426e7ec932f42e030320896c311a", size = 218990, upload-time = "2025-12-08T13:13:29.463Z" }, + { url = "https://files.pythonhosted.org/packages/21/1d/82f0b3323b3d149d7672e7744c116e9c170f4957e0c42572f0366dbb4477/coverage-7.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:494f5459ffa1bd45e18558cd98710c36c0b8fbfa82a5eabcbe671d80ecffbfe8", size = 219340, upload-time = "2025-12-08T13:13:31.524Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e3/fe3fd4702a3832a255f4d43013eacb0ef5fc155a5960ea9269d8696db28b/coverage-7.13.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:06cac81bf10f74034e055e903f5f946e3e26fc51c09fc9f584e4a1605d977053", size = 260638, upload-time = "2025-12-08T13:13:32.965Z" }, + { url = "https://files.pythonhosted.org/packages/ad/01/63186cb000307f2b4da463f72af9b85d380236965574c78e7e27680a2593/coverage-7.13.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f2ffc92b46ed6e6760f1d47a71e56b5664781bc68986dbd1836b2b70c0ce2071", size = 262705, upload-time = "2025-12-08T13:13:34.378Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a1/c0dacef0cc865f2455d59eed3548573ce47ed603205ffd0735d1d78b5906/coverage-7.13.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0602f701057c6823e5db1b74530ce85f17c3c5be5c85fc042ac939cbd909426e", size = 265125, upload-time = "2025-12-08T13:13:35.73Z" }, + { url = "https://files.pythonhosted.org/packages/ef/92/82b99223628b61300bd382c205795533bed021505eab6dd86e11fb5d7925/coverage-7.13.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:25dc33618d45456ccb1d37bce44bc78cf269909aa14c4db2e03d63146a8a1493", size = 259844, upload-time = "2025-12-08T13:13:37.69Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2c/89b0291ae4e6cd59ef042708e1c438e2290f8c31959a20055d8768349ee2/coverage-7.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:71936a8b3b977ddd0b694c28c6a34f4fff2e9dd201969a4ff5d5fc7742d614b0", size = 262700, upload-time = "2025-12-08T13:13:39.525Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f9/a5f992efae1996245e796bae34ceb942b05db275e4b34222a9a40b9fbd3b/coverage-7.13.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:936bc20503ce24770c71938d1369461f0c5320830800933bc3956e2a4ded930e", size = 260321, upload-time = "2025-12-08T13:13:41.172Z" }, + { url = "https://files.pythonhosted.org/packages/4c/89/a29f5d98c64fedbe32e2ac3c227fbf78edc01cc7572eee17d61024d89889/coverage-7.13.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:af0a583efaacc52ae2521f8d7910aff65cdb093091d76291ac5820d5e947fc1c", size = 259222, upload-time = "2025-12-08T13:13:43.282Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c3/940fe447aae302a6701ee51e53af7e08b86ff6eed7631e5740c157ee22b9/coverage-7.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f1c23e24a7000da892a312fb17e33c5f94f8b001de44b7cf8ba2e36fbd15859e", size = 261411, upload-time = "2025-12-08T13:13:44.72Z" }, + { url = "https://files.pythonhosted.org/packages/eb/31/12a4aec689cb942a89129587860ed4d0fd522d5fda81237147fde554b8ae/coverage-7.13.0-cp313-cp313t-win32.whl", hash = "sha256:5f8a0297355e652001015e93be345ee54393e45dc3050af4a0475c5a2b767d46", size = 221505, upload-time = "2025-12-08T13:13:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/65/8c/3b5fe3259d863572d2b0827642c50c3855d26b3aefe80bdc9eba1f0af3b0/coverage-7.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6abb3a4c52f05e08460bd9acf04fec027f8718ecaa0d09c40ffbc3fbd70ecc39", size = 222569, upload-time = "2025-12-08T13:13:47.79Z" }, + { url = "https://files.pythonhosted.org/packages/b0/39/f71fa8316a96ac72fc3908839df651e8eccee650001a17f2c78cdb355624/coverage-7.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:3ad968d1e3aa6ce5be295ab5fe3ae1bf5bb4769d0f98a80a0252d543a2ef2e9e", size = 220841, upload-time = "2025-12-08T13:13:49.243Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4b/9b54bedda55421449811dcd5263a2798a63f48896c24dfb92b0f1b0845bd/coverage-7.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:453b7ec753cf5e4356e14fe858064e5520c460d3bbbcb9c35e55c0d21155c256", size = 218343, upload-time = "2025-12-08T13:13:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/59/df/c3a1f34d4bba2e592c8979f924da4d3d4598b0df2392fbddb7761258e3dc/coverage-7.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af827b7cbb303e1befa6c4f94fd2bf72f108089cfa0f8abab8f4ca553cf5ca5a", size = 218672, upload-time = "2025-12-08T13:13:52.284Z" }, + { url = "https://files.pythonhosted.org/packages/07/62/eec0659e47857698645ff4e6ad02e30186eb8afd65214fd43f02a76537cb/coverage-7.13.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9987a9e4f8197a1000280f7cc089e3ea2c8b3c0a64d750537809879a7b4ceaf9", size = 249715, upload-time = "2025-12-08T13:13:53.791Z" }, + { url = "https://files.pythonhosted.org/packages/23/2d/3c7ff8b2e0e634c1f58d095f071f52ed3c23ff25be524b0ccae8b71f99f8/coverage-7.13.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3188936845cd0cb114fa6a51842a304cdbac2958145d03be2377ec41eb285d19", size = 252225, upload-time = "2025-12-08T13:13:55.274Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ac/fb03b469d20e9c9a81093575003f959cf91a4a517b783aab090e4538764b/coverage-7.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2bdb3babb74079f021696cb46b8bb5f5661165c385d3a238712b031a12355be", size = 253559, upload-time = "2025-12-08T13:13:57.161Z" }, + { url = "https://files.pythonhosted.org/packages/29/62/14afa9e792383c66cc0a3b872a06ded6e4ed1079c7d35de274f11d27064e/coverage-7.13.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7464663eaca6adba4175f6c19354feea61ebbdd735563a03d1e472c7072d27bb", size = 249724, upload-time = "2025-12-08T13:13:58.692Z" }, + { url = "https://files.pythonhosted.org/packages/31/b7/333f3dab2939070613696ab3ee91738950f0467778c6e5a5052e840646b7/coverage-7.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8069e831f205d2ff1f3d355e82f511eb7c5522d7d413f5db5756b772ec8697f8", size = 251582, upload-time = "2025-12-08T13:14:00.642Z" }, + { url = "https://files.pythonhosted.org/packages/81/cb/69162bda9381f39b2287265d7e29ee770f7c27c19f470164350a38318764/coverage-7.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6fb2d5d272341565f08e962cce14cdf843a08ac43bd621783527adb06b089c4b", size = 249538, upload-time = "2025-12-08T13:14:02.556Z" }, + { url = "https://files.pythonhosted.org/packages/e0/76/350387b56a30f4970abe32b90b2a434f87d29f8b7d4ae40d2e8a85aacfb3/coverage-7.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5e70f92ef89bac1ac8a99b3324923b4749f008fdbd7aa9cb35e01d7a284a04f9", size = 249349, upload-time = "2025-12-08T13:14:04.015Z" }, + { url = "https://files.pythonhosted.org/packages/86/0d/7f6c42b8d59f4c7e43ea3059f573c0dcfed98ba46eb43c68c69e52ae095c/coverage-7.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4b5de7d4583e60d5fd246dd57fcd3a8aa23c6e118a8c72b38adf666ba8e7e927", size = 251011, upload-time = "2025-12-08T13:14:05.505Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f1/4bb2dff379721bb0b5c649d5c5eaf438462cad824acf32eb1b7ca0c7078e/coverage-7.13.0-cp314-cp314-win32.whl", hash = "sha256:a6c6e16b663be828a8f0b6c5027d36471d4a9f90d28444aa4ced4d48d7d6ae8f", size = 221091, upload-time = "2025-12-08T13:14:07.127Z" }, + { url = "https://files.pythonhosted.org/packages/ba/44/c239da52f373ce379c194b0ee3bcc121020e397242b85f99e0afc8615066/coverage-7.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:0900872f2fdb3ee5646b557918d02279dc3af3dfb39029ac4e945458b13f73bc", size = 221904, upload-time = "2025-12-08T13:14:08.542Z" }, + { url = "https://files.pythonhosted.org/packages/89/1f/b9f04016d2a29c2e4a0307baefefad1a4ec5724946a2b3e482690486cade/coverage-7.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:3a10260e6a152e5f03f26db4a407c4c62d3830b9af9b7c0450b183615f05d43b", size = 220480, upload-time = "2025-12-08T13:14:10.958Z" }, + { url = "https://files.pythonhosted.org/packages/16/d4/364a1439766c8e8647860584171c36010ca3226e6e45b1753b1b249c5161/coverage-7.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9097818b6cc1cfb5f174e3263eba4a62a17683bcfe5c4b5d07f4c97fa51fbf28", size = 219074, upload-time = "2025-12-08T13:14:13.345Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f4/71ba8be63351e099911051b2089662c03d5671437a0ec2171823c8e03bec/coverage-7.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0018f73dfb4301a89292c73be6ba5f58722ff79f51593352759c1790ded1cabe", size = 219342, upload-time = "2025-12-08T13:14:15.02Z" }, + { url = "https://files.pythonhosted.org/packages/5e/25/127d8ed03d7711a387d96f132589057213e3aef7475afdaa303412463f22/coverage-7.13.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:166ad2a22ee770f5656e1257703139d3533b4a0b6909af67c6b4a3adc1c98657", size = 260713, upload-time = "2025-12-08T13:14:16.907Z" }, + { url = "https://files.pythonhosted.org/packages/fd/db/559fbb6def07d25b2243663b46ba9eb5a3c6586c0c6f4e62980a68f0ee1c/coverage-7.13.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f6aaef16d65d1787280943f1c8718dc32e9cf141014e4634d64446702d26e0ff", size = 262825, upload-time = "2025-12-08T13:14:18.68Z" }, + { url = "https://files.pythonhosted.org/packages/37/99/6ee5bf7eff884766edb43bd8736b5e1c5144d0fe47498c3779326fe75a35/coverage-7.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e999e2dcc094002d6e2c7bbc1fb85b58ba4f465a760a8014d97619330cdbbbf3", size = 265233, upload-time = "2025-12-08T13:14:20.55Z" }, + { url = "https://files.pythonhosted.org/packages/d8/90/92f18fe0356ea69e1f98f688ed80cec39f44e9f09a1f26a1bbf017cc67f2/coverage-7.13.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:00c3d22cf6fb1cf3bf662aaaa4e563be8243a5ed2630339069799835a9cc7f9b", size = 259779, upload-time = "2025-12-08T13:14:22.367Z" }, + { url = "https://files.pythonhosted.org/packages/90/5d/b312a8b45b37a42ea7d27d7d3ff98ade3a6c892dd48d1d503e773503373f/coverage-7.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22ccfe8d9bb0d6134892cbe1262493a8c70d736b9df930f3f3afae0fe3ac924d", size = 262700, upload-time = "2025-12-08T13:14:24.309Z" }, + { url = "https://files.pythonhosted.org/packages/63/f8/b1d0de5c39351eb71c366f872376d09386640840a2e09b0d03973d791e20/coverage-7.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9372dff5ea15930fea0445eaf37bbbafbc771a49e70c0aeed8b4e2c2614cc00e", size = 260302, upload-time = "2025-12-08T13:14:26.068Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7c/d42f4435bc40c55558b3109a39e2d456cddcec37434f62a1f1230991667a/coverage-7.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:69ac2c492918c2461bc6ace42d0479638e60719f2a4ef3f0815fa2df88e9f940", size = 259136, upload-time = "2025-12-08T13:14:27.604Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d3/23413241dc04d47cfe19b9a65b32a2edd67ecd0b817400c2843ebc58c847/coverage-7.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:739c6c051a7540608d097b8e13c76cfa85263ced467168dc6b477bae3df7d0e2", size = 261467, upload-time = "2025-12-08T13:14:29.09Z" }, + { url = "https://files.pythonhosted.org/packages/13/e6/6e063174500eee216b96272c0d1847bf215926786f85c2bd024cf4d02d2f/coverage-7.13.0-cp314-cp314t-win32.whl", hash = "sha256:fe81055d8c6c9de76d60c94ddea73c290b416e061d40d542b24a5871bad498b7", size = 221875, upload-time = "2025-12-08T13:14:31.106Z" }, + { url = "https://files.pythonhosted.org/packages/3b/46/f4fb293e4cbe3620e3ac2a3e8fd566ed33affb5861a9b20e3dd6c1896cbc/coverage-7.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:445badb539005283825959ac9fa4a28f712c214b65af3a2c464f1adc90f5fcbc", size = 222982, upload-time = "2025-12-08T13:14:33.1Z" }, + { url = "https://files.pythonhosted.org/packages/68/62/5b3b9018215ed9733fbd1ae3b2ed75c5de62c3b55377a52cae732e1b7805/coverage-7.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:de7f6748b890708578fc4b7bb967d810aeb6fcc9bff4bb77dbca77dab2f9df6a", size = 221016, upload-time = "2025-12-08T13:14:34.601Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4c/1968f32fb9a2604645827e11ff84a31e59d532e01995f904723b4f5328b3/coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904", size = 210068, upload-time = "2025-12-08T13:14:36.236Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11'" }, +] + +[[package]] +name = "decli" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/59/d4ffff1dee2c8f6f2dd8f87010962e60f7b7847504d765c91ede5a466730/decli-0.6.3.tar.gz", hash = "sha256:87f9d39361adf7f16b9ca6e3b614badf7519da13092f2db3c80ca223c53c7656", size = 7564, upload-time = "2025-06-01T15:23:41.25Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/fa/ec878c28bc7f65b77e7e17af3522c9948a9711b9fa7fc4c5e3140a7e3578/decli-0.6.3-py3-none-any.whl", hash = "sha256:5152347c7bb8e3114ad65db719e5709b28d7f7f45bdb709f70167925e55640f3", size = 7989, upload-time = "2025-06-01T15:23:40.228Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "deprecated" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/85/12f0a49a7c4ffb70572b6c2ef13c90c88fd190debda93b23f026b25f9634/deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223", size = 2932523, upload-time = "2025-10-30T08:19:02.757Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", size = 11298, upload-time = "2025-10-30T08:19:00.758Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "filelock" +version = "3.20.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/23/ce7a1126827cedeb958fc043d61745754464eb56c5937c35bbf2b8e26f34/filelock-3.20.1.tar.gz", hash = "sha256:b8360948b351b80f420878d8516519a2204b07aefcdcfd24912a5d33127f188c", size = 19476, upload-time = "2025-12-15T23:54:28.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/7f/a1a97644e39e7316d850784c642093c99df1290a460df4ede27659056834/filelock-3.20.1-py3-none-any.whl", hash = "sha256:15d9e9a67306188a44baa72f569d2bfd803076269365fdea0934385da4dc361a", size = 16666, upload-time = "2025-12-15T23:54:26.874Z" }, +] + +[[package]] +name = "freezegun" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/dd/23e2f4e357f8fd3bdff613c1fe4466d21bfb00a6177f238079b17f7b1c84/freezegun-1.5.5.tar.gz", hash = "sha256:ac7742a6cc6c25a2c35e9292dfd554b897b517d2dec26891a2e8debf205cb94a", size = 35914, upload-time = "2025-08-09T10:39:08.338Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/2e/b41d8a1a917d6581fc27a35d05561037b048e47df50f27f8ac9c7e27a710/freezegun-1.5.5-py3-none-any.whl", hash = "sha256:cd557f4a75cf074e84bc374249b9dd491eaeacd61376b9eb3c423282211619d2", size = 19266, upload-time = "2025-08-09T10:39:06.636Z" }, +] + +[[package]] +name = "ghp-import" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, +] + +[[package]] +name = "identify" +version = "2.6.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/e7/685de97986c916a6d93b3876139e00eef26ad5bbbd61925d670ae8013449/identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf", size = 99311, upload-time = "2025-10-02T17:43:40.631Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/1c/e5fd8f973d4f375adb21565739498e2e9a1e54c858a97b9a8ccfdc81da9b/identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757", size = 99183, upload-time = "2025-10-02T17:43:39.137Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "ipython" +version = "8.37.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version < '3.11'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "jedi", marker = "python_full_version < '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version < '3.11'" }, + { name = "pexpect", marker = "python_full_version < '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version < '3.11'" }, + { name = "pygments", marker = "python_full_version < '3.11'" }, + { name = "stack-data", marker = "python_full_version < '3.11'" }, + { name = "traitlets", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size = 5606088, upload-time = "2025-05-31T16:39:09.613Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/d0/274fbf7b0b12643cbbc001ce13e6a5b1607ac4929d1b11c72460152c9fc3/ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2", size = 831864, upload-time = "2025-05-31T16:39:06.38Z" }, +] + +[[package]] +name = "ipython" +version = "9.8.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.11'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version >= '3.11'" }, + { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" }, + { name = "jedi", marker = "python_full_version >= '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" }, + { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, + { name = "stack-data", marker = "python_full_version >= '3.11'" }, + { name = "traitlets", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version == '3.11.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/51/a703c030f4928646d390b4971af4938a1b10c9dfce694f0d99a0bb073cb2/ipython-9.8.0.tar.gz", hash = "sha256:8e4ce129a627eb9dd221c41b1d2cdaed4ef7c9da8c17c63f6f578fe231141f83", size = 4424940, upload-time = "2025-12-03T10:18:24.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl", hash = "sha256:ebe6d1d58d7d988fbf23ff8ff6d8e1622cfdb194daf4b7b73b792c4ec3b85385", size = 621374, upload-time = "2025-12-03T10:18:22.335Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "librt" +version = "0.7.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/93/e4/b59bdf1197fdf9888452ea4d2048cdad61aef85eb83e99dc52551d7fdc04/librt-0.7.4.tar.gz", hash = "sha256:3871af56c59864d5fd21d1ac001eb2fb3b140d52ba0454720f2e4a19812404ba", size = 145862, upload-time = "2025-12-15T16:52:43.862Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/1e/3e61dff6c07a3b400fe907d3164b92b3b3023ef86eac1ee236869dc276f7/librt-0.7.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dc300cb5a5a01947b1ee8099233156fdccd5001739e5f596ecfbc0dab07b5a3b", size = 54708, upload-time = "2025-12-15T16:51:03.752Z" }, + { url = "https://files.pythonhosted.org/packages/87/98/ab2428b0a80d0fd67decaeea84a5ec920e3dd4d95ecfd074c71f51bd7315/librt-0.7.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee8d3323d921e0f6919918a97f9b5445a7dfe647270b2629ec1008aa676c0bc0", size = 56656, upload-time = "2025-12-15T16:51:05.038Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ce/de1fad3a16e4fb5b6605bd6cbe6d0e5207cc8eca58993835749a1da0812b/librt-0.7.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:95cb80854a355b284c55f79674f6187cc9574df4dc362524e0cce98c89ee8331", size = 161024, upload-time = "2025-12-15T16:51:06.31Z" }, + { url = "https://files.pythonhosted.org/packages/88/00/ddfcdc1147dd7fb68321d7b064b12f0b9101d85f466a46006f86096fde8d/librt-0.7.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ca1caedf8331d8ad6027f93b52d68ed8f8009f5c420c246a46fe9d3be06be0f", size = 169529, upload-time = "2025-12-15T16:51:07.907Z" }, + { url = "https://files.pythonhosted.org/packages/dd/b3/915702c7077df2483b015030d1979404474f490fe9a071e9576f7b26fef6/librt-0.7.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2a6f1236151e6fe1da289351b5b5bce49651c91554ecc7b70a947bced6fe212", size = 183270, upload-time = "2025-12-15T16:51:09.164Z" }, + { url = "https://files.pythonhosted.org/packages/45/19/ab2f217e8ec509fca4ea9e2e5022b9f72c1a7b7195f5a5770d299df807ea/librt-0.7.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7766b57aeebaf3f1dac14fdd4a75c9a61f2ed56d8ebeefe4189db1cb9d2a3783", size = 179038, upload-time = "2025-12-15T16:51:10.538Z" }, + { url = "https://files.pythonhosted.org/packages/10/1c/d40851d187662cf50312ebbc0b277c7478dd78dbaaf5ee94056f1d7f2f83/librt-0.7.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1c4c89fb01157dd0a3bfe9e75cd6253b0a1678922befcd664eca0772a4c6c979", size = 173502, upload-time = "2025-12-15T16:51:11.888Z" }, + { url = "https://files.pythonhosted.org/packages/07/52/d5880835c772b22c38db18660420fa6901fd9e9a433b65f0ba9b0f4da764/librt-0.7.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f7fa8beef580091c02b4fd26542de046b2abfe0aaefa02e8bcf68acb7618f2b3", size = 193570, upload-time = "2025-12-15T16:51:13.168Z" }, + { url = "https://files.pythonhosted.org/packages/f1/35/22d3c424b82f86ce019c0addadf001d459dfac8036aecc07fadc5c541053/librt-0.7.4-cp310-cp310-win32.whl", hash = "sha256:543c42fa242faae0466fe72d297976f3c710a357a219b1efde3a0539a68a6997", size = 42596, upload-time = "2025-12-15T16:51:14.422Z" }, + { url = "https://files.pythonhosted.org/packages/95/b1/e7c316ac5fe60ac1fdfe515198087205220803c4cf923ee63e1cb8380b17/librt-0.7.4-cp310-cp310-win_amd64.whl", hash = "sha256:25cc40d8eb63f0a7ea4c8f49f524989b9df901969cb860a2bc0e4bad4b8cb8a8", size = 48972, upload-time = "2025-12-15T16:51:15.516Z" }, + { url = "https://files.pythonhosted.org/packages/84/64/44089b12d8b4714a7f0e2f33fb19285ba87702d4be0829f20b36ebeeee07/librt-0.7.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3485b9bb7dfa66167d5500ffdafdc35415b45f0da06c75eb7df131f3357b174a", size = 54709, upload-time = "2025-12-15T16:51:16.699Z" }, + { url = "https://files.pythonhosted.org/packages/26/ef/6fa39fb5f37002f7d25e0da4f24d41b457582beea9369eeb7e9e73db5508/librt-0.7.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:188b4b1a770f7f95ea035d5bbb9d7367248fc9d12321deef78a269ebf46a5729", size = 56663, upload-time = "2025-12-15T16:51:17.856Z" }, + { url = "https://files.pythonhosted.org/packages/9d/e4/cbaca170a13bee2469c90df9e47108610b4422c453aea1aec1779ac36c24/librt-0.7.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1b668b1c840183e4e38ed5a99f62fac44c3a3eef16870f7f17cfdfb8b47550ed", size = 161703, upload-time = "2025-12-15T16:51:19.421Z" }, + { url = "https://files.pythonhosted.org/packages/d0/32/0b2296f9cc7e693ab0d0835e355863512e5eac90450c412777bd699c76ae/librt-0.7.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0e8f864b521f6cfedb314d171630f827efee08f5c3462bcbc2244ab8e1768cd6", size = 171027, upload-time = "2025-12-15T16:51:20.721Z" }, + { url = "https://files.pythonhosted.org/packages/d8/33/c70b6d40f7342716e5f1353c8da92d9e32708a18cbfa44897a93ec2bf879/librt-0.7.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4df7c9def4fc619a9c2ab402d73a0c5b53899abe090e0100323b13ccb5a3dd82", size = 184700, upload-time = "2025-12-15T16:51:22.272Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c8/555c405155da210e4c4113a879d378f54f850dbc7b794e847750a8fadd43/librt-0.7.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f79bc3595b6ed159a1bf0cdc70ed6ebec393a874565cab7088a219cca14da727", size = 180719, upload-time = "2025-12-15T16:51:23.561Z" }, + { url = "https://files.pythonhosted.org/packages/6b/88/34dc1f1461c5613d1b73f0ecafc5316cc50adcc1b334435985b752ed53e5/librt-0.7.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77772a4b8b5f77d47d883846928c36d730b6e612a6388c74cba33ad9eb149c11", size = 174535, upload-time = "2025-12-15T16:51:25.031Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5a/f3fafe80a221626bcedfa9fe5abbf5f04070989d44782f579b2d5920d6d0/librt-0.7.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:064a286e6ab0b4c900e228ab4fa9cb3811b4b83d3e0cc5cd816b2d0f548cb61c", size = 195236, upload-time = "2025-12-15T16:51:26.328Z" }, + { url = "https://files.pythonhosted.org/packages/d8/77/5c048d471ce17f4c3a6e08419be19add4d291e2f7067b877437d482622ac/librt-0.7.4-cp311-cp311-win32.whl", hash = "sha256:42da201c47c77b6cc91fc17e0e2b330154428d35d6024f3278aa2683e7e2daf2", size = 42930, upload-time = "2025-12-15T16:51:27.853Z" }, + { url = "https://files.pythonhosted.org/packages/fb/3b/514a86305a12c3d9eac03e424b07cd312c7343a9f8a52719aa079590a552/librt-0.7.4-cp311-cp311-win_amd64.whl", hash = "sha256:d31acb5886c16ae1711741f22504195af46edec8315fe69b77e477682a87a83e", size = 49240, upload-time = "2025-12-15T16:51:29.037Z" }, + { url = "https://files.pythonhosted.org/packages/ba/01/3b7b1914f565926b780a734fac6e9a4d2c7aefe41f4e89357d73697a9457/librt-0.7.4-cp311-cp311-win_arm64.whl", hash = "sha256:114722f35093da080a333b3834fff04ef43147577ed99dd4db574b03a5f7d170", size = 42613, upload-time = "2025-12-15T16:51:30.194Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e7/b805d868d21f425b7e76a0ea71a2700290f2266a4f3c8357fcf73efc36aa/librt-0.7.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7dd3b5c37e0fb6666c27cf4e2c88ae43da904f2155c4cfc1e5a2fdce3b9fcf92", size = 55688, upload-time = "2025-12-15T16:51:31.571Z" }, + { url = "https://files.pythonhosted.org/packages/59/5e/69a2b02e62a14cfd5bfd9f1e9adea294d5bcfeea219c7555730e5d068ee4/librt-0.7.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9c5de1928c486201b23ed0cc4ac92e6e07be5cd7f3abc57c88a9cf4f0f32108", size = 57141, upload-time = "2025-12-15T16:51:32.714Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6b/05dba608aae1272b8ea5ff8ef12c47a4a099a04d1e00e28a94687261d403/librt-0.7.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:078ae52ffb3f036396cc4aed558e5b61faedd504a3c1f62b8ae34bf95ae39d94", size = 165322, upload-time = "2025-12-15T16:51:33.986Z" }, + { url = "https://files.pythonhosted.org/packages/8f/bc/199533d3fc04a4cda8d7776ee0d79955ab0c64c79ca079366fbc2617e680/librt-0.7.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce58420e25097b2fc201aef9b9f6d65df1eb8438e51154e1a7feb8847e4a55ab", size = 174216, upload-time = "2025-12-15T16:51:35.384Z" }, + { url = "https://files.pythonhosted.org/packages/62/ec/09239b912a45a8ed117cb4a6616d9ff508f5d3131bd84329bf2f8d6564f1/librt-0.7.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b719c8730c02a606dc0e8413287e8e94ac2d32a51153b300baf1f62347858fba", size = 189005, upload-time = "2025-12-15T16:51:36.687Z" }, + { url = "https://files.pythonhosted.org/packages/46/2e/e188313d54c02f5b0580dd31476bb4b0177514ff8d2be9f58d4a6dc3a7ba/librt-0.7.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3749ef74c170809e6dee68addec9d2458700a8de703de081c888e92a8b015cf9", size = 183960, upload-time = "2025-12-15T16:51:37.977Z" }, + { url = "https://files.pythonhosted.org/packages/eb/84/f1d568d254518463d879161d3737b784137d236075215e56c7c9be191cee/librt-0.7.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b35c63f557653c05b5b1b6559a074dbabe0afee28ee2a05b6c9ba21ad0d16a74", size = 177609, upload-time = "2025-12-15T16:51:40.584Z" }, + { url = "https://files.pythonhosted.org/packages/5d/43/060bbc1c002f0d757c33a1afe6bf6a565f947a04841139508fc7cef6c08b/librt-0.7.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1ef704e01cb6ad39ad7af668d51677557ca7e5d377663286f0ee1b6b27c28e5f", size = 199269, upload-time = "2025-12-15T16:51:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/ff/7f/708f8f02d8012ee9f366c07ea6a92882f48bd06cc1ff16a35e13d0fbfb08/librt-0.7.4-cp312-cp312-win32.whl", hash = "sha256:c66c2b245926ec15188aead25d395091cb5c9df008d3b3207268cd65557d6286", size = 43186, upload-time = "2025-12-15T16:51:43.149Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a5/4e051b061c8b2509be31b2c7ad4682090502c0a8b6406edcf8c6b4fe1ef7/librt-0.7.4-cp312-cp312-win_amd64.whl", hash = "sha256:71a56f4671f7ff723451f26a6131754d7c1809e04e22ebfbac1db8c9e6767a20", size = 49455, upload-time = "2025-12-15T16:51:44.336Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d2/90d84e9f919224a3c1f393af1636d8638f54925fdc6cd5ee47f1548461e5/librt-0.7.4-cp312-cp312-win_arm64.whl", hash = "sha256:419eea245e7ec0fe664eb7e85e7ff97dcdb2513ca4f6b45a8ec4a3346904f95a", size = 42828, upload-time = "2025-12-15T16:51:45.498Z" }, + { url = "https://files.pythonhosted.org/packages/fe/4d/46a53ccfbb39fd0b493fd4496eb76f3ebc15bb3e45d8c2e695a27587edf5/librt-0.7.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d44a1b1ba44cbd2fc3cb77992bef6d6fdb1028849824e1dd5e4d746e1f7f7f0b", size = 55745, upload-time = "2025-12-15T16:51:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/7f/2b/3ac7f5212b1828bf4f979cf87f547db948d3e28421d7a430d4db23346ce4/librt-0.7.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c9cab4b3de1f55e6c30a84c8cee20e4d3b2476f4d547256694a1b0163da4fe32", size = 57166, upload-time = "2025-12-15T16:51:48.219Z" }, + { url = "https://files.pythonhosted.org/packages/e8/99/6523509097cbe25f363795f0c0d1c6a3746e30c2994e25b5aefdab119b21/librt-0.7.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2857c875f1edd1feef3c371fbf830a61b632fb4d1e57160bb1e6a3206e6abe67", size = 165833, upload-time = "2025-12-15T16:51:49.443Z" }, + { url = "https://files.pythonhosted.org/packages/fe/35/323611e59f8fe032649b4fb7e77f746f96eb7588fcbb31af26bae9630571/librt-0.7.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b370a77be0a16e1ad0270822c12c21462dc40496e891d3b0caf1617c8cc57e20", size = 174818, upload-time = "2025-12-15T16:51:51.015Z" }, + { url = "https://files.pythonhosted.org/packages/41/e6/40fb2bb21616c6e06b6a64022802228066e9a31618f493e03f6b9661548a/librt-0.7.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d05acd46b9a52087bfc50c59dfdf96a2c480a601e8898a44821c7fd676598f74", size = 189607, upload-time = "2025-12-15T16:51:52.671Z" }, + { url = "https://files.pythonhosted.org/packages/32/48/1b47c7d5d28b775941e739ed2bfe564b091c49201b9503514d69e4ed96d7/librt-0.7.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:70969229cb23d9c1a80e14225838d56e464dc71fa34c8342c954fc50e7516dee", size = 184585, upload-time = "2025-12-15T16:51:54.027Z" }, + { url = "https://files.pythonhosted.org/packages/75/a6/ee135dfb5d3b54d5d9001dbe483806229c6beac3ee2ba1092582b7efeb1b/librt-0.7.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4450c354b89dbb266730893862dbff06006c9ed5b06b6016d529b2bf644fc681", size = 178249, upload-time = "2025-12-15T16:51:55.248Z" }, + { url = "https://files.pythonhosted.org/packages/04/87/d5b84ec997338be26af982bcd6679be0c1db9a32faadab1cf4bb24f9e992/librt-0.7.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:adefe0d48ad35b90b6f361f6ff5a1bd95af80c17d18619c093c60a20e7a5b60c", size = 199851, upload-time = "2025-12-15T16:51:56.933Z" }, + { url = "https://files.pythonhosted.org/packages/86/63/ba1333bf48306fe398e3392a7427ce527f81b0b79d0d91618c4610ce9d15/librt-0.7.4-cp313-cp313-win32.whl", hash = "sha256:21ea710e96c1e050635700695095962a22ea420d4b3755a25e4909f2172b4ff2", size = 43249, upload-time = "2025-12-15T16:51:58.498Z" }, + { url = "https://files.pythonhosted.org/packages/f9/8a/de2c6df06cdfa9308c080e6b060fe192790b6a48a47320b215e860f0e98c/librt-0.7.4-cp313-cp313-win_amd64.whl", hash = "sha256:772e18696cf5a64afee908662fbcb1f907460ddc851336ee3a848ef7684c8e1e", size = 49417, upload-time = "2025-12-15T16:51:59.618Z" }, + { url = "https://files.pythonhosted.org/packages/31/66/8ee0949efc389691381ed686185e43536c20e7ad880c122dd1f31e65c658/librt-0.7.4-cp313-cp313-win_arm64.whl", hash = "sha256:52e34c6af84e12921748c8354aa6acf1912ca98ba60cdaa6920e34793f1a0788", size = 42824, upload-time = "2025-12-15T16:52:00.784Z" }, + { url = "https://files.pythonhosted.org/packages/74/81/6921e65c8708eb6636bbf383aa77e6c7dad33a598ed3b50c313306a2da9d/librt-0.7.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4f1ee004942eaaed6e06c087d93ebc1c67e9a293e5f6b9b5da558df6bf23dc5d", size = 55191, upload-time = "2025-12-15T16:52:01.97Z" }, + { url = "https://files.pythonhosted.org/packages/0d/d6/3eb864af8a8de8b39cc8dd2e9ded1823979a27795d72c4eea0afa8c26c9f/librt-0.7.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d854c6dc0f689bad7ed452d2a3ecff58029d80612d336a45b62c35e917f42d23", size = 56898, upload-time = "2025-12-15T16:52:03.356Z" }, + { url = "https://files.pythonhosted.org/packages/49/bc/b1d4c0711fdf79646225d576faee8747b8528a6ec1ceb6accfd89ade7102/librt-0.7.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a4f7339d9e445280f23d63dea842c0c77379c4a47471c538fc8feedab9d8d063", size = 163725, upload-time = "2025-12-15T16:52:04.572Z" }, + { url = "https://files.pythonhosted.org/packages/2c/08/61c41cd8f0a6a41fc99ea78a2205b88187e45ba9800792410ed62f033584/librt-0.7.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39003fc73f925e684f8521b2dbf34f61a5deb8a20a15dcf53e0d823190ce8848", size = 172469, upload-time = "2025-12-15T16:52:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c7/4ee18b4d57f01444230bc18cf59103aeab8f8c0f45e84e0e540094df1df1/librt-0.7.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bb15ee29d95875ad697d449fe6071b67f730f15a6961913a2b0205015ca0843", size = 186804, upload-time = "2025-12-15T16:52:07.192Z" }, + { url = "https://files.pythonhosted.org/packages/a1/af/009e8ba3fbf830c936842da048eda1b34b99329f402e49d88fafff6525d1/librt-0.7.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:02a69369862099e37d00765583052a99d6a68af7e19b887e1b78fee0146b755a", size = 181807, upload-time = "2025-12-15T16:52:08.554Z" }, + { url = "https://files.pythonhosted.org/packages/85/26/51ae25f813656a8b117c27a974f25e8c1e90abcd5a791ac685bf5b489a1b/librt-0.7.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ec72342cc4d62f38b25a94e28b9efefce41839aecdecf5e9627473ed04b7be16", size = 175595, upload-time = "2025-12-15T16:52:10.186Z" }, + { url = "https://files.pythonhosted.org/packages/48/93/36d6c71f830305f88996b15c8e017aa8d1e03e2e947b40b55bbf1a34cf24/librt-0.7.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:776dbb9bfa0fc5ce64234b446995d8d9f04badf64f544ca036bd6cff6f0732ce", size = 196504, upload-time = "2025-12-15T16:52:11.472Z" }, + { url = "https://files.pythonhosted.org/packages/08/11/8299e70862bb9d704735bf132c6be09c17b00fbc7cda0429a9df222fdc1b/librt-0.7.4-cp314-cp314-win32.whl", hash = "sha256:0f8cac84196d0ffcadf8469d9ded4d4e3a8b1c666095c2a291e22bf58e1e8a9f", size = 39738, upload-time = "2025-12-15T16:52:12.962Z" }, + { url = "https://files.pythonhosted.org/packages/54/d5/656b0126e4e0f8e2725cd2d2a1ec40f71f37f6f03f135a26b663c0e1a737/librt-0.7.4-cp314-cp314-win_amd64.whl", hash = "sha256:037f5cb6fe5abe23f1dc058054d50e9699fcc90d0677eee4e4f74a8677636a1a", size = 45976, upload-time = "2025-12-15T16:52:14.441Z" }, + { url = "https://files.pythonhosted.org/packages/60/86/465ff07b75c1067da8fa7f02913c4ead096ef106cfac97a977f763783bfb/librt-0.7.4-cp314-cp314-win_arm64.whl", hash = "sha256:a5deebb53d7a4d7e2e758a96befcd8edaaca0633ae71857995a0f16033289e44", size = 39073, upload-time = "2025-12-15T16:52:15.621Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a0/24941f85960774a80d4b3c2aec651d7d980466da8101cae89e8b032a3e21/librt-0.7.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b4c25312c7f4e6ab35ab16211bdf819e6e4eddcba3b2ea632fb51c9a2a97e105", size = 57369, upload-time = "2025-12-15T16:52:16.782Z" }, + { url = "https://files.pythonhosted.org/packages/77/a0/ddb259cae86ab415786c1547d0fe1b40f04a7b089f564fd5c0242a3fafb2/librt-0.7.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:618b7459bb392bdf373f2327e477597fff8f9e6a1878fffc1b711c013d1b0da4", size = 59230, upload-time = "2025-12-15T16:52:18.259Z" }, + { url = "https://files.pythonhosted.org/packages/31/11/77823cb530ab8a0c6fac848ac65b745be446f6f301753b8990e8809080c9/librt-0.7.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1437c3f72a30c7047f16fd3e972ea58b90172c3c6ca309645c1c68984f05526a", size = 183869, upload-time = "2025-12-15T16:52:19.457Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ce/157db3614cf3034b3f702ae5ba4fefda4686f11eea4b7b96542324a7a0e7/librt-0.7.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c96cb76f055b33308f6858b9b594618f1b46e147a4d03a4d7f0c449e304b9b95", size = 194606, upload-time = "2025-12-15T16:52:20.795Z" }, + { url = "https://files.pythonhosted.org/packages/30/ef/6ec4c7e3d6490f69a4fd2803516fa5334a848a4173eac26d8ee6507bff6e/librt-0.7.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28f990e6821204f516d09dc39966ef8b84556ffd648d5926c9a3f681e8de8906", size = 206776, upload-time = "2025-12-15T16:52:22.229Z" }, + { url = "https://files.pythonhosted.org/packages/ad/22/750b37bf549f60a4782ab80e9d1e9c44981374ab79a7ea68670159905918/librt-0.7.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc4aebecc79781a1b77d7d4e7d9fe080385a439e198d993b557b60f9117addaf", size = 203205, upload-time = "2025-12-15T16:52:23.603Z" }, + { url = "https://files.pythonhosted.org/packages/7a/87/2e8a0f584412a93df5faad46c5fa0a6825fdb5eba2ce482074b114877f44/librt-0.7.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:022cc673e69283a42621dd453e2407cf1647e77f8bd857d7ad7499901e62376f", size = 196696, upload-time = "2025-12-15T16:52:24.951Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ca/7bf78fa950e43b564b7de52ceeb477fb211a11f5733227efa1591d05a307/librt-0.7.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2b3ca211ae8ea540569e9c513da052699b7b06928dcda61247cb4f318122bdb5", size = 217191, upload-time = "2025-12-15T16:52:26.194Z" }, + { url = "https://files.pythonhosted.org/packages/d6/49/3732b0e8424ae35ad5c3166d9dd5bcdae43ce98775e0867a716ff5868064/librt-0.7.4-cp314-cp314t-win32.whl", hash = "sha256:8a461f6456981d8c8e971ff5a55f2e34f4e60871e665d2f5fde23ee74dea4eeb", size = 40276, upload-time = "2025-12-15T16:52:27.54Z" }, + { url = "https://files.pythonhosted.org/packages/35/d6/d8823e01bd069934525fddb343189c008b39828a429b473fb20d67d5cd36/librt-0.7.4-cp314-cp314t-win_amd64.whl", hash = "sha256:721a7b125a817d60bf4924e1eec2a7867bfcf64cfc333045de1df7a0629e4481", size = 46772, upload-time = "2025-12-15T16:52:28.653Z" }, + { url = "https://files.pythonhosted.org/packages/36/e9/a0aa60f5322814dd084a89614e9e31139702e342f8459ad8af1984a18168/librt-0.7.4-cp314-cp314t-win_arm64.whl", hash = "sha256:76b2ba71265c0102d11458879b4d53ccd0b32b0164d14deb8d2b598a018e502f", size = 39724, upload-time = "2025-12-15T16:52:29.836Z" }, +] + +[[package]] +name = "markdown" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/7dd27d9d863b3376fcf23a5a13cb5d024aed1db46f963f1b5735ae43b3be/markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e", size = 364931, upload-time = "2025-11-03T19:51:15.007Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c", size = 107678, upload-time = "2025-11-03T19:51:13.887Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, + { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, + { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, + { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, + { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, + { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mergedeep" +version = "1.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, +] + +[[package]] +name = "mkdocs" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "ghp-import" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mergedeep" }, + { name = "mkdocs-get-deps" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "pyyaml-env-tag" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" }, +] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mergedeep" }, + { name = "platformdirs" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239, upload-time = "2023-11-20T17:51:09.981Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, +] + +[[package]] +name = "mkdocs-material" +version = "9.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "backrefs" }, + { name = "colorama" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "mkdocs" }, + { name = "mkdocs-material-extensions" }, + { name = "paginate" }, + { name = "pygments" }, + { name = "pymdown-extensions" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/e2/2ffc356cd72f1473d07c7719d82a8f2cbd261666828614ecb95b12169f41/mkdocs_material-9.7.1.tar.gz", hash = "sha256:89601b8f2c3e6c6ee0a918cc3566cb201d40bf37c3cd3c2067e26fadb8cce2b8", size = 4094392, upload-time = "2025-12-18T09:49:00.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/32/ed071cb721aca8c227718cffcf7bd539620e9799bbf2619e90c757bfd030/mkdocs_material-9.7.1-py3-none-any.whl", hash = "sha256:3f6100937d7d731f87f1e3e3b021c97f7239666b9ba1151ab476cabb96c60d5c", size = 9297166, upload-time = "2025-12-18T09:48:56.664Z" }, +] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" }, +] + +[[package]] +name = "mypy" +version = "1.19.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, + { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, + { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, + { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, + { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, + { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, + { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, + { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, + { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" }, + { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" }, + { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, + { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, + { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, + { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, + { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, + { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, + { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, + { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, + { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, + { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, + { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, + { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "paginate" +version = "0.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" }, +] + +[[package]] +name = "parso" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, +] + +[[package]] +name = "pastel" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/f1/4594f5e0fcddb6953e5b8fe00da8c317b8b41b547e2b3ae2da7512943c62/pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d", size = 7555, upload-time = "2020-09-16T19:21:12.43Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/18/a8444036c6dd65ba3624c63b734d3ba95ba63ace513078e1580590075d21/pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", size = 5955, upload-time = "2020-09-16T19:21:11.409Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "poethepoet" +version = "0.38.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pastel" }, + { name = "pyyaml" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/14/d1f795f314c4bf3ad6d64216e370bdfda73093ed76e979485778b655a7ac/poethepoet-0.38.0.tar.gz", hash = "sha256:aeeb2f0a2cf0d3afa833976eff3ac7b8f5e472ae64171824900d79d3c68163c7", size = 77339, upload-time = "2025-11-23T13:51:28.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/89/2bf7d43ef4b0d60f446933ae9d3649f95c2c45c47b6736d121b602c28361/poethepoet-0.38.0-py3-none-any.whl", hash = "sha256:214bd9fcb348ff3dfd1466579d67e0c02242451a7044aced1a79641adef9cad0", size = 101938, upload-time = "2025-11-23T13:51:26.518Z" }, +] + +[[package]] +name = "pre-commit" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pymdown-extensions" +version = "10.19.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/2d/9f30cee56d4d6d222430d401e85b0a6a1ae229819362f5786943d1a8c03b/pymdown_extensions-10.19.1.tar.gz", hash = "sha256:4969c691009a389fb1f9712dd8e7bd70dcc418d15a0faf70acb5117d022f7de8", size = 847839, upload-time = "2025-12-14T17:25:24.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/35/b763e8fbcd51968329b9adc52d188fc97859f85f2ee15fe9f379987d99c5/pymdown_extensions-10.19.1-py3-none-any.whl", hash = "sha256:e8698a66055b1dc0dca2a7f2c9d0ea6f5faa7834a9c432e3535ab96c0c4e509b", size = 266693, upload-time = "2025-12-14T17:25:22.999Z" }, +] + +[[package]] +name = "pyproject-api" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/7b/c0e1333b61d41c69e59e5366e727b18c4992688caf0de1be10b3e5265f6b/pyproject_api-1.10.0.tar.gz", hash = "sha256:40c6f2d82eebdc4afee61c773ed208c04c19db4c4a60d97f8d7be3ebc0bbb330", size = 22785, upload-time = "2025-10-09T19:12:27.21Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/cc/cecf97be298bee2b2a37dd360618c819a2a7fd95251d8e480c1f0eb88f3b/pyproject_api-1.10.0-py3-none-any.whl", hash = "sha256:8757c41a79c0f4ab71b99abed52b97ecf66bd20b04fa59da43b5840bac105a09", size = 13218, upload-time = "2025-10-09T19:12:24.428Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, +] + +[[package]] +name = "pytest-cov" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pluggy" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, +] + +[[package]] +name = "pytest-datadir" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b4/46/db060b291999ca048edd06d6fa9ee95945d088edc38b1172c59eeb46ec45/pytest_datadir-1.8.0.tar.gz", hash = "sha256:7a15faed76cebe87cc91941dd1920a9a38eba56a09c11e9ddf1434d28a0f78eb", size = 11848, upload-time = "2025-07-30T13:52:12.518Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/7a/33895863aec26ac3bb5068a73583f935680d6ab6af2a9567d409430c3ee1/pytest_datadir-1.8.0-py3-none-any.whl", hash = "sha256:5c677bc097d907ac71ca418109adc3abe34cf0bddfe6cf78aecfbabd96a15cf0", size = 6512, upload-time = "2025-07-30T13:52:11.525Z" }, +] + +[[package]] +name = "pytest-freezer" +version = "0.4.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "freezegun" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/f0/98dcbc5324064360b19850b14c84cea9ca50785d921741dbfc442346e925/pytest_freezer-0.4.9.tar.gz", hash = "sha256:21bf16bc9cc46bf98f94382c4b5c3c389be7056ff0be33029111ae11b3f1c82a", size = 3177, upload-time = "2024-12-12T08:53:08.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/e9/30252bc05bcf67200a17f4f0b4cc7598f0a68df4fa9fa356193aa899f145/pytest_freezer-0.4.9-py3-none-any.whl", hash = "sha256:8b6c50523b7d4aec4590b52bfa5ff766d772ce506e2bf4846c88041ea9ccae59", size = 3192, upload-time = "2024-12-12T08:53:07.641Z" }, +] + +[[package]] +name = "pytest-gitconfig" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/c7/39ad46d239bf49e6c1c8b4f6b99e75c8bee7bfc1e83cd8542d8701190508/pytest_gitconfig-0.9.0.tar.gz", hash = "sha256:5f9e8a29b4a8e55ddd740216ddb0a8a5e97f1c9c7f6bfdac91863473a8c60f9c", size = 10078, upload-time = "2025-12-28T01:52:17.821Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/78/460084e968adb270fa1b15d3b125d3d6da25514293e05c811820a19bfc04/pytest_gitconfig-0.9.0-py3-none-any.whl", hash = "sha256:3d855a9dd5fb3906010dbb1f8161366d4d86b34df8c14021fa012f23de3e5354", size = 7113, upload-time = "2025-12-28T01:52:16.395Z" }, +] + +[[package]] +name = "pytest-mock" +version = "3.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" }, +] + +[[package]] +name = "pytest-regressions" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, + { name = "pytest-datadir" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3a/63/cdb0ee15012a538fa07de21ec0a5c8eb113db9f28378f67b538d1c0b6d04/pytest_regressions-2.8.3.tar.gz", hash = "sha256:1ad90708bee02a3d36c78ef0b6f9692a9a30d312dd828680fd6d2a7235fcd221", size = 117168, upload-time = "2025-09-05T12:51:32.319Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/b9/7b2fe8407744cc37a74e29bed833256a305133505ea4979564911a98338b/pytest_regressions-2.8.3-py3-none-any.whl", hash = "sha256:72500dd95bde418c850f290a3108dacb56427067f364f7112cb5b16f6d6cc29c", size = 24894, upload-time = "2025-09-05T12:51:31.1Z" }, +] + +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyyaml-env-tag" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" }, +] + +[[package]] +name = "questionary" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/45/eafb0bba0f9988f6a2520f9ca2df2c82ddfa8d67c95d6625452e97b204a5/questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d", size = 25845, upload-time = "2025-08-28T19:00:20.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59", size = 36753, upload-time = "2025-08-28T19:00:19.56Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rich" +version = "14.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, +] + +[[package]] +name = "ruff" +version = "0.14.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/08/52232a877978dd8f9cf2aeddce3e611b40a63287dfca29b6b8da791f5e8d/ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4", size = 5859763, upload-time = "2025-12-18T19:28:57.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/01/933704d69f3f05ee16ef11406b78881733c186fe14b6a46b05cfcaf6d3b2/ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49", size = 13527080, upload-time = "2025-12-18T19:29:25.642Z" }, + { url = "https://files.pythonhosted.org/packages/df/58/a0349197a7dfa603ffb7f5b0470391efa79ddc327c1e29c4851e85b09cc5/ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f", size = 13797320, upload-time = "2025-12-18T19:29:02.571Z" }, + { url = "https://files.pythonhosted.org/packages/7b/82/36be59f00a6082e38c23536df4e71cdbc6af8d7c707eade97fcad5c98235/ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d", size = 12918434, upload-time = "2025-12-18T19:28:51.202Z" }, + { url = "https://files.pythonhosted.org/packages/a6/00/45c62a7f7e34da92a25804f813ebe05c88aa9e0c25e5cb5a7d23dd7450e3/ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77", size = 13371961, upload-time = "2025-12-18T19:29:04.991Z" }, + { url = "https://files.pythonhosted.org/packages/40/31/a5906d60f0405f7e57045a70f2d57084a93ca7425f22e1d66904769d1628/ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a", size = 13275629, upload-time = "2025-12-18T19:29:21.381Z" }, + { url = "https://files.pythonhosted.org/packages/3e/60/61c0087df21894cf9d928dc04bcd4fb10e8b2e8dca7b1a276ba2155b2002/ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f", size = 14029234, upload-time = "2025-12-18T19:29:00.132Z" }, + { url = "https://files.pythonhosted.org/packages/44/84/77d911bee3b92348b6e5dab5a0c898d87084ea03ac5dc708f46d88407def/ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935", size = 15449890, upload-time = "2025-12-18T19:28:53.573Z" }, + { url = "https://files.pythonhosted.org/packages/e9/36/480206eaefa24a7ec321582dda580443a8f0671fdbf6b1c80e9c3e93a16a/ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e", size = 15123172, upload-time = "2025-12-18T19:29:23.453Z" }, + { url = "https://files.pythonhosted.org/packages/5c/38/68e414156015ba80cef5473d57919d27dfb62ec804b96180bafdeaf0e090/ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d", size = 14460260, upload-time = "2025-12-18T19:29:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/b3/19/9e050c0dca8aba824d67cc0db69fb459c28d8cd3f6855b1405b3f29cc91d/ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f", size = 14229978, upload-time = "2025-12-18T19:29:11.32Z" }, + { url = "https://files.pythonhosted.org/packages/51/eb/e8dd1dd6e05b9e695aa9dd420f4577debdd0f87a5ff2fedda33c09e9be8c/ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f", size = 14338036, upload-time = "2025-12-18T19:29:09.184Z" }, + { url = "https://files.pythonhosted.org/packages/6a/12/f3e3a505db7c19303b70af370d137795fcfec136d670d5de5391e295c134/ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d", size = 13264051, upload-time = "2025-12-18T19:29:13.431Z" }, + { url = "https://files.pythonhosted.org/packages/08/64/8c3a47eaccfef8ac20e0484e68e0772013eb85802f8a9f7603ca751eb166/ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405", size = 13283998, upload-time = "2025-12-18T19:29:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/12/84/534a5506f4074e5cc0529e5cd96cfc01bb480e460c7edf5af70d2bcae55e/ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60", size = 13601891, upload-time = "2025-12-18T19:28:55.811Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1e/14c916087d8598917dbad9b2921d340f7884824ad6e9c55de948a93b106d/ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830", size = 14336660, upload-time = "2025-12-18T19:29:16.531Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1c/d7b67ab43f30013b47c12b42d1acd354c195351a3f7a1d67f59e54227ede/ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6", size = 13196187, upload-time = "2025-12-18T19:29:19.006Z" }, + { url = "https://files.pythonhosted.org/packages/fb/9c/896c862e13886fae2af961bef3e6312db9ebc6adc2b156fe95e615dee8c1/ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154", size = 14661283, upload-time = "2025-12-18T19:29:30.16Z" }, + { url = "https://files.pythonhosted.org/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "termcolor" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/56/ab275c2b56a5e2342568838f0d5e3e66a32354adcc159b495e374cda43f5/termcolor-3.2.0.tar.gz", hash = "sha256:610e6456feec42c4bcd28934a8c87a06c3fa28b01561d46aa09a9881b8622c58", size = 14423, upload-time = "2025-10-25T19:11:42.586Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl", hash = "sha256:a10343879eba4da819353c55cb8049b0933890c2ebf9ad5d3ecd2bb32ea96ea6", size = 7698, upload-time = "2025-10-25T19:11:41.536Z" }, +] + +[[package]] +name = "tomli" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, + { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, + { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, + { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, + { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, + { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, + { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, + { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, + { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, + { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, + { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, + { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, + { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, + { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, + { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, + { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, + { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, + { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, + { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, + { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, + { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, + { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, +] + +[[package]] +name = "tox" +version = "4.32.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachetools" }, + { name = "chardet" }, + { name = "colorama" }, + { name = "filelock" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "pluggy" }, + { name = "pyproject-api" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/59/bf/0e4dbd42724cbae25959f0e34c95d0c730df03ab03f54d52accd9abfc614/tox-4.32.0.tar.gz", hash = "sha256:1ad476b5f4d3679455b89a992849ffc3367560bbc7e9495ee8a3963542e7c8ff", size = 203330, upload-time = "2025-10-24T18:03:38.132Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl", hash = "sha256:451e81dc02ba8d1ed20efd52ee409641ae4b5d5830e008af10fe8823ef1bd551", size = 175905, upload-time = "2025-10-24T18:03:36.337Z" }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + +[[package]] +name = "types-colorama" +version = "0.4.15.20250801" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/37/af713e7d73ca44738c68814cbacf7a655aa40ddd2e8513d431ba78ace7b3/types_colorama-0.4.15.20250801.tar.gz", hash = "sha256:02565d13d68963d12237d3f330f5ecd622a3179f7b5b14ee7f16146270c357f5", size = 10437, upload-time = "2025-08-01T03:48:22.605Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/3a/44ccbbfef6235aeea84c74041dc6dfee6c17ff3ddba782a0250e41687ec7/types_colorama-0.4.15.20250801-py3-none-any.whl", hash = "sha256:b6e89bd3b250fdad13a8b6a465c933f4a5afe485ea2e2f104d739be50b13eea9", size = 10743, upload-time = "2025-08-01T03:48:21.774Z" }, +] + +[[package]] +name = "types-deprecated" +version = "1.3.1.20251101" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/96/0f96107945697e452c56a2e9f575da627e61d67940e5913d9c968e5e8be1/types_deprecated-1.3.1.20251101.tar.gz", hash = "sha256:f002d266b73201f46ec6fc712c1f016067ec6cb44357559cdb50c86b010951a7", size = 8358, upload-time = "2025-11-01T03:04:05.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/50/fb191dba89031e30c9ea07c3133c6fe8e7da038ef4d0b79539cf85fb1a97/types_deprecated-1.3.1.20251101-py3-none-any.whl", hash = "sha256:274edcc2a084d3fe31802d3c1379abd630716d3db34e40577e12ad84d6b73134", size = 9057, upload-time = "2025-11-01T03:04:04.633Z" }, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20251115" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/36/06d01fb52c0d57e9ad0c237654990920fa41195e4b3d640830dabf9eeb2f/types_python_dateutil-2.9.0.20251115.tar.gz", hash = "sha256:8a47f2c3920f52a994056b8786309b43143faa5a64d4cbb2722d6addabdf1a58", size = 16363, upload-time = "2025-11-15T03:00:13.717Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/0b/56961d3ba517ed0df9b3a27bfda6514f3d01b28d499d1bce9068cfe4edd1/types_python_dateutil-2.9.0.20251115-py3-none-any.whl", hash = "sha256:9cf9c1c582019753b8639a081deefd7e044b9fa36bd8217f565c6c4e36ee0624", size = 18251, upload-time = "2025-11-15T03:00:12.317Z" }, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.20250915" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/69/3c51b36d04da19b92f9e815be12753125bd8bc247ba0470a982e6979e71c/types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3", size = 17522, upload-time = "2025-09-15T03:01:00.728Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/e0/1eed384f02555dde685fff1a1ac805c1c7dcb6dd019c916fe659b1c1f9ec/types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6", size = 20338, upload-time = "2025-09-15T03:00:59.218Z" }, +] + +[[package]] +name = "types-termcolor" +version = "1.1.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/c8/77b1d73399d1cb77823ad32a36490b6a9851a7bd84f3a54560adab7ae022/types-termcolor-1.1.6.2.tar.gz", hash = "sha256:d8f0f69cf5552cc59ce75aa5172937cec9b320c17453adefe4168b93d16daad6", size = 2594, upload-time = "2023-03-28T01:19:18.367Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/94/0b01039dcb59173fc1f172a29b455986108f02fad9c5e103ff48afe17f35/types_termcolor-1.1.6.2-py3-none-any.whl", hash = "sha256:44c4c762c54a90d99b5c1033ef008aaa5610056d31d5c66b9288a942682a64d7", size = 2360, upload-time = "2023-03-28T01:19:17.328Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "urllib3" +version = "2.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, +] + +[[package]] +name = "virtualenv" +version = "20.35.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/20/28/e6f1a6f655d620846bd9df527390ecc26b3805a0c5989048c210e22c5ca9/virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", size = 6028799, upload-time = "2025-10-29T06:57:40.511Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" }, +] + +[[package]] +name = "watchdog" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/56/90994d789c61df619bfc5ce2ecdabd5eeff564e1eb47512bd01b5e019569/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26", size = 96390, upload-time = "2024-11-01T14:06:24.793Z" }, + { url = "https://files.pythonhosted.org/packages/55/46/9a67ee697342ddf3c6daa97e3a587a56d6c4052f881ed926a849fcf7371c/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112", size = 88389, upload-time = "2024-11-01T14:06:27.112Z" }, + { url = "https://files.pythonhosted.org/packages/44/65/91b0985747c52064d8701e1075eb96f8c40a79df889e59a399453adfb882/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3", size = 89020, upload-time = "2024-11-01T14:06:29.876Z" }, + { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, + { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, + { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, + { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" }, + { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" }, + { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, + { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, + { url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902, upload-time = "2024-11-01T14:06:53.119Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380, upload-time = "2024-11-01T14:06:55.19Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, + { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, + { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, + { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, + { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, +] + +[[package]] +name = "wrapt" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2a/6de8a50cb435b7f42c46126cf1a54b2aab81784e74c8595c8e025e8f36d3/wrapt-2.0.1.tar.gz", hash = "sha256:9c9c635e78497cacb81e84f8b11b23e0aacac7a136e73b8e5b2109a1d9fc468f", size = 82040, upload-time = "2025-11-07T00:45:33.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/0d/12d8c803ed2ce4e5e7d5b9f5f602721f9dfef82c95959f3ce97fa584bb5c/wrapt-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:64b103acdaa53b7caf409e8d45d39a8442fe6dcfec6ba3f3d141e0cc2b5b4dbd", size = 77481, upload-time = "2025-11-07T00:43:11.103Z" }, + { url = "https://files.pythonhosted.org/packages/05/3e/4364ebe221ebf2a44d9fc8695a19324692f7dd2795e64bd59090856ebf12/wrapt-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91bcc576260a274b169c3098e9a3519fb01f2989f6d3d386ef9cbf8653de1374", size = 60692, upload-time = "2025-11-07T00:43:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ff/ae2a210022b521f86a8ddcdd6058d137c051003812b0388a5e9a03d3fe10/wrapt-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab594f346517010050126fcd822697b25a7031d815bb4fbc238ccbe568216489", size = 61574, upload-time = "2025-11-07T00:43:14.967Z" }, + { url = "https://files.pythonhosted.org/packages/c6/93/5cf92edd99617095592af919cb81d4bff61c5dbbb70d3c92099425a8ec34/wrapt-2.0.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:36982b26f190f4d737f04a492a68accbfc6fa042c3f42326fdfbb6c5b7a20a31", size = 113688, upload-time = "2025-11-07T00:43:18.275Z" }, + { url = "https://files.pythonhosted.org/packages/a0/0a/e38fc0cee1f146c9fb266d8ef96ca39fb14a9eef165383004019aa53f88a/wrapt-2.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23097ed8bc4c93b7bf36fa2113c6c733c976316ce0ee2c816f64ca06102034ef", size = 115698, upload-time = "2025-11-07T00:43:19.407Z" }, + { url = "https://files.pythonhosted.org/packages/b0/85/bef44ea018b3925fb0bcbe9112715f665e4d5309bd945191da814c314fd1/wrapt-2.0.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8bacfe6e001749a3b64db47bcf0341da757c95959f592823a93931a422395013", size = 112096, upload-time = "2025-11-07T00:43:16.5Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0b/733a2376e413117e497aa1a5b1b78e8f3a28c0e9537d26569f67d724c7c5/wrapt-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8ec3303e8a81932171f455f792f8df500fc1a09f20069e5c16bd7049ab4e8e38", size = 114878, upload-time = "2025-11-07T00:43:20.81Z" }, + { url = "https://files.pythonhosted.org/packages/da/03/d81dcb21bbf678fcda656495792b059f9d56677d119ca022169a12542bd0/wrapt-2.0.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:3f373a4ab5dbc528a94334f9fe444395b23c2f5332adab9ff4ea82f5a9e33bc1", size = 111298, upload-time = "2025-11-07T00:43:22.229Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d5/5e623040e8056e1108b787020d56b9be93dbbf083bf2324d42cde80f3a19/wrapt-2.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f49027b0b9503bf6c8cdc297ca55006b80c2f5dd36cecc72c6835ab6e10e8a25", size = 113361, upload-time = "2025-11-07T00:43:24.301Z" }, + { url = "https://files.pythonhosted.org/packages/a1/f3/de535ccecede6960e28c7b722e5744846258111d6c9f071aa7578ea37ad3/wrapt-2.0.1-cp310-cp310-win32.whl", hash = "sha256:8330b42d769965e96e01fa14034b28a2a7600fbf7e8f0cc90ebb36d492c993e4", size = 58035, upload-time = "2025-11-07T00:43:28.96Z" }, + { url = "https://files.pythonhosted.org/packages/21/15/39d3ca5428a70032c2ec8b1f1c9d24c32e497e7ed81aed887a4998905fcc/wrapt-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:1218573502a8235bb8a7ecaed12736213b22dcde9feab115fa2989d42b5ded45", size = 60383, upload-time = "2025-11-07T00:43:25.804Z" }, + { url = "https://files.pythonhosted.org/packages/43/c2/dfd23754b7f7a4dce07e08f4309c4e10a40046a83e9ae1800f2e6b18d7c1/wrapt-2.0.1-cp310-cp310-win_arm64.whl", hash = "sha256:eda8e4ecd662d48c28bb86be9e837c13e45c58b8300e43ba3c9b4fa9900302f7", size = 58894, upload-time = "2025-11-07T00:43:27.074Z" }, + { url = "https://files.pythonhosted.org/packages/98/60/553997acf3939079dab022e37b67b1904b5b0cc235503226898ba573b10c/wrapt-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e17283f533a0d24d6e5429a7d11f250a58d28b4ae5186f8f47853e3e70d2590", size = 77480, upload-time = "2025-11-07T00:43:30.573Z" }, + { url = "https://files.pythonhosted.org/packages/2d/50/e5b3d30895d77c52105c6d5cbf94d5b38e2a3dd4a53d22d246670da98f7c/wrapt-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85df8d92158cb8f3965aecc27cf821461bb5f40b450b03facc5d9f0d4d6ddec6", size = 60690, upload-time = "2025-11-07T00:43:31.594Z" }, + { url = "https://files.pythonhosted.org/packages/f0/40/660b2898703e5cbbb43db10cdefcc294274458c3ca4c68637c2b99371507/wrapt-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1be685ac7700c966b8610ccc63c3187a72e33cab53526a27b2a285a662cd4f7", size = 61578, upload-time = "2025-11-07T00:43:32.918Z" }, + { url = "https://files.pythonhosted.org/packages/5b/36/825b44c8a10556957bc0c1d84c7b29a40e05fcf1873b6c40aa9dbe0bd972/wrapt-2.0.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:df0b6d3b95932809c5b3fecc18fda0f1e07452d05e2662a0b35548985f256e28", size = 114115, upload-time = "2025-11-07T00:43:35.605Z" }, + { url = "https://files.pythonhosted.org/packages/83/73/0a5d14bb1599677304d3c613a55457d34c344e9b60eda8a737c2ead7619e/wrapt-2.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da7384b0e5d4cae05c97cd6f94faaf78cc8b0f791fc63af43436d98c4ab37bb", size = 116157, upload-time = "2025-11-07T00:43:37.058Z" }, + { url = "https://files.pythonhosted.org/packages/01/22/1c158fe763dbf0a119f985d945711d288994fe5514c0646ebe0eb18b016d/wrapt-2.0.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ec65a78fbd9d6f083a15d7613b2800d5663dbb6bb96003899c834beaa68b242c", size = 112535, upload-time = "2025-11-07T00:43:34.138Z" }, + { url = "https://files.pythonhosted.org/packages/5c/28/4f16861af67d6de4eae9927799b559c20ebdd4fe432e89ea7fe6fcd9d709/wrapt-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7de3cc939be0e1174969f943f3b44e0d79b6f9a82198133a5b7fc6cc92882f16", size = 115404, upload-time = "2025-11-07T00:43:39.214Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8b/7960122e625fad908f189b59c4aae2d50916eb4098b0fb2819c5a177414f/wrapt-2.0.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fb1a5b72cbd751813adc02ef01ada0b0d05d3dcbc32976ce189a1279d80ad4a2", size = 111802, upload-time = "2025-11-07T00:43:40.476Z" }, + { url = "https://files.pythonhosted.org/packages/3e/73/7881eee5ac31132a713ab19a22c9e5f1f7365c8b1df50abba5d45b781312/wrapt-2.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3fa272ca34332581e00bf7773e993d4f632594eb2d1b0b162a9038df0fd971dd", size = 113837, upload-time = "2025-11-07T00:43:42.921Z" }, + { url = "https://files.pythonhosted.org/packages/45/00/9499a3d14e636d1f7089339f96c4409bbc7544d0889f12264efa25502ae8/wrapt-2.0.1-cp311-cp311-win32.whl", hash = "sha256:fc007fdf480c77301ab1afdbb6ab22a5deee8885f3b1ed7afcb7e5e84a0e27be", size = 58028, upload-time = "2025-11-07T00:43:47.369Z" }, + { url = "https://files.pythonhosted.org/packages/70/5d/8f3d7eea52f22638748f74b102e38fdf88cb57d08ddeb7827c476a20b01b/wrapt-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:47434236c396d04875180171ee1f3815ca1eada05e24a1ee99546320d54d1d1b", size = 60385, upload-time = "2025-11-07T00:43:44.34Z" }, + { url = "https://files.pythonhosted.org/packages/14/e2/32195e57a8209003587bbbad44d5922f13e0ced2a493bb46ca882c5b123d/wrapt-2.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:837e31620e06b16030b1d126ed78e9383815cbac914693f54926d816d35d8edf", size = 58893, upload-time = "2025-11-07T00:43:46.161Z" }, + { url = "https://files.pythonhosted.org/packages/cb/73/8cb252858dc8254baa0ce58ce382858e3a1cf616acebc497cb13374c95c6/wrapt-2.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1fdbb34da15450f2b1d735a0e969c24bdb8d8924892380126e2a293d9902078c", size = 78129, upload-time = "2025-11-07T00:43:48.852Z" }, + { url = "https://files.pythonhosted.org/packages/19/42/44a0db2108526ee6e17a5ab72478061158f34b08b793df251d9fbb9a7eb4/wrapt-2.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d32794fe940b7000f0519904e247f902f0149edbe6316c710a8562fb6738841", size = 61205, upload-time = "2025-11-07T00:43:50.402Z" }, + { url = "https://files.pythonhosted.org/packages/4d/8a/5b4b1e44b791c22046e90d9b175f9a7581a8cc7a0debbb930f81e6ae8e25/wrapt-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:386fb54d9cd903ee0012c09291336469eb7b244f7183d40dc3e86a16a4bace62", size = 61692, upload-time = "2025-11-07T00:43:51.678Z" }, + { url = "https://files.pythonhosted.org/packages/11/53/3e794346c39f462bcf1f58ac0487ff9bdad02f9b6d5ee2dc84c72e0243b2/wrapt-2.0.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7b219cb2182f230676308cdcacd428fa837987b89e4b7c5c9025088b8a6c9faf", size = 121492, upload-time = "2025-11-07T00:43:55.017Z" }, + { url = "https://files.pythonhosted.org/packages/c6/7e/10b7b0e8841e684c8ca76b462a9091c45d62e8f2de9c4b1390b690eadf16/wrapt-2.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:641e94e789b5f6b4822bb8d8ebbdfc10f4e4eae7756d648b717d980f657a9eb9", size = 123064, upload-time = "2025-11-07T00:43:56.323Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d1/3c1e4321fc2f5ee7fd866b2d822aa89b84495f28676fd976c47327c5b6aa/wrapt-2.0.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe21b118b9f58859b5ebaa4b130dee18669df4bd111daad082b7beb8799ad16b", size = 117403, upload-time = "2025-11-07T00:43:53.258Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b0/d2f0a413cf201c8c2466de08414a15420a25aa83f53e647b7255cc2fab5d/wrapt-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17fb85fa4abc26a5184d93b3efd2dcc14deb4b09edcdb3535a536ad34f0b4dba", size = 121500, upload-time = "2025-11-07T00:43:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/bd/45/bddb11d28ca39970a41ed48a26d210505120f925918592283369219f83cc/wrapt-2.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b89ef9223d665ab255ae42cc282d27d69704d94be0deffc8b9d919179a609684", size = 116299, upload-time = "2025-11-07T00:43:58.877Z" }, + { url = "https://files.pythonhosted.org/packages/81/af/34ba6dd570ef7a534e7eec0c25e2615c355602c52aba59413411c025a0cb/wrapt-2.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a453257f19c31b31ba593c30d997d6e5be39e3b5ad9148c2af5a7314061c63eb", size = 120622, upload-time = "2025-11-07T00:43:59.962Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3e/693a13b4146646fb03254636f8bafd20c621955d27d65b15de07ab886187/wrapt-2.0.1-cp312-cp312-win32.whl", hash = "sha256:3e271346f01e9c8b1130a6a3b0e11908049fe5be2d365a5f402778049147e7e9", size = 58246, upload-time = "2025-11-07T00:44:03.169Z" }, + { url = "https://files.pythonhosted.org/packages/a7/36/715ec5076f925a6be95f37917b66ebbeaa1372d1862c2ccd7a751574b068/wrapt-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:2da620b31a90cdefa9cd0c2b661882329e2e19d1d7b9b920189956b76c564d75", size = 60492, upload-time = "2025-11-07T00:44:01.027Z" }, + { url = "https://files.pythonhosted.org/packages/ef/3e/62451cd7d80f65cc125f2b426b25fbb6c514bf6f7011a0c3904fc8c8df90/wrapt-2.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:aea9c7224c302bc8bfc892b908537f56c430802560e827b75ecbde81b604598b", size = 58987, upload-time = "2025-11-07T00:44:02.095Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/41af4c46b5e498c90fc87981ab2972fbd9f0bccda597adb99d3d3441b94b/wrapt-2.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:47b0f8bafe90f7736151f61482c583c86b0693d80f075a58701dd1549b0010a9", size = 78132, upload-time = "2025-11-07T00:44:04.628Z" }, + { url = "https://files.pythonhosted.org/packages/1c/92/d68895a984a5ebbbfb175512b0c0aad872354a4a2484fbd5552e9f275316/wrapt-2.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cbeb0971e13b4bd81d34169ed57a6dda017328d1a22b62fda45e1d21dd06148f", size = 61211, upload-time = "2025-11-07T00:44:05.626Z" }, + { url = "https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218", size = 61689, upload-time = "2025-11-07T00:44:06.719Z" }, + { url = "https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9", size = 121502, upload-time = "2025-11-07T00:44:09.557Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c", size = 123110, upload-time = "2025-11-07T00:44:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/e5/08/cdbb965fbe4c02c5233d185d070cabed2ecc1f1e47662854f95d77613f57/wrapt-2.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:98d873ed6c8b4ee2418f7afce666751854d6d03e3c0ec2a399bb039cd2ae89db", size = 117434, upload-time = "2025-11-07T00:44:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/6aae2ce39db4cb5216302fa2e9577ad74424dfbe315bd6669725569e048c/wrapt-2.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9e850f5b7fc67af856ff054c71690d54fa940c3ef74209ad9f935b4f66a0233", size = 121533, upload-time = "2025-11-07T00:44:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/79/35/565abf57559fbe0a9155c29879ff43ce8bd28d2ca61033a3a3dd67b70794/wrapt-2.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e505629359cb5f751e16e30cf3f91a1d3ddb4552480c205947da415d597f7ac2", size = 116324, upload-time = "2025-11-07T00:44:13.28Z" }, + { url = "https://files.pythonhosted.org/packages/e1/e0/53ff5e76587822ee33e560ad55876d858e384158272cd9947abdd4ad42ca/wrapt-2.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2879af909312d0baf35f08edeea918ee3af7ab57c37fe47cb6a373c9f2749c7b", size = 120627, upload-time = "2025-11-07T00:44:14.431Z" }, + { url = "https://files.pythonhosted.org/packages/7c/7b/38df30fd629fbd7612c407643c63e80e1c60bcc982e30ceeae163a9800e7/wrapt-2.0.1-cp313-cp313-win32.whl", hash = "sha256:d67956c676be5a24102c7407a71f4126d30de2a569a1c7871c9f3cabc94225d7", size = 58252, upload-time = "2025-11-07T00:44:17.814Z" }, + { url = "https://files.pythonhosted.org/packages/85/64/d3954e836ea67c4d3ad5285e5c8fd9d362fd0a189a2db622df457b0f4f6a/wrapt-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9ca66b38dd642bf90c59b6738af8070747b610115a39af2498535f62b5cdc1c3", size = 60500, upload-time = "2025-11-07T00:44:15.561Z" }, + { url = "https://files.pythonhosted.org/packages/89/4e/3c8b99ac93527cfab7f116089db120fef16aac96e5f6cdb724ddf286086d/wrapt-2.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:5a4939eae35db6b6cec8e7aa0e833dcca0acad8231672c26c2a9ab7a0f8ac9c8", size = 58993, upload-time = "2025-11-07T00:44:16.65Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f4/eff2b7d711cae20d220780b9300faa05558660afb93f2ff5db61fe725b9a/wrapt-2.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a52f93d95c8d38fed0669da2ebdb0b0376e895d84596a976c15a9eb45e3eccb3", size = 82028, upload-time = "2025-11-07T00:44:18.944Z" }, + { url = "https://files.pythonhosted.org/packages/0c/67/cb945563f66fd0f61a999339460d950f4735c69f18f0a87ca586319b1778/wrapt-2.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e54bbf554ee29fcceee24fa41c4d091398b911da6e7f5d7bffda963c9aed2e1", size = 62949, upload-time = "2025-11-07T00:44:20.074Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ca/f63e177f0bbe1e5cf5e8d9b74a286537cd709724384ff20860f8f6065904/wrapt-2.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:908f8c6c71557f4deaa280f55d0728c3bca0960e8c3dd5ceeeafb3c19942719d", size = 63681, upload-time = "2025-11-07T00:44:21.345Z" }, + { url = "https://files.pythonhosted.org/packages/39/a1/1b88fcd21fd835dca48b556daef750952e917a2794fa20c025489e2e1f0f/wrapt-2.0.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e2f84e9af2060e3904a32cea9bb6db23ce3f91cfd90c6b426757cf7cc01c45c7", size = 152696, upload-time = "2025-11-07T00:44:24.318Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/d9185500c1960d9f5f77b9c0b890b7fc62282b53af7ad1b6bd779157f714/wrapt-2.0.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3612dc06b436968dfb9142c62e5dfa9eb5924f91120b3c8ff501ad878f90eb3", size = 158859, upload-time = "2025-11-07T00:44:25.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/60/5d796ed0f481ec003220c7878a1d6894652efe089853a208ea0838c13086/wrapt-2.0.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d2d947d266d99a1477cd005b23cbd09465276e302515e122df56bb9511aca1b", size = 146068, upload-time = "2025-11-07T00:44:22.81Z" }, + { url = "https://files.pythonhosted.org/packages/04/f8/75282dd72f102ddbfba137e1e15ecba47b40acff32c08ae97edbf53f469e/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7d539241e87b650cbc4c3ac9f32c8d1ac8a54e510f6dca3f6ab60dcfd48c9b10", size = 155724, upload-time = "2025-11-07T00:44:26.634Z" }, + { url = "https://files.pythonhosted.org/packages/5a/27/fe39c51d1b344caebb4a6a9372157bdb8d25b194b3561b52c8ffc40ac7d1/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4811e15d88ee62dbf5c77f2c3ff3932b1e3ac92323ba3912f51fc4016ce81ecf", size = 144413, upload-time = "2025-11-07T00:44:27.939Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/9f6b643fe39d4505c7bf926d7c2595b7cb4b607c8c6b500e56c6b36ac238/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c1c91405fcf1d501fa5d55df21e58ea49e6b879ae829f1039faaf7e5e509b41e", size = 150325, upload-time = "2025-11-07T00:44:29.29Z" }, + { url = "https://files.pythonhosted.org/packages/bb/b6/20ffcf2558596a7f58a2e69c89597128781f0b88e124bf5a4cadc05b8139/wrapt-2.0.1-cp313-cp313t-win32.whl", hash = "sha256:e76e3f91f864e89db8b8d2a8311d57df93f01ad6bb1e9b9976d1f2e83e18315c", size = 59943, upload-time = "2025-11-07T00:44:33.211Z" }, + { url = "https://files.pythonhosted.org/packages/87/6a/0e56111cbb3320151eed5d3821ee1373be13e05b376ea0870711f18810c3/wrapt-2.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:83ce30937f0ba0d28818807b303a412440c4b63e39d3d8fc036a94764b728c92", size = 63240, upload-time = "2025-11-07T00:44:30.935Z" }, + { url = "https://files.pythonhosted.org/packages/1d/54/5ab4c53ea1f7f7e5c3e7c1095db92932cc32fd62359d285486d00c2884c3/wrapt-2.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:4b55cacc57e1dc2d0991dbe74c6419ffd415fb66474a02335cb10efd1aa3f84f", size = 60416, upload-time = "2025-11-07T00:44:32.002Z" }, + { url = "https://files.pythonhosted.org/packages/73/81/d08d83c102709258e7730d3cd25befd114c60e43ef3891d7e6877971c514/wrapt-2.0.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5e53b428f65ece6d9dad23cb87e64506392b720a0b45076c05354d27a13351a1", size = 78290, upload-time = "2025-11-07T00:44:34.691Z" }, + { url = "https://files.pythonhosted.org/packages/f6/14/393afba2abb65677f313aa680ff0981e829626fed39b6a7e3ec807487790/wrapt-2.0.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ad3ee9d0f254851c71780966eb417ef8e72117155cff04821ab9b60549694a55", size = 61255, upload-time = "2025-11-07T00:44:35.762Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/a4a1f2fba205a9462e36e708ba37e5ac95f4987a0f1f8fd23f0bf1fc3b0f/wrapt-2.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7b822c61ed04ee6ad64bc90d13368ad6eb094db54883b5dde2182f67a7f22c0", size = 61797, upload-time = "2025-11-07T00:44:37.22Z" }, + { url = "https://files.pythonhosted.org/packages/12/db/99ba5c37cf1c4fad35349174f1e38bd8d992340afc1ff27f526729b98986/wrapt-2.0.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7164a55f5e83a9a0b031d3ffab4d4e36bbec42e7025db560f225489fa929e509", size = 120470, upload-time = "2025-11-07T00:44:39.425Z" }, + { url = "https://files.pythonhosted.org/packages/30/3f/a1c8d2411eb826d695fc3395a431757331582907a0ec59afce8fe8712473/wrapt-2.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e60690ba71a57424c8d9ff28f8d006b7ad7772c22a4af432188572cd7fa004a1", size = 122851, upload-time = "2025-11-07T00:44:40.582Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8d/72c74a63f201768d6a04a8845c7976f86be6f5ff4d74996c272cefc8dafc/wrapt-2.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3cd1a4bd9a7a619922a8557e1318232e7269b5fb69d4ba97b04d20450a6bf970", size = 117433, upload-time = "2025-11-07T00:44:38.313Z" }, + { url = "https://files.pythonhosted.org/packages/c7/5a/df37cf4042cb13b08256f8e27023e2f9b3d471d553376616591bb99bcb31/wrapt-2.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b4c2e3d777e38e913b8ce3a6257af72fb608f86a1df471cb1d4339755d0a807c", size = 121280, upload-time = "2025-11-07T00:44:41.69Z" }, + { url = "https://files.pythonhosted.org/packages/54/34/40d6bc89349f9931e1186ceb3e5fbd61d307fef814f09fbbac98ada6a0c8/wrapt-2.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3d366aa598d69416b5afedf1faa539fac40c1d80a42f6b236c88c73a3c8f2d41", size = 116343, upload-time = "2025-11-07T00:44:43.013Z" }, + { url = "https://files.pythonhosted.org/packages/70/66/81c3461adece09d20781dee17c2366fdf0cb8754738b521d221ca056d596/wrapt-2.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c235095d6d090aa903f1db61f892fffb779c1eaeb2a50e566b52001f7a0f66ed", size = 119650, upload-time = "2025-11-07T00:44:44.523Z" }, + { url = "https://files.pythonhosted.org/packages/46/3a/d0146db8be8761a9e388cc9cc1c312b36d583950ec91696f19bbbb44af5a/wrapt-2.0.1-cp314-cp314-win32.whl", hash = "sha256:bfb5539005259f8127ea9c885bdc231978c06b7a980e63a8a61c8c4c979719d0", size = 58701, upload-time = "2025-11-07T00:44:48.277Z" }, + { url = "https://files.pythonhosted.org/packages/1a/38/5359da9af7d64554be63e9046164bd4d8ff289a2dd365677d25ba3342c08/wrapt-2.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:4ae879acc449caa9ed43fc36ba08392b9412ee67941748d31d94e3cedb36628c", size = 60947, upload-time = "2025-11-07T00:44:46.086Z" }, + { url = "https://files.pythonhosted.org/packages/aa/3f/96db0619276a833842bf36343685fa04f987dd6e3037f314531a1e00492b/wrapt-2.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:8639b843c9efd84675f1e100ed9e99538ebea7297b62c4b45a7042edb84db03e", size = 59359, upload-time = "2025-11-07T00:44:47.164Z" }, + { url = "https://files.pythonhosted.org/packages/71/49/5f5d1e867bf2064bf3933bc6cf36ade23505f3902390e175e392173d36a2/wrapt-2.0.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:9219a1d946a9b32bb23ccae66bdb61e35c62773ce7ca6509ceea70f344656b7b", size = 82031, upload-time = "2025-11-07T00:44:49.4Z" }, + { url = "https://files.pythonhosted.org/packages/2b/89/0009a218d88db66ceb83921e5685e820e2c61b59bbbb1324ba65342668bc/wrapt-2.0.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fa4184e74197af3adad3c889a1af95b53bb0466bced92ea99a0c014e48323eec", size = 62952, upload-time = "2025-11-07T00:44:50.74Z" }, + { url = "https://files.pythonhosted.org/packages/ae/18/9b968e920dd05d6e44bcc918a046d02afea0fb31b2f1c80ee4020f377cbe/wrapt-2.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c5ef2f2b8a53b7caee2f797ef166a390fef73979b15778a4a153e4b5fedce8fa", size = 63688, upload-time = "2025-11-07T00:44:52.248Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7d/78bdcb75826725885d9ea26c49a03071b10c4c92da93edda612910f150e4/wrapt-2.0.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e042d653a4745be832d5aa190ff80ee4f02c34b21f4b785745eceacd0907b815", size = 152706, upload-time = "2025-11-07T00:44:54.613Z" }, + { url = "https://files.pythonhosted.org/packages/dd/77/cac1d46f47d32084a703df0d2d29d47e7eb2a7d19fa5cbca0e529ef57659/wrapt-2.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2afa23318136709c4b23d87d543b425c399887b4057936cd20386d5b1422b6fa", size = 158866, upload-time = "2025-11-07T00:44:55.79Z" }, + { url = "https://files.pythonhosted.org/packages/8a/11/b521406daa2421508903bf8d5e8b929216ec2af04839db31c0a2c525eee0/wrapt-2.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c72328f668cf4c503ffcf9434c2b71fdd624345ced7941bc6693e61bbe36bef", size = 146148, upload-time = "2025-11-07T00:44:53.388Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c0/340b272bed297baa7c9ce0c98ef7017d9c035a17a6a71dce3184b8382da2/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3793ac154afb0e5b45d1233cb94d354ef7a983708cc3bb12563853b1d8d53747", size = 155737, upload-time = "2025-11-07T00:44:56.971Z" }, + { url = "https://files.pythonhosted.org/packages/f3/93/bfcb1fb2bdf186e9c2883a4d1ab45ab099c79cbf8f4e70ea453811fa3ea7/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:fec0d993ecba3991645b4857837277469c8cc4c554a7e24d064d1ca291cfb81f", size = 144451, upload-time = "2025-11-07T00:44:58.515Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6b/dca504fb18d971139d232652656180e3bd57120e1193d9a5899c3c0b7cdd/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:949520bccc1fa227274da7d03bf238be15389cd94e32e4297b92337df9b7a349", size = 150353, upload-time = "2025-11-07T00:44:59.753Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f6/a1de4bd3653afdf91d250ca5c721ee51195df2b61a4603d4b373aa804d1d/wrapt-2.0.1-cp314-cp314t-win32.whl", hash = "sha256:be9e84e91d6497ba62594158d3d31ec0486c60055c49179edc51ee43d095f79c", size = 60609, upload-time = "2025-11-07T00:45:03.315Z" }, + { url = "https://files.pythonhosted.org/packages/01/3a/07cd60a9d26fe73efead61c7830af975dfdba8537632d410462672e4432b/wrapt-2.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:61c4956171c7434634401db448371277d07032a81cc21c599c22953374781395", size = 64038, upload-time = "2025-11-07T00:45:00.948Z" }, + { url = "https://files.pythonhosted.org/packages/41/99/8a06b8e17dddbf321325ae4eb12465804120f699cd1b8a355718300c62da/wrapt-2.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:35cdbd478607036fee40273be8ed54a451f5f23121bd9d4be515158f9498f7ad", size = 60634, upload-time = "2025-11-07T00:45:02.087Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/b51471c11592ff9c012bd3e2f7334a6ff2f42a7aed2caffcf0bdddc9cb89/wrapt-2.0.1-py3-none-any.whl", hash = "sha256:4d2ce1bf1a48c5277d7969259232b57645aae5686dba1eaeade39442277afbca", size = 44046, upload-time = "2025-11-07T00:45:32.116Z" }, +] From de164ab72936f683380e20cb82fefb1de7772658 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Tue, 30 Dec 2025 16:27:13 +0100 Subject: [PATCH 145/221] ci(uv): don't specify Python version when not require --- .github/workflows/docspublish.yml | 4 ---- .github/workflows/homebrewpublish.yml | 2 -- .github/workflows/pythonpublish.yml | 2 -- 3 files changed, 8 deletions(-) diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index e70da7b9d8..c7eb973fb0 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -16,8 +16,6 @@ jobs: fetch-depth: 0 - name: Set up Python uses: astral-sh/setup-uv@v7 - with: - python-version: "3.x" - name: Install dependencies run: | uv --version @@ -51,8 +49,6 @@ jobs: git pull origin master - name: Set up Python uses: astral-sh/setup-uv@v7 - with: - python-version: "3.x" - name: Install dependencies run: | uv --version diff --git a/.github/workflows/homebrewpublish.yml b/.github/workflows/homebrewpublish.yml index ae92e28b77..0ea8eba0df 100644 --- a/.github/workflows/homebrewpublish.yml +++ b/.github/workflows/homebrewpublish.yml @@ -15,8 +15,6 @@ jobs: uses: actions/checkout@v6 - name: Set up Python uses: astral-sh/setup-uv@v7 - with: - python-version: "3.x" - name: Install dependencies run: uv pip install -U commitizen - name: Set Project version env variable diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 853fc33ccf..bddf13a5d8 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -15,8 +15,6 @@ jobs: fetch-depth: 0 - name: Set up Python uses: astral-sh/setup-uv@v7 - with: - python-version: "3.x" - name: Build run: uv build - name: Publish From 431300aff432ceb41e5647c7fa13b039f144cd62 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Tue, 30 Dec 2025 16:33:13 +0100 Subject: [PATCH 146/221] build(poe): do not call `uv run` in `poe` tasks --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ec456ed487..55d5f35943 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -255,7 +255,7 @@ lint.help = "Lint the code" lint.sequence = [{ cmd = "ruff check" }, { cmd = "mypy" }] check-commit.help = "Check the commit messages" -check-commit.cmd = "uv run cz --no-raise 3 check --rev-range origin/master.." +check-commit.cmd = "cz --no-raise 3 check --rev-range origin/master.." test.help = "Run the test suite" test.cmd = "pytest -n 3 --dist=loadfile" From 8088731ab02e8a17a433724ea2fd3cdfe79b2eb1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 31 Dec 2025 09:52:29 +0000 Subject: [PATCH 147/221] docs(cli/screenshots): update CLI screenshots [skip ci] --- docs/images/cli_help/cz___help.svg | 166 ++++----- docs/images/cli_help/cz_bump___help.svg | 358 ++++++++++--------- docs/images/cli_help/cz_changelog___help.svg | 198 +++++----- docs/images/cli_help/cz_check___help.svg | 146 ++++---- docs/images/cli_help/cz_commit___help.svg | 112 +++--- 5 files changed, 496 insertions(+), 484 deletions(-) diff --git a/docs/images/cli_help/cz___help.svg b/docs/images/cli_help/cz___help.svg index d580cfe619..ae9a135743 100644 --- a/docs/images/cli_help/cz___help.svg +++ b/docs/images/cli_help/cz___help.svg @@ -19,136 +19,136 @@ font-weight: 700; } - .terminal-1389600277-matrix { + .terminal-1688774822-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1389600277-title { + .terminal-1688774822-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1389600277-r1 { fill: #c5c8c6 } -.terminal-1389600277-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-1389600277-r3 { fill: #d0b344 } -.terminal-1389600277-r4 { fill: #1984e9;text-decoration: underline; } -.terminal-1389600277-r5 { fill: #68a0b3;font-weight: bold } + .terminal-1688774822-r1 { fill: #c5c8c6 } +.terminal-1688774822-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-1688774822-r3 { fill: #d0b344 } +.terminal-1688774822-r4 { fill: #1984e9;text-decoration: underline; } +.terminal-1688774822-r5 { fill: #68a0b3;font-weight: bold } </style> <defs> - <clipPath id="terminal-1389600277-clip-terminal"> + <clipPath id="terminal-1688774822-clip-terminal"> <rect x="0" y="0" width="975.0" height="901.8" /> </clipPath> - <clipPath id="terminal-1389600277-line-0"> + <clipPath id="terminal-1688774822-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-1"> +<clipPath id="terminal-1688774822-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-2"> +<clipPath id="terminal-1688774822-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-3"> +<clipPath id="terminal-1688774822-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-4"> +<clipPath id="terminal-1688774822-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-5"> +<clipPath id="terminal-1688774822-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-6"> +<clipPath id="terminal-1688774822-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-7"> +<clipPath id="terminal-1688774822-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-8"> +<clipPath id="terminal-1688774822-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-9"> +<clipPath id="terminal-1688774822-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-10"> +<clipPath id="terminal-1688774822-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-11"> +<clipPath id="terminal-1688774822-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-12"> +<clipPath id="terminal-1688774822-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-13"> +<clipPath id="terminal-1688774822-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-14"> +<clipPath id="terminal-1688774822-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-15"> +<clipPath id="terminal-1688774822-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-16"> +<clipPath id="terminal-1688774822-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-17"> +<clipPath id="terminal-1688774822-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-18"> +<clipPath id="terminal-1688774822-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-19"> +<clipPath id="terminal-1688774822-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-20"> +<clipPath id="terminal-1688774822-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-21"> +<clipPath id="terminal-1688774822-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-22"> +<clipPath id="terminal-1688774822-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-23"> +<clipPath id="terminal-1688774822-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-24"> +<clipPath id="terminal-1688774822-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-25"> +<clipPath id="terminal-1688774822-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-26"> +<clipPath id="terminal-1688774822-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-27"> +<clipPath id="terminal-1688774822-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-28"> +<clipPath id="terminal-1688774822-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-29"> +<clipPath id="terminal-1688774822-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-30"> +<clipPath id="terminal-1688774822-line-30"> <rect x="0" y="733.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-31"> +<clipPath id="terminal-1688774822-line-31"> <rect x="0" y="757.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-32"> +<clipPath id="terminal-1688774822-line-32"> <rect x="0" y="782.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-33"> +<clipPath id="terminal-1688774822-line-33"> <rect x="0" y="806.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-34"> +<clipPath id="terminal-1688774822-line-34"> <rect x="0" y="831.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1389600277-line-35"> +<clipPath id="terminal-1688774822-line-35"> <rect x="0" y="855.5" width="976" height="24.65"/> </clipPath> </defs> @@ -160,46 +160,46 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1389600277-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-1688774822-clip-terminal)"> - <g class="terminal-1389600277-matrix"> - <text class="terminal-1389600277-r1" x="0" y="20" textLength="134.2" clip-path="url(#terminal-1389600277-line-0)">$ cz --help</text><text class="terminal-1389600277-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1389600277-line-0)"> -</text><text class="terminal-1389600277-r1" x="0" y="44.4" textLength="122" clip-path="url(#terminal-1389600277-line-1)">usage: cz </text><text class="terminal-1389600277-r2" x="122" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">[</text><text class="terminal-1389600277-r1" x="134.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1389600277-line-1)">-h</text><text class="terminal-1389600277-r2" x="158.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">]</text><text class="terminal-1389600277-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">[</text><text class="terminal-1389600277-r1" x="195.2" y="44.4" textLength="183" clip-path="url(#terminal-1389600277-line-1)">--config CONFIG</text><text class="terminal-1389600277-r2" x="378.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">]</text><text class="terminal-1389600277-r2" x="402.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">[</text><text class="terminal-1389600277-r1" x="414.8" y="44.4" textLength="85.4" clip-path="url(#terminal-1389600277-line-1)">--debug</text><text class="terminal-1389600277-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">]</text><text class="terminal-1389600277-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">[</text><text class="terminal-1389600277-r1" x="536.8" y="44.4" textLength="85.4" clip-path="url(#terminal-1389600277-line-1)">-n NAME</text><text class="terminal-1389600277-r2" x="622.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">]</text><text class="terminal-1389600277-r2" x="646.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">[</text><text class="terminal-1389600277-r1" x="658.8" y="44.4" textLength="146.4" clip-path="url(#terminal-1389600277-line-1)">-nr NO_RAISE</text><text class="terminal-1389600277-r2" x="805.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)">]</text><text class="terminal-1389600277-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-1)"> -</text><text class="terminal-1389600277-r2" x="122" y="68.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-2)">{</text><text class="terminal-1389600277-r1" x="134.2" y="68.8" textLength="829.6" clip-path="url(#terminal-1389600277-line-2)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-1389600277-r2" x="963.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-2)">}</text><text class="terminal-1389600277-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-2)"> -</text><text class="terminal-1389600277-r3" x="0" y="93.2" textLength="36.6" clip-path="url(#terminal-1389600277-line-3)">...</text><text class="terminal-1389600277-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-3)"> -</text><text class="terminal-1389600277-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-4)"> -</text><text class="terminal-1389600277-r1" x="0" y="142" textLength="915" clip-path="url(#terminal-1389600277-line-5)">Commitizen is a powerful release management tool that helps teams maintain </text><text class="terminal-1389600277-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1389600277-line-5)"> -</text><text class="terminal-1389600277-r1" x="0" y="166.4" textLength="951.6" clip-path="url(#terminal-1389600277-line-6)">consistent and meaningful commit messages while automating version management.</text><text class="terminal-1389600277-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-6)"> -</text><text class="terminal-1389600277-r1" x="0" y="190.8" textLength="427" clip-path="url(#terminal-1389600277-line-7)">For more information, please visit </text><text class="terminal-1389600277-r4" x="427" y="190.8" textLength="549" clip-path="url(#terminal-1389600277-line-7)">https://commitizen-tools.github.io/commitizen</text><text class="terminal-1389600277-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-7)"> -</text><text class="terminal-1389600277-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-8)"> -</text><text class="terminal-1389600277-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-1389600277-line-9)">options:</text><text class="terminal-1389600277-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-9)"> -</text><text class="terminal-1389600277-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-1389600277-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-1389600277-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1389600277-line-10)"> -</text><text class="terminal-1389600277-r1" x="0" y="288.4" textLength="658.8" clip-path="url(#terminal-1389600277-line-11)">  --config CONFIG       the path of configuration file</text><text class="terminal-1389600277-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-11)"> -</text><text class="terminal-1389600277-r1" x="0" y="312.8" textLength="463.6" clip-path="url(#terminal-1389600277-line-12)">  --debug               use debug mode</text><text class="terminal-1389600277-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-12)"> -</text><text class="terminal-1389600277-r1" x="0" y="337.2" textLength="597.8" clip-path="url(#terminal-1389600277-line-13)">  -n, --name NAME       use the given commitizen </text><text class="terminal-1389600277-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-13)">(</text><text class="terminal-1389600277-r1" x="610" y="337.2" textLength="97.6" clip-path="url(#terminal-1389600277-line-13)">default:</text><text class="terminal-1389600277-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-13)"> -</text><text class="terminal-1389600277-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-1389600277-line-14)">                        cz_conventional_commits</text><text class="terminal-1389600277-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-14)">)</text><text class="terminal-1389600277-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-14)"> -</text><text class="terminal-1389600277-r1" x="0" y="386" textLength="317.2" clip-path="url(#terminal-1389600277-line-15)">  -nr, --no-raise NO_RAISE</text><text class="terminal-1389600277-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1389600277-line-15)"> -</text><text class="terminal-1389600277-r1" x="0" y="410.4" textLength="915" clip-path="url(#terminal-1389600277-line-16)">                        comma separated error codes that won't raise error,</text><text class="terminal-1389600277-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-16)"> -</text><text class="terminal-1389600277-r1" x="0" y="434.8" textLength="439.2" clip-path="url(#terminal-1389600277-line-17)">                        e.g: cz -nr </text><text class="terminal-1389600277-r5" x="439.2" y="434.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-17)">1</text><text class="terminal-1389600277-r1" x="451.4" y="434.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-17)">,</text><text class="terminal-1389600277-r5" x="463.6" y="434.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-17)">2</text><text class="terminal-1389600277-r1" x="475.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-17)">,</text><text class="terminal-1389600277-r5" x="488" y="434.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-17)">3</text><text class="terminal-1389600277-r1" x="500.2" y="434.8" textLength="231.8" clip-path="url(#terminal-1389600277-line-17)"> bump. See codes at</text><text class="terminal-1389600277-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-17)"> -</text><text class="terminal-1389600277-r4" x="292.8" y="459.2" textLength="231.8" clip-path="url(#terminal-1389600277-line-18)">https://commitizen-</text><text class="terminal-1389600277-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-18)"> -</text><text class="terminal-1389600277-r1" x="0" y="483.6" textLength="756.4" clip-path="url(#terminal-1389600277-line-19)">                        tools.github.io/commitizen/exit_codes/</text><text class="terminal-1389600277-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-19)"> -</text><text class="terminal-1389600277-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1389600277-line-20)"> -</text><text class="terminal-1389600277-r1" x="0" y="532.4" textLength="109.8" clip-path="url(#terminal-1389600277-line-21)">commands:</text><text class="terminal-1389600277-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-21)"> -</text><text class="terminal-1389600277-r2" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-22)">{</text><text class="terminal-1389600277-r1" x="36.6" y="556.8" textLength="829.6" clip-path="url(#terminal-1389600277-line-22)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-1389600277-r2" x="866.2" y="556.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-22)">}</text><text class="terminal-1389600277-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-22)"> -</text><text class="terminal-1389600277-r1" x="0" y="581.2" textLength="646.6" clip-path="url(#terminal-1389600277-line-23)">    init                init commitizen configuration</text><text class="terminal-1389600277-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-23)"> -</text><text class="terminal-1389600277-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-1389600277-line-24)">    commit </text><text class="terminal-1389600277-r2" x="134.2" y="605.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-24)">(</text><text class="terminal-1389600277-r1" x="146.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-24)">c</text><text class="terminal-1389600277-r2" x="158.6" y="605.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-24)">)</text><text class="terminal-1389600277-r1" x="170.8" y="605.6" textLength="329.4" clip-path="url(#terminal-1389600277-line-24)">          create new commit</text><text class="terminal-1389600277-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-24)"> -</text><text class="terminal-1389600277-r1" x="0" y="630" textLength="610" clip-path="url(#terminal-1389600277-line-25)">    ls                  show available commitizens</text><text class="terminal-1389600277-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1389600277-line-25)"> -</text><text class="terminal-1389600277-r1" x="0" y="654.4" textLength="524.6" clip-path="url(#terminal-1389600277-line-26)">    example             show commit example</text><text class="terminal-1389600277-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-26)"> -</text><text class="terminal-1389600277-r1" x="0" y="678.8" textLength="646.6" clip-path="url(#terminal-1389600277-line-27)">    info                show information about the cz</text><text class="terminal-1389600277-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-27)"> -</text><text class="terminal-1389600277-r1" x="0" y="703.2" textLength="512.4" clip-path="url(#terminal-1389600277-line-28)">    schema              show commit schema</text><text class="terminal-1389600277-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-28)"> -</text><text class="terminal-1389600277-r1" x="0" y="727.6" textLength="805.2" clip-path="url(#terminal-1389600277-line-29)">    bump                bump semantic version based on the git log</text><text class="terminal-1389600277-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-29)"> -</text><text class="terminal-1389600277-r1" x="0" y="752" textLength="170.8" clip-path="url(#terminal-1389600277-line-30)">    changelog </text><text class="terminal-1389600277-r2" x="170.8" y="752" textLength="12.2" clip-path="url(#terminal-1389600277-line-30)">(</text><text class="terminal-1389600277-r1" x="183" y="752" textLength="24.4" clip-path="url(#terminal-1389600277-line-30)">ch</text><text class="terminal-1389600277-r2" x="207.4" y="752" textLength="12.2" clip-path="url(#terminal-1389600277-line-30)">)</text><text class="terminal-1389600277-r1" x="219.6" y="752" textLength="305" clip-path="url(#terminal-1389600277-line-30)">      generate changelog </text><text class="terminal-1389600277-r2" x="524.6" y="752" textLength="12.2" clip-path="url(#terminal-1389600277-line-30)">(</text><text class="terminal-1389600277-r1" x="536.8" y="752" textLength="329.4" clip-path="url(#terminal-1389600277-line-30)">note that it will overwrite</text><text class="terminal-1389600277-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1389600277-line-30)"> -</text><text class="terminal-1389600277-r1" x="0" y="776.4" textLength="451.4" clip-path="url(#terminal-1389600277-line-31)">                        existing file</text><text class="terminal-1389600277-r2" x="451.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-31)">)</text><text class="terminal-1389600277-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-31)"> -</text><text class="terminal-1389600277-r1" x="0" y="800.8" textLength="951.6" clip-path="url(#terminal-1389600277-line-32)">    check               validates that a commit message matches the commitizen</text><text class="terminal-1389600277-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-1389600277-line-32)"> -</text><text class="terminal-1389600277-r1" x="0" y="825.2" textLength="366" clip-path="url(#terminal-1389600277-line-33)">                        schema</text><text class="terminal-1389600277-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-1389600277-line-33)"> -</text><text class="terminal-1389600277-r1" x="0" y="849.6" textLength="902.8" clip-path="url(#terminal-1389600277-line-34)">    version             get the version of the installed commitizen or the</text><text class="terminal-1389600277-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-1389600277-line-34)"> -</text><text class="terminal-1389600277-r1" x="0" y="874" textLength="488" clip-path="url(#terminal-1389600277-line-35)">                        current project </text><text class="terminal-1389600277-r2" x="488" y="874" textLength="12.2" clip-path="url(#terminal-1389600277-line-35)">(</text><text class="terminal-1389600277-r1" x="500.2" y="874" textLength="353.8" clip-path="url(#terminal-1389600277-line-35)">default: installed commitizen</text><text class="terminal-1389600277-r2" x="854" y="874" textLength="12.2" clip-path="url(#terminal-1389600277-line-35)">)</text><text class="terminal-1389600277-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-1389600277-line-35)"> -</text><text class="terminal-1389600277-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-1389600277-line-36)"> + <g class="terminal-1688774822-matrix"> + <text class="terminal-1688774822-r1" x="0" y="20" textLength="134.2" clip-path="url(#terminal-1688774822-line-0)">$ cz --help</text><text class="terminal-1688774822-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1688774822-line-0)"> +</text><text class="terminal-1688774822-r1" x="0" y="44.4" textLength="122" clip-path="url(#terminal-1688774822-line-1)">usage: cz </text><text class="terminal-1688774822-r2" x="122" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="134.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1688774822-line-1)">-h</text><text class="terminal-1688774822-r2" x="158.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="195.2" y="44.4" textLength="183" clip-path="url(#terminal-1688774822-line-1)">--config CONFIG</text><text class="terminal-1688774822-r2" x="378.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="402.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="414.8" y="44.4" textLength="85.4" clip-path="url(#terminal-1688774822-line-1)">--debug</text><text class="terminal-1688774822-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="536.8" y="44.4" textLength="85.4" clip-path="url(#terminal-1688774822-line-1)">-n NAME</text><text class="terminal-1688774822-r2" x="622.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="646.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="658.8" y="44.4" textLength="146.4" clip-path="url(#terminal-1688774822-line-1)">-nr NO_RAISE</text><text class="terminal-1688774822-r2" x="805.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)"> +</text><text class="terminal-1688774822-r2" x="122" y="68.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-2)">{</text><text class="terminal-1688774822-r1" x="134.2" y="68.8" textLength="829.6" clip-path="url(#terminal-1688774822-line-2)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-1688774822-r2" x="963.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-2)">}</text><text class="terminal-1688774822-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-2)"> +</text><text class="terminal-1688774822-r3" x="122" y="93.2" textLength="36.6" clip-path="url(#terminal-1688774822-line-3)">...</text><text class="terminal-1688774822-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-3)"> +</text><text class="terminal-1688774822-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-4)"> +</text><text class="terminal-1688774822-r1" x="0" y="142" textLength="915" clip-path="url(#terminal-1688774822-line-5)">Commitizen is a powerful release management tool that helps teams maintain </text><text class="terminal-1688774822-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1688774822-line-5)"> +</text><text class="terminal-1688774822-r1" x="0" y="166.4" textLength="951.6" clip-path="url(#terminal-1688774822-line-6)">consistent and meaningful commit messages while automating version management.</text><text class="terminal-1688774822-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-6)"> +</text><text class="terminal-1688774822-r1" x="0" y="190.8" textLength="427" clip-path="url(#terminal-1688774822-line-7)">For more information, please visit </text><text class="terminal-1688774822-r4" x="427" y="190.8" textLength="549" clip-path="url(#terminal-1688774822-line-7)">https://commitizen-tools.github.io/commitizen</text><text class="terminal-1688774822-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-7)"> +</text><text class="terminal-1688774822-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-8)"> +</text><text class="terminal-1688774822-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-1688774822-line-9)">options:</text><text class="terminal-1688774822-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-9)"> +</text><text class="terminal-1688774822-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-1688774822-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-1688774822-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1688774822-line-10)"> +</text><text class="terminal-1688774822-r1" x="0" y="288.4" textLength="658.8" clip-path="url(#terminal-1688774822-line-11)">  --config CONFIG       the path of configuration file</text><text class="terminal-1688774822-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-11)"> +</text><text class="terminal-1688774822-r1" x="0" y="312.8" textLength="463.6" clip-path="url(#terminal-1688774822-line-12)">  --debug               use debug mode</text><text class="terminal-1688774822-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-12)"> +</text><text class="terminal-1688774822-r1" x="0" y="337.2" textLength="597.8" clip-path="url(#terminal-1688774822-line-13)">  -n NAME, --name NAME  use the given commitizen </text><text class="terminal-1688774822-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-13)">(</text><text class="terminal-1688774822-r1" x="610" y="337.2" textLength="97.6" clip-path="url(#terminal-1688774822-line-13)">default:</text><text class="terminal-1688774822-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-13)"> +</text><text class="terminal-1688774822-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-1688774822-line-14)">                        cz_conventional_commits</text><text class="terminal-1688774822-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-14)">)</text><text class="terminal-1688774822-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-14)"> +</text><text class="terminal-1688774822-r1" x="0" y="386" textLength="427" clip-path="url(#terminal-1688774822-line-15)">  -nr NO_RAISE, --no-raise NO_RAISE</text><text class="terminal-1688774822-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1688774822-line-15)"> +</text><text class="terminal-1688774822-r1" x="0" y="410.4" textLength="915" clip-path="url(#terminal-1688774822-line-16)">                        comma separated error codes that won't raise error,</text><text class="terminal-1688774822-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-16)"> +</text><text class="terminal-1688774822-r1" x="0" y="434.8" textLength="439.2" clip-path="url(#terminal-1688774822-line-17)">                        e.g: cz -nr </text><text class="terminal-1688774822-r5" x="439.2" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">1</text><text class="terminal-1688774822-r1" x="451.4" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">,</text><text class="terminal-1688774822-r5" x="463.6" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">2</text><text class="terminal-1688774822-r1" x="475.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">,</text><text class="terminal-1688774822-r5" x="488" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">3</text><text class="terminal-1688774822-r1" x="500.2" y="434.8" textLength="231.8" clip-path="url(#terminal-1688774822-line-17)"> bump. See codes at</text><text class="terminal-1688774822-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)"> +</text><text class="terminal-1688774822-r4" x="292.8" y="459.2" textLength="231.8" clip-path="url(#terminal-1688774822-line-18)">https://commitizen-</text><text class="terminal-1688774822-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-18)"> +</text><text class="terminal-1688774822-r1" x="0" y="483.6" textLength="756.4" clip-path="url(#terminal-1688774822-line-19)">                        tools.github.io/commitizen/exit_codes/</text><text class="terminal-1688774822-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-19)"> +</text><text class="terminal-1688774822-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1688774822-line-20)"> +</text><text class="terminal-1688774822-r1" x="0" y="532.4" textLength="109.8" clip-path="url(#terminal-1688774822-line-21)">commands:</text><text class="terminal-1688774822-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-21)"> +</text><text class="terminal-1688774822-r2" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-22)">{</text><text class="terminal-1688774822-r1" x="36.6" y="556.8" textLength="829.6" clip-path="url(#terminal-1688774822-line-22)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-1688774822-r2" x="866.2" y="556.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-22)">}</text><text class="terminal-1688774822-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-22)"> +</text><text class="terminal-1688774822-r1" x="0" y="581.2" textLength="646.6" clip-path="url(#terminal-1688774822-line-23)">    init                init commitizen configuration</text><text class="terminal-1688774822-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-23)"> +</text><text class="terminal-1688774822-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-1688774822-line-24)">    commit </text><text class="terminal-1688774822-r2" x="134.2" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)">(</text><text class="terminal-1688774822-r1" x="146.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)">c</text><text class="terminal-1688774822-r2" x="158.6" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)">)</text><text class="terminal-1688774822-r1" x="170.8" y="605.6" textLength="329.4" clip-path="url(#terminal-1688774822-line-24)">          create new commit</text><text class="terminal-1688774822-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)"> +</text><text class="terminal-1688774822-r1" x="0" y="630" textLength="610" clip-path="url(#terminal-1688774822-line-25)">    ls                  show available commitizens</text><text class="terminal-1688774822-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1688774822-line-25)"> +</text><text class="terminal-1688774822-r1" x="0" y="654.4" textLength="524.6" clip-path="url(#terminal-1688774822-line-26)">    example             show commit example</text><text class="terminal-1688774822-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-26)"> +</text><text class="terminal-1688774822-r1" x="0" y="678.8" textLength="646.6" clip-path="url(#terminal-1688774822-line-27)">    info                show information about the cz</text><text class="terminal-1688774822-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-27)"> +</text><text class="terminal-1688774822-r1" x="0" y="703.2" textLength="512.4" clip-path="url(#terminal-1688774822-line-28)">    schema              show commit schema</text><text class="terminal-1688774822-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-28)"> +</text><text class="terminal-1688774822-r1" x="0" y="727.6" textLength="805.2" clip-path="url(#terminal-1688774822-line-29)">    bump                bump semantic version based on the git log</text><text class="terminal-1688774822-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-29)"> +</text><text class="terminal-1688774822-r1" x="0" y="752" textLength="170.8" clip-path="url(#terminal-1688774822-line-30)">    changelog </text><text class="terminal-1688774822-r2" x="170.8" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)">(</text><text class="terminal-1688774822-r1" x="183" y="752" textLength="24.4" clip-path="url(#terminal-1688774822-line-30)">ch</text><text class="terminal-1688774822-r2" x="207.4" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)">)</text><text class="terminal-1688774822-r1" x="219.6" y="752" textLength="305" clip-path="url(#terminal-1688774822-line-30)">      generate changelog </text><text class="terminal-1688774822-r2" x="524.6" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)">(</text><text class="terminal-1688774822-r1" x="536.8" y="752" textLength="329.4" clip-path="url(#terminal-1688774822-line-30)">note that it will overwrite</text><text class="terminal-1688774822-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)"> +</text><text class="terminal-1688774822-r1" x="0" y="776.4" textLength="451.4" clip-path="url(#terminal-1688774822-line-31)">                        existing file</text><text class="terminal-1688774822-r2" x="451.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-31)">)</text><text class="terminal-1688774822-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-31)"> +</text><text class="terminal-1688774822-r1" x="0" y="800.8" textLength="951.6" clip-path="url(#terminal-1688774822-line-32)">    check               validates that a commit message matches the commitizen</text><text class="terminal-1688774822-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-32)"> +</text><text class="terminal-1688774822-r1" x="0" y="825.2" textLength="366" clip-path="url(#terminal-1688774822-line-33)">                        schema</text><text class="terminal-1688774822-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-33)"> +</text><text class="terminal-1688774822-r1" x="0" y="849.6" textLength="902.8" clip-path="url(#terminal-1688774822-line-34)">    version             get the version of the installed commitizen or the</text><text class="terminal-1688774822-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-34)"> +</text><text class="terminal-1688774822-r1" x="0" y="874" textLength="488" clip-path="url(#terminal-1688774822-line-35)">                        current project </text><text class="terminal-1688774822-r2" x="488" y="874" textLength="12.2" clip-path="url(#terminal-1688774822-line-35)">(</text><text class="terminal-1688774822-r1" x="500.2" y="874" textLength="353.8" clip-path="url(#terminal-1688774822-line-35)">default: installed commitizen</text><text class="terminal-1688774822-r2" x="854" y="874" textLength="12.2" clip-path="url(#terminal-1688774822-line-35)">)</text><text class="terminal-1688774822-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-1688774822-line-35)"> +</text><text class="terminal-1688774822-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-36)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_bump___help.svg b/docs/images/cli_help/cz_bump___help.svg index 7d007df312..dff62998d2 100644 --- a/docs/images/cli_help/cz_bump___help.svg +++ b/docs/images/cli_help/cz_bump___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 2075.2" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 2099.6" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,370 +19,374 @@ font-weight: 700; } - .terminal-1655558888-matrix { + .terminal-1363677843-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1655558888-title { + .terminal-1363677843-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1655558888-r1 { fill: #c5c8c6 } -.terminal-1655558888-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-1655558888-r3 { fill: #68a0b3;font-weight: bold } -.terminal-1655558888-r4 { fill: #98a84b } + .terminal-1363677843-r1 { fill: #c5c8c6 } +.terminal-1363677843-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-1363677843-r3 { fill: #68a0b3;font-weight: bold } +.terminal-1363677843-r4 { fill: #98a84b } </style> <defs> - <clipPath id="terminal-1655558888-clip-terminal"> - <rect x="0" y="0" width="975.0" height="2024.1999999999998" /> + <clipPath id="terminal-1363677843-clip-terminal"> + <rect x="0" y="0" width="975.0" height="2048.6" /> </clipPath> - <clipPath id="terminal-1655558888-line-0"> + <clipPath id="terminal-1363677843-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-1"> +<clipPath id="terminal-1363677843-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-2"> +<clipPath id="terminal-1363677843-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-3"> +<clipPath id="terminal-1363677843-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-4"> +<clipPath id="terminal-1363677843-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-5"> +<clipPath id="terminal-1363677843-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-6"> +<clipPath id="terminal-1363677843-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-7"> +<clipPath id="terminal-1363677843-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-8"> +<clipPath id="terminal-1363677843-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-9"> +<clipPath id="terminal-1363677843-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-10"> +<clipPath id="terminal-1363677843-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-11"> +<clipPath id="terminal-1363677843-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-12"> +<clipPath id="terminal-1363677843-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-13"> +<clipPath id="terminal-1363677843-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-14"> +<clipPath id="terminal-1363677843-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-15"> +<clipPath id="terminal-1363677843-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-16"> +<clipPath id="terminal-1363677843-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-17"> +<clipPath id="terminal-1363677843-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-18"> +<clipPath id="terminal-1363677843-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-19"> +<clipPath id="terminal-1363677843-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-20"> +<clipPath id="terminal-1363677843-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-21"> +<clipPath id="terminal-1363677843-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-22"> +<clipPath id="terminal-1363677843-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-23"> +<clipPath id="terminal-1363677843-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-24"> +<clipPath id="terminal-1363677843-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-25"> +<clipPath id="terminal-1363677843-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-26"> +<clipPath id="terminal-1363677843-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-27"> +<clipPath id="terminal-1363677843-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-28"> +<clipPath id="terminal-1363677843-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-29"> +<clipPath id="terminal-1363677843-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-30"> +<clipPath id="terminal-1363677843-line-30"> <rect x="0" y="733.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-31"> +<clipPath id="terminal-1363677843-line-31"> <rect x="0" y="757.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-32"> +<clipPath id="terminal-1363677843-line-32"> <rect x="0" y="782.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-33"> +<clipPath id="terminal-1363677843-line-33"> <rect x="0" y="806.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-34"> +<clipPath id="terminal-1363677843-line-34"> <rect x="0" y="831.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-35"> +<clipPath id="terminal-1363677843-line-35"> <rect x="0" y="855.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-36"> +<clipPath id="terminal-1363677843-line-36"> <rect x="0" y="879.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-37"> +<clipPath id="terminal-1363677843-line-37"> <rect x="0" y="904.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-38"> +<clipPath id="terminal-1363677843-line-38"> <rect x="0" y="928.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-39"> +<clipPath id="terminal-1363677843-line-39"> <rect x="0" y="953.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-40"> +<clipPath id="terminal-1363677843-line-40"> <rect x="0" y="977.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-41"> +<clipPath id="terminal-1363677843-line-41"> <rect x="0" y="1001.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-42"> +<clipPath id="terminal-1363677843-line-42"> <rect x="0" y="1026.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-43"> +<clipPath id="terminal-1363677843-line-43"> <rect x="0" y="1050.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-44"> +<clipPath id="terminal-1363677843-line-44"> <rect x="0" y="1075.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-45"> +<clipPath id="terminal-1363677843-line-45"> <rect x="0" y="1099.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-46"> +<clipPath id="terminal-1363677843-line-46"> <rect x="0" y="1123.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-47"> +<clipPath id="terminal-1363677843-line-47"> <rect x="0" y="1148.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-48"> +<clipPath id="terminal-1363677843-line-48"> <rect x="0" y="1172.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-49"> +<clipPath id="terminal-1363677843-line-49"> <rect x="0" y="1197.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-50"> +<clipPath id="terminal-1363677843-line-50"> <rect x="0" y="1221.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-51"> +<clipPath id="terminal-1363677843-line-51"> <rect x="0" y="1245.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-52"> +<clipPath id="terminal-1363677843-line-52"> <rect x="0" y="1270.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-53"> +<clipPath id="terminal-1363677843-line-53"> <rect x="0" y="1294.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-54"> +<clipPath id="terminal-1363677843-line-54"> <rect x="0" y="1319.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-55"> +<clipPath id="terminal-1363677843-line-55"> <rect x="0" y="1343.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-56"> +<clipPath id="terminal-1363677843-line-56"> <rect x="0" y="1367.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-57"> +<clipPath id="terminal-1363677843-line-57"> <rect x="0" y="1392.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-58"> +<clipPath id="terminal-1363677843-line-58"> <rect x="0" y="1416.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-59"> +<clipPath id="terminal-1363677843-line-59"> <rect x="0" y="1441.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-60"> +<clipPath id="terminal-1363677843-line-60"> <rect x="0" y="1465.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-61"> +<clipPath id="terminal-1363677843-line-61"> <rect x="0" y="1489.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-62"> +<clipPath id="terminal-1363677843-line-62"> <rect x="0" y="1514.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-63"> +<clipPath id="terminal-1363677843-line-63"> <rect x="0" y="1538.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-64"> +<clipPath id="terminal-1363677843-line-64"> <rect x="0" y="1563.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-65"> +<clipPath id="terminal-1363677843-line-65"> <rect x="0" y="1587.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-66"> +<clipPath id="terminal-1363677843-line-66"> <rect x="0" y="1611.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-67"> +<clipPath id="terminal-1363677843-line-67"> <rect x="0" y="1636.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-68"> +<clipPath id="terminal-1363677843-line-68"> <rect x="0" y="1660.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-69"> +<clipPath id="terminal-1363677843-line-69"> <rect x="0" y="1685.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-70"> +<clipPath id="terminal-1363677843-line-70"> <rect x="0" y="1709.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-71"> +<clipPath id="terminal-1363677843-line-71"> <rect x="0" y="1733.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-72"> +<clipPath id="terminal-1363677843-line-72"> <rect x="0" y="1758.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-73"> +<clipPath id="terminal-1363677843-line-73"> <rect x="0" y="1782.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-74"> +<clipPath id="terminal-1363677843-line-74"> <rect x="0" y="1807.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-75"> +<clipPath id="terminal-1363677843-line-75"> <rect x="0" y="1831.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-76"> +<clipPath id="terminal-1363677843-line-76"> <rect x="0" y="1855.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-77"> +<clipPath id="terminal-1363677843-line-77"> <rect x="0" y="1880.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-78"> +<clipPath id="terminal-1363677843-line-78"> <rect x="0" y="1904.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-79"> +<clipPath id="terminal-1363677843-line-79"> <rect x="0" y="1929.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-80"> +<clipPath id="terminal-1363677843-line-80"> <rect x="0" y="1953.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1655558888-line-81"> +<clipPath id="terminal-1363677843-line-81"> <rect x="0" y="1977.9" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-1363677843-line-82"> + <rect x="0" y="2002.3" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="2073.2" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="2097.6" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1655558888-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-1363677843-clip-terminal)"> - <g class="terminal-1655558888-matrix"> - <text class="terminal-1655558888-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-1655558888-line-0)">$ cz bump --help</text><text class="terminal-1655558888-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1655558888-line-0)"> -</text><text class="terminal-1655558888-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-1655558888-line-1)">usage: cz bump </text><text class="terminal-1655558888-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">[</text><text class="terminal-1655558888-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1655558888-line-1)">-h</text><text class="terminal-1655558888-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">]</text><text class="terminal-1655558888-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">[</text><text class="terminal-1655558888-r1" x="256.2" y="44.4" textLength="109.8" clip-path="url(#terminal-1655558888-line-1)">--dry-run</text><text class="terminal-1655558888-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">]</text><text class="terminal-1655558888-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">[</text><text class="terminal-1655558888-r1" x="402.6" y="44.4" textLength="146.4" clip-path="url(#terminal-1655558888-line-1)">--files-only</text><text class="terminal-1655558888-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">]</text><text class="terminal-1655558888-r2" x="573.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">[</text><text class="terminal-1655558888-r1" x="585.6" y="44.4" textLength="183" clip-path="url(#terminal-1655558888-line-1)">--local-version</text><text class="terminal-1655558888-r2" x="768.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">]</text><text class="terminal-1655558888-r2" x="793" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">[</text><text class="terminal-1655558888-r1" x="805.2" y="44.4" textLength="134.2" clip-path="url(#terminal-1655558888-line-1)">--changelog</text><text class="terminal-1655558888-r2" x="939.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)">]</text><text class="terminal-1655558888-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-1)"> -</text><text class="terminal-1655558888-r2" x="183" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)">[</text><text class="terminal-1655558888-r1" x="195.2" y="68.8" textLength="134.2" clip-path="url(#terminal-1655558888-line-2)">--no-verify</text><text class="terminal-1655558888-r2" x="329.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)">]</text><text class="terminal-1655558888-r2" x="353.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)">[</text><text class="terminal-1655558888-r1" x="366" y="68.8" textLength="61" clip-path="url(#terminal-1655558888-line-2)">--yes</text><text class="terminal-1655558888-r2" x="427" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)">]</text><text class="terminal-1655558888-r2" x="451.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)">[</text><text class="terminal-1655558888-r1" x="463.6" y="68.8" textLength="280.6" clip-path="url(#terminal-1655558888-line-2)">--tag-format TAG_FORMAT</text><text class="terminal-1655558888-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)">]</text><text class="terminal-1655558888-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-2)"> -</text><text class="terminal-1655558888-r2" x="183" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)">[</text><text class="terminal-1655558888-r1" x="195.2" y="93.2" textLength="329.4" clip-path="url(#terminal-1655558888-line-3)">--bump-message BUMP_MESSAGE</text><text class="terminal-1655558888-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)">]</text><text class="terminal-1655558888-r2" x="549" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)">[</text><text class="terminal-1655558888-r1" x="561.2" y="93.2" textLength="158.6" clip-path="url(#terminal-1655558888-line-3)">--prerelease </text><text class="terminal-1655558888-r2" x="719.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)">{</text><text class="terminal-1655558888-r1" x="732" y="93.2" textLength="158.6" clip-path="url(#terminal-1655558888-line-3)">alpha,beta,rc</text><text class="terminal-1655558888-r2" x="890.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)">}</text><text class="terminal-1655558888-r2" x="902.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)">]</text><text class="terminal-1655558888-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-3)"> -</text><text class="terminal-1655558888-r2" x="183" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)">[</text><text class="terminal-1655558888-r1" x="195.2" y="117.6" textLength="280.6" clip-path="url(#terminal-1655558888-line-4)">--devrelease DEVRELEASE</text><text class="terminal-1655558888-r2" x="475.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)">]</text><text class="terminal-1655558888-r2" x="500.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)">[</text><text class="terminal-1655558888-r1" x="512.4" y="117.6" textLength="146.4" clip-path="url(#terminal-1655558888-line-4)">--increment </text><text class="terminal-1655558888-r2" x="658.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)">{</text><text class="terminal-1655558888-r1" x="671" y="117.6" textLength="207.4" clip-path="url(#terminal-1655558888-line-4)">MAJOR,MINOR,PATCH</text><text class="terminal-1655558888-r2" x="878.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)">}</text><text class="terminal-1655558888-r2" x="890.6" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)">]</text><text class="terminal-1655558888-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-4)"> -</text><text class="terminal-1655558888-r2" x="183" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)">[</text><text class="terminal-1655558888-r1" x="195.2" y="142" textLength="207.4" clip-path="url(#terminal-1655558888-line-5)">--increment-mode </text><text class="terminal-1655558888-r2" x="402.6" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)">{</text><text class="terminal-1655558888-r1" x="414.8" y="142" textLength="146.4" clip-path="url(#terminal-1655558888-line-5)">linear,exact</text><text class="terminal-1655558888-r2" x="561.2" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)">}</text><text class="terminal-1655558888-r2" x="573.4" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)">]</text><text class="terminal-1655558888-r2" x="597.8" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)">[</text><text class="terminal-1655558888-r1" x="610" y="142" textLength="231.8" clip-path="url(#terminal-1655558888-line-5)">--check-consistency</text><text class="terminal-1655558888-r2" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)">]</text><text class="terminal-1655558888-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1655558888-line-5)"> -</text><text class="terminal-1655558888-r2" x="183" y="166.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-6)">[</text><text class="terminal-1655558888-r1" x="195.2" y="166.4" textLength="183" clip-path="url(#terminal-1655558888-line-6)">--annotated-tag</text><text class="terminal-1655558888-r2" x="378.2" y="166.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-6)">]</text><text class="terminal-1655558888-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-6)"> -</text><text class="terminal-1655558888-r2" x="183" y="190.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-7)">[</text><text class="terminal-1655558888-r1" x="195.2" y="190.8" textLength="549" clip-path="url(#terminal-1655558888-line-7)">--annotated-tag-message ANNOTATED_TAG_MESSAGE</text><text class="terminal-1655558888-r2" x="744.2" y="190.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-7)">]</text><text class="terminal-1655558888-r2" x="768.6" y="190.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-7)">[</text><text class="terminal-1655558888-r1" x="780.8" y="190.8" textLength="122" clip-path="url(#terminal-1655558888-line-7)">--gpg-sign</text><text class="terminal-1655558888-r2" x="902.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-7)">]</text><text class="terminal-1655558888-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-7)"> -</text><text class="terminal-1655558888-r2" x="183" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)">[</text><text class="terminal-1655558888-r1" x="195.2" y="215.2" textLength="256.2" clip-path="url(#terminal-1655558888-line-8)">--changelog-to-stdout</text><text class="terminal-1655558888-r2" x="451.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)">]</text><text class="terminal-1655558888-r2" x="475.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)">[</text><text class="terminal-1655558888-r1" x="488" y="215.2" textLength="268.4" clip-path="url(#terminal-1655558888-line-8)">--git-output-to-stderr</text><text class="terminal-1655558888-r2" x="756.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)">]</text><text class="terminal-1655558888-r2" x="780.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)">[</text><text class="terminal-1655558888-r1" x="793" y="215.2" textLength="85.4" clip-path="url(#terminal-1655558888-line-8)">--retry</text><text class="terminal-1655558888-r2" x="878.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)">]</text><text class="terminal-1655558888-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-8)"> -</text><text class="terminal-1655558888-r2" x="183" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)">[</text><text class="terminal-1655558888-r1" x="195.2" y="239.6" textLength="244" clip-path="url(#terminal-1655558888-line-9)">--major-version-zero</text><text class="terminal-1655558888-r2" x="439.2" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)">]</text><text class="terminal-1655558888-r2" x="463.6" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)">[</text><text class="terminal-1655558888-r1" x="475.8" y="239.6" textLength="231.8" clip-path="url(#terminal-1655558888-line-9)">--template TEMPLATE</text><text class="terminal-1655558888-r2" x="707.6" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)">]</text><text class="terminal-1655558888-r2" x="732" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)">[</text><text class="terminal-1655558888-r1" x="744.2" y="239.6" textLength="158.6" clip-path="url(#terminal-1655558888-line-9)">--extra EXTRA</text><text class="terminal-1655558888-r2" x="902.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)">]</text><text class="terminal-1655558888-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-9)"> -</text><text class="terminal-1655558888-r2" x="183" y="264" textLength="12.2" clip-path="url(#terminal-1655558888-line-10)">[</text><text class="terminal-1655558888-r1" x="195.2" y="264" textLength="256.2" clip-path="url(#terminal-1655558888-line-10)">--file-name FILE_NAME</text><text class="terminal-1655558888-r2" x="451.4" y="264" textLength="12.2" clip-path="url(#terminal-1655558888-line-10)">]</text><text class="terminal-1655558888-r2" x="475.8" y="264" textLength="12.2" clip-path="url(#terminal-1655558888-line-10)">[</text><text class="terminal-1655558888-r1" x="488" y="264" textLength="451.4" clip-path="url(#terminal-1655558888-line-10)">--prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-1655558888-r2" x="939.4" y="264" textLength="12.2" clip-path="url(#terminal-1655558888-line-10)">]</text><text class="terminal-1655558888-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1655558888-line-10)"> -</text><text class="terminal-1655558888-r2" x="183" y="288.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-11)">[</text><text class="terminal-1655558888-r1" x="195.2" y="288.4" textLength="207.4" clip-path="url(#terminal-1655558888-line-11)">--version-scheme </text><text class="terminal-1655558888-r2" x="402.6" y="288.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-11)">{</text><text class="terminal-1655558888-r1" x="414.8" y="288.4" textLength="256.2" clip-path="url(#terminal-1655558888-line-11)">pep440,semver,semver2</text><text class="terminal-1655558888-r2" x="671" y="288.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-11)">}</text><text class="terminal-1655558888-r2" x="683.2" y="288.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-11)">]</text><text class="terminal-1655558888-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-11)"> -</text><text class="terminal-1655558888-r2" x="183" y="312.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-12)">[</text><text class="terminal-1655558888-r1" x="195.2" y="312.8" textLength="183" clip-path="url(#terminal-1655558888-line-12)">--version-type </text><text class="terminal-1655558888-r2" x="378.2" y="312.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-12)">{</text><text class="terminal-1655558888-r1" x="390.4" y="312.8" textLength="256.2" clip-path="url(#terminal-1655558888-line-12)">pep440,semver,semver2</text><text class="terminal-1655558888-r2" x="646.6" y="312.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-12)">}</text><text class="terminal-1655558888-r2" x="658.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-12)">]</text><text class="terminal-1655558888-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-12)"> -</text><text class="terminal-1655558888-r2" x="183" y="337.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-13)">[</text><text class="terminal-1655558888-r1" x="195.2" y="337.2" textLength="378.2" clip-path="url(#terminal-1655558888-line-13)">--build-metadata BUILD_METADATA</text><text class="terminal-1655558888-r2" x="573.4" y="337.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-13)">]</text><text class="terminal-1655558888-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-13)">[</text><text class="terminal-1655558888-r1" x="610" y="337.2" textLength="122" clip-path="url(#terminal-1655558888-line-13)">--get-next</text><text class="terminal-1655558888-r2" x="732" y="337.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-13)">]</text><text class="terminal-1655558888-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-13)"> -</text><text class="terminal-1655558888-r2" x="183" y="361.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-14)">[</text><text class="terminal-1655558888-r1" x="195.2" y="361.6" textLength="207.4" clip-path="url(#terminal-1655558888-line-14)">--allow-no-commit</text><text class="terminal-1655558888-r2" x="402.6" y="361.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-14)">]</text><text class="terminal-1655558888-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-14)"> -</text><text class="terminal-1655558888-r2" x="183" y="386" textLength="12.2" clip-path="url(#terminal-1655558888-line-15)">[</text><text class="terminal-1655558888-r1" x="195.2" y="386" textLength="170.8" clip-path="url(#terminal-1655558888-line-15)">MANUAL_VERSION</text><text class="terminal-1655558888-r2" x="366" y="386" textLength="12.2" clip-path="url(#terminal-1655558888-line-15)">]</text><text class="terminal-1655558888-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1655558888-line-15)"> -</text><text class="terminal-1655558888-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-16)"> -</text><text class="terminal-1655558888-r1" x="0" y="434.8" textLength="512.4" clip-path="url(#terminal-1655558888-line-17)">bump semantic version based on the git log</text><text class="terminal-1655558888-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-17)"> -</text><text class="terminal-1655558888-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-18)"> -</text><text class="terminal-1655558888-r1" x="0" y="483.6" textLength="256.2" clip-path="url(#terminal-1655558888-line-19)">positional arguments:</text><text class="terminal-1655558888-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-19)"> -</text><text class="terminal-1655558888-r1" x="0" y="508" textLength="610" clip-path="url(#terminal-1655558888-line-20)">  MANUAL_VERSION        bump to the given version </text><text class="terminal-1655558888-r2" x="610" y="508" textLength="12.2" clip-path="url(#terminal-1655558888-line-20)">(</text><text class="terminal-1655558888-r1" x="622.2" y="508" textLength="61" clip-path="url(#terminal-1655558888-line-20)">e.g: </text><text class="terminal-1655558888-r3" x="683.2" y="508" textLength="36.6" clip-path="url(#terminal-1655558888-line-20)">1.5</text><text class="terminal-1655558888-r1" x="719.8" y="508" textLength="12.2" clip-path="url(#terminal-1655558888-line-20)">.</text><text class="terminal-1655558888-r3" x="732" y="508" textLength="12.2" clip-path="url(#terminal-1655558888-line-20)">3</text><text class="terminal-1655558888-r2" x="744.2" y="508" textLength="12.2" clip-path="url(#terminal-1655558888-line-20)">)</text><text class="terminal-1655558888-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1655558888-line-20)"> -</text><text class="terminal-1655558888-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-21)"> -</text><text class="terminal-1655558888-r1" x="0" y="556.8" textLength="97.6" clip-path="url(#terminal-1655558888-line-22)">options:</text><text class="terminal-1655558888-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-22)"> -</text><text class="terminal-1655558888-r1" x="0" y="581.2" textLength="671" clip-path="url(#terminal-1655558888-line-23)">  -h, --help            show this help message and exit</text><text class="terminal-1655558888-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-23)"> -</text><text class="terminal-1655558888-r1" x="0" y="605.6" textLength="915" clip-path="url(#terminal-1655558888-line-24)">  --dry-run             show output to stdout, no commit, no modified files</text><text class="terminal-1655558888-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-24)"> -</text><text class="terminal-1655558888-r1" x="0" y="630" textLength="793" clip-path="url(#terminal-1655558888-line-25)">  --files-only          bump version in the files from the config</text><text class="terminal-1655558888-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1655558888-line-25)"> -</text><text class="terminal-1655558888-r1" x="0" y="654.4" textLength="719.8" clip-path="url(#terminal-1655558888-line-26)">  --local-version       bump only the local version portion</text><text class="terminal-1655558888-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-26)"> -</text><text class="terminal-1655558888-r1" x="0" y="678.8" textLength="841.8" clip-path="url(#terminal-1655558888-line-27)">  --changelog, -ch      generate the changelog for the newest version</text><text class="terminal-1655558888-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-27)"> -</text><text class="terminal-1655558888-r1" x="0" y="703.2" textLength="902.8" clip-path="url(#terminal-1655558888-line-28)">  --no-verify           this option bypasses the pre-commit and commit-msg</text><text class="terminal-1655558888-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-28)"> -</text><text class="terminal-1655558888-r1" x="0" y="727.6" textLength="353.8" clip-path="url(#terminal-1655558888-line-29)">                        hooks</text><text class="terminal-1655558888-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-29)"> -</text><text class="terminal-1655558888-r1" x="0" y="752" textLength="719.8" clip-path="url(#terminal-1655558888-line-30)">  --yes                 accept automatically questions done</text><text class="terminal-1655558888-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1655558888-line-30)"> -</text><text class="terminal-1655558888-r1" x="0" y="776.4" textLength="305" clip-path="url(#terminal-1655558888-line-31)">  --tag-format TAG_FORMAT</text><text class="terminal-1655558888-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-31)"> -</text><text class="terminal-1655558888-r1" x="0" y="800.8" textLength="939.4" clip-path="url(#terminal-1655558888-line-32)">                        the format used to tag the commit and read it, use it</text><text class="terminal-1655558888-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-32)"> -</text><text class="terminal-1655558888-r1" x="0" y="825.2" textLength="866.2" clip-path="url(#terminal-1655558888-line-33)">                        in existing projects, wrap around simple quotes</text><text class="terminal-1655558888-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-33)"> -</text><text class="terminal-1655558888-r1" x="0" y="849.6" textLength="353.8" clip-path="url(#terminal-1655558888-line-34)">  --bump-message BUMP_MESSAGE</text><text class="terminal-1655558888-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-34)"> -</text><text class="terminal-1655558888-r1" x="0" y="874" textLength="902.8" clip-path="url(#terminal-1655558888-line-35)">                        template used to create the release commit, useful</text><text class="terminal-1655558888-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-1655558888-line-35)"> -</text><text class="terminal-1655558888-r1" x="0" y="898.4" textLength="536.8" clip-path="url(#terminal-1655558888-line-36)">                        when working with CI</text><text class="terminal-1655558888-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-36)"> -</text><text class="terminal-1655558888-r1" x="0" y="922.8" textLength="244" clip-path="url(#terminal-1655558888-line-37)">  --prerelease, -pr </text><text class="terminal-1655558888-r2" x="244" y="922.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-37)">{</text><text class="terminal-1655558888-r1" x="256.2" y="922.8" textLength="158.6" clip-path="url(#terminal-1655558888-line-37)">alpha,beta,rc</text><text class="terminal-1655558888-r2" x="414.8" y="922.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-37)">}</text><text class="terminal-1655558888-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-37)"> -</text><text class="terminal-1655558888-r1" x="0" y="947.2" textLength="597.8" clip-path="url(#terminal-1655558888-line-38)">                        choose type of prerelease</text><text class="terminal-1655558888-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-38)"> -</text><text class="terminal-1655558888-r1" x="0" y="971.6" textLength="353.8" clip-path="url(#terminal-1655558888-line-39)">  --devrelease, -d DEVRELEASE</text><text class="terminal-1655558888-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-39)"> -</text><text class="terminal-1655558888-r1" x="0" y="996" textLength="841.8" clip-path="url(#terminal-1655558888-line-40)">                        specify non-negative integer for dev. release</text><text class="terminal-1655558888-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-1655558888-line-40)"> -</text><text class="terminal-1655558888-r1" x="0" y="1020.4" textLength="170.8" clip-path="url(#terminal-1655558888-line-41)">  --increment </text><text class="terminal-1655558888-r2" x="170.8" y="1020.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-41)">{</text><text class="terminal-1655558888-r1" x="183" y="1020.4" textLength="207.4" clip-path="url(#terminal-1655558888-line-41)">MAJOR,MINOR,PATCH</text><text class="terminal-1655558888-r2" x="390.4" y="1020.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-41)">}</text><text class="terminal-1655558888-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-41)"> -</text><text class="terminal-1655558888-r1" x="0" y="1044.8" textLength="756.4" clip-path="url(#terminal-1655558888-line-42)">                        manually specify the desired increment</text><text class="terminal-1655558888-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-42)"> -</text><text class="terminal-1655558888-r1" x="0" y="1069.2" textLength="231.8" clip-path="url(#terminal-1655558888-line-43)">  --increment-mode </text><text class="terminal-1655558888-r2" x="231.8" y="1069.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-43)">{</text><text class="terminal-1655558888-r1" x="244" y="1069.2" textLength="146.4" clip-path="url(#terminal-1655558888-line-43)">linear,exact</text><text class="terminal-1655558888-r2" x="390.4" y="1069.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-43)">}</text><text class="terminal-1655558888-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-43)"> -</text><text class="terminal-1655558888-r1" x="0" y="1093.6" textLength="902.8" clip-path="url(#terminal-1655558888-line-44)">                        set the method by which the new version is chosen.</text><text class="terminal-1655558888-r1" x="976" y="1093.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-44)"> -</text><text class="terminal-1655558888-r4" x="292.8" y="1118" textLength="97.6" clip-path="url(#terminal-1655558888-line-45)">'linear'</text><text class="terminal-1655558888-r2" x="402.6" y="1118" textLength="12.2" clip-path="url(#terminal-1655558888-line-45)">(</text><text class="terminal-1655558888-r1" x="414.8" y="1118" textLength="85.4" clip-path="url(#terminal-1655558888-line-45)">default</text><text class="terminal-1655558888-r2" x="500.2" y="1118" textLength="12.2" clip-path="url(#terminal-1655558888-line-45)">)</text><text class="terminal-1655558888-r1" x="512.4" y="1118" textLength="414.8" clip-path="url(#terminal-1655558888-line-45)"> guesses the next version based on</text><text class="terminal-1655558888-r1" x="976" y="1118" textLength="12.2" clip-path="url(#terminal-1655558888-line-45)"> -</text><text class="terminal-1655558888-r1" x="0" y="1142.4" textLength="939.4" clip-path="url(#terminal-1655558888-line-46)">                        typical linear version progression, such that bumping</text><text class="terminal-1655558888-r1" x="976" y="1142.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-46)"> -</text><text class="terminal-1655558888-r1" x="0" y="1166.8" textLength="866.2" clip-path="url(#terminal-1655558888-line-47)">                        of a pre-release with lower precedence than the</text><text class="terminal-1655558888-r1" x="976" y="1166.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-47)"> -</text><text class="terminal-1655558888-r1" x="0" y="1191.2" textLength="939.4" clip-path="url(#terminal-1655558888-line-48)">                        current pre-release phase maintains the current phase</text><text class="terminal-1655558888-r1" x="976" y="1191.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-48)"> -</text><text class="terminal-1655558888-r1" x="0" y="1215.6" textLength="561.2" clip-path="url(#terminal-1655558888-line-49)">                        of higher precedence. </text><text class="terminal-1655558888-r4" x="561.2" y="1215.6" textLength="85.4" clip-path="url(#terminal-1655558888-line-49)">'exact'</text><text class="terminal-1655558888-r1" x="646.6" y="1215.6" textLength="305" clip-path="url(#terminal-1655558888-line-49)"> applies the changes that</text><text class="terminal-1655558888-r1" x="976" y="1215.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-49)"> -</text><text class="terminal-1655558888-r1" x="0" y="1240" textLength="536.8" clip-path="url(#terminal-1655558888-line-50)">                        have been specified </text><text class="terminal-1655558888-r2" x="536.8" y="1240" textLength="12.2" clip-path="url(#terminal-1655558888-line-50)">(</text><text class="terminal-1655558888-r1" x="549" y="1240" textLength="353.8" clip-path="url(#terminal-1655558888-line-50)">or determined from the commit</text><text class="terminal-1655558888-r1" x="976" y="1240" textLength="12.2" clip-path="url(#terminal-1655558888-line-50)"> -</text><text class="terminal-1655558888-r1" x="0" y="1264.4" textLength="329.4" clip-path="url(#terminal-1655558888-line-51)">                        log</text><text class="terminal-1655558888-r2" x="329.4" y="1264.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-51)">)</text><text class="terminal-1655558888-r1" x="341.6" y="1264.4" textLength="585.6" clip-path="url(#terminal-1655558888-line-51)"> without interpretation, such that the increment</text><text class="terminal-1655558888-r1" x="976" y="1264.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-51)"> -</text><text class="terminal-1655558888-r1" x="0" y="1288.8" textLength="707.6" clip-path="url(#terminal-1655558888-line-52)">                        and pre-release are always honored</text><text class="terminal-1655558888-r1" x="976" y="1288.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-52)"> -</text><text class="terminal-1655558888-r1" x="0" y="1313.2" textLength="317.2" clip-path="url(#terminal-1655558888-line-53)">  --check-consistency, -cc</text><text class="terminal-1655558888-r1" x="976" y="1313.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-53)"> -</text><text class="terminal-1655558888-r1" x="0" y="1337.6" textLength="951.6" clip-path="url(#terminal-1655558888-line-54)">                        check consistency among versions defined in commitizen</text><text class="terminal-1655558888-r1" x="976" y="1337.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-54)"> -</text><text class="terminal-1655558888-r1" x="0" y="1362" textLength="671" clip-path="url(#terminal-1655558888-line-55)">                        configuration and version_files</text><text class="terminal-1655558888-r1" x="976" y="1362" textLength="12.2" clip-path="url(#terminal-1655558888-line-55)"> -</text><text class="terminal-1655558888-r1" x="0" y="1386.4" textLength="866.2" clip-path="url(#terminal-1655558888-line-56)">  --annotated-tag, -at  create annotated tag instead of lightweight one</text><text class="terminal-1655558888-r1" x="976" y="1386.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-56)"> -</text><text class="terminal-1655558888-r1" x="0" y="1410.8" textLength="646.6" clip-path="url(#terminal-1655558888-line-57)">  --annotated-tag-message, -atm ANNOTATED_TAG_MESSAGE</text><text class="terminal-1655558888-r1" x="976" y="1410.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-57)"> -</text><text class="terminal-1655558888-r1" x="0" y="1435.2" textLength="634.4" clip-path="url(#terminal-1655558888-line-58)">                        create annotated tag message</text><text class="terminal-1655558888-r1" x="976" y="1435.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-58)"> -</text><text class="terminal-1655558888-r1" x="0" y="1459.6" textLength="719.8" clip-path="url(#terminal-1655558888-line-59)">  --gpg-sign, -s        sign tag instead of lightweight one</text><text class="terminal-1655558888-r1" x="976" y="1459.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-59)"> -</text><text class="terminal-1655558888-r1" x="0" y="1484" textLength="280.6" clip-path="url(#terminal-1655558888-line-60)">  --changelog-to-stdout</text><text class="terminal-1655558888-r1" x="976" y="1484" textLength="12.2" clip-path="url(#terminal-1655558888-line-60)"> -</text><text class="terminal-1655558888-r1" x="0" y="1508.4" textLength="658.8" clip-path="url(#terminal-1655558888-line-61)">                        Output changelog to the stdout</text><text class="terminal-1655558888-r1" x="976" y="1508.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-61)"> -</text><text class="terminal-1655558888-r1" x="0" y="1532.8" textLength="292.8" clip-path="url(#terminal-1655558888-line-62)">  --git-output-to-stderr</text><text class="terminal-1655558888-r1" x="976" y="1532.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-62)"> -</text><text class="terminal-1655558888-r1" x="0" y="1557.2" textLength="646.6" clip-path="url(#terminal-1655558888-line-63)">                        Redirect git output to stderr</text><text class="terminal-1655558888-r1" x="976" y="1557.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-63)"> -</text><text class="terminal-1655558888-r1" x="0" y="1581.6" textLength="744.2" clip-path="url(#terminal-1655558888-line-64)">  --retry               retry commit if it fails the 1st time</text><text class="terminal-1655558888-r1" x="976" y="1581.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-64)"> -</text><text class="terminal-1655558888-r1" x="0" y="1606" textLength="939.4" clip-path="url(#terminal-1655558888-line-65)">  --major-version-zero  keep major version at zero, even for breaking changes</text><text class="terminal-1655558888-r1" x="976" y="1606" textLength="12.2" clip-path="url(#terminal-1655558888-line-65)"> -</text><text class="terminal-1655558888-r1" x="0" y="1630.4" textLength="305" clip-path="url(#terminal-1655558888-line-66)">  --template, -t TEMPLATE</text><text class="terminal-1655558888-r1" x="976" y="1630.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-66)"> -</text><text class="terminal-1655558888-r1" x="0" y="1654.8" textLength="646.6" clip-path="url(#terminal-1655558888-line-67)">                        changelog template file name </text><text class="terminal-1655558888-r2" x="646.6" y="1654.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-67)">(</text><text class="terminal-1655558888-r1" x="658.8" y="1654.8" textLength="280.6" clip-path="url(#terminal-1655558888-line-67)">relative to the current</text><text class="terminal-1655558888-r1" x="976" y="1654.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-67)"> -</text><text class="terminal-1655558888-r1" x="0" y="1679.2" textLength="500.2" clip-path="url(#terminal-1655558888-line-68)">                        working directory</text><text class="terminal-1655558888-r2" x="500.2" y="1679.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-68)">)</text><text class="terminal-1655558888-r1" x="976" y="1679.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-68)"> -</text><text class="terminal-1655558888-r1" x="0" y="1703.6" textLength="622.2" clip-path="url(#terminal-1655558888-line-69)">  --extra, -e EXTRA     a changelog extra variable </text><text class="terminal-1655558888-r2" x="622.2" y="1703.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-69)">(</text><text class="terminal-1655558888-r1" x="634.4" y="1703.6" textLength="146.4" clip-path="url(#terminal-1655558888-line-69)">in the form </text><text class="terminal-1655558888-r4" x="780.8" y="1703.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-69)">'</text><text class="terminal-1655558888-r4" x="793" y="1703.6" textLength="36.6" clip-path="url(#terminal-1655558888-line-69)">key</text><text class="terminal-1655558888-r4" x="829.6" y="1703.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-69)">=</text><text class="terminal-1655558888-r4" x="841.8" y="1703.6" textLength="61" clip-path="url(#terminal-1655558888-line-69)">value</text><text class="terminal-1655558888-r4" x="902.8" y="1703.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-69)">'</text><text class="terminal-1655558888-r2" x="915" y="1703.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-69)">)</text><text class="terminal-1655558888-r1" x="976" y="1703.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-69)"> -</text><text class="terminal-1655558888-r1" x="0" y="1728" textLength="280.6" clip-path="url(#terminal-1655558888-line-70)">  --file-name FILE_NAME</text><text class="terminal-1655558888-r1" x="976" y="1728" textLength="12.2" clip-path="url(#terminal-1655558888-line-70)"> -</text><text class="terminal-1655558888-r1" x="0" y="1752.4" textLength="573.4" clip-path="url(#terminal-1655558888-line-71)">                        file name of changelog </text><text class="terminal-1655558888-r2" x="573.4" y="1752.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-71)">(</text><text class="terminal-1655558888-r1" x="585.6" y="1752.4" textLength="109.8" clip-path="url(#terminal-1655558888-line-71)">default: </text><text class="terminal-1655558888-r4" x="695.4" y="1752.4" textLength="170.8" clip-path="url(#terminal-1655558888-line-71)">'CHANGELOG.md'</text><text class="terminal-1655558888-r2" x="866.2" y="1752.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-71)">)</text><text class="terminal-1655558888-r1" x="976" y="1752.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-71)"> -</text><text class="terminal-1655558888-r1" x="0" y="1776.8" textLength="475.8" clip-path="url(#terminal-1655558888-line-72)">  --prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-1655558888-r1" x="976" y="1776.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-72)"> -</text><text class="terminal-1655558888-r1" x="0" y="1801.2" textLength="719.8" clip-path="url(#terminal-1655558888-line-73)">                        start pre-releases with this offset</text><text class="terminal-1655558888-r1" x="976" y="1801.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-73)"> -</text><text class="terminal-1655558888-r1" x="0" y="1825.6" textLength="231.8" clip-path="url(#terminal-1655558888-line-74)">  --version-scheme </text><text class="terminal-1655558888-r2" x="231.8" y="1825.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-74)">{</text><text class="terminal-1655558888-r1" x="244" y="1825.6" textLength="256.2" clip-path="url(#terminal-1655558888-line-74)">pep440,semver,semver2</text><text class="terminal-1655558888-r2" x="500.2" y="1825.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-74)">}</text><text class="terminal-1655558888-r1" x="976" y="1825.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-74)"> -</text><text class="terminal-1655558888-r1" x="0" y="1850" textLength="549" clip-path="url(#terminal-1655558888-line-75)">                        choose version scheme</text><text class="terminal-1655558888-r1" x="976" y="1850" textLength="12.2" clip-path="url(#terminal-1655558888-line-75)"> -</text><text class="terminal-1655558888-r1" x="0" y="1874.4" textLength="207.4" clip-path="url(#terminal-1655558888-line-76)">  --version-type </text><text class="terminal-1655558888-r2" x="207.4" y="1874.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-76)">{</text><text class="terminal-1655558888-r1" x="219.6" y="1874.4" textLength="256.2" clip-path="url(#terminal-1655558888-line-76)">pep440,semver,semver2</text><text class="terminal-1655558888-r2" x="475.8" y="1874.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-76)">}</text><text class="terminal-1655558888-r1" x="976" y="1874.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-76)"> -</text><text class="terminal-1655558888-r1" x="0" y="1898.8" textLength="780.8" clip-path="url(#terminal-1655558888-line-77)">                        Deprecated, use --version-scheme instead</text><text class="terminal-1655558888-r1" x="976" y="1898.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-77)"> -</text><text class="terminal-1655558888-r1" x="0" y="1923.2" textLength="402.6" clip-path="url(#terminal-1655558888-line-78)">  --build-metadata BUILD_METADATA</text><text class="terminal-1655558888-r1" x="976" y="1923.2" textLength="12.2" clip-path="url(#terminal-1655558888-line-78)"> -</text><text class="terminal-1655558888-r1" x="0" y="1947.6" textLength="915" clip-path="url(#terminal-1655558888-line-79)">                        Add additional build-metadata to the version-number</text><text class="terminal-1655558888-r1" x="976" y="1947.6" textLength="12.2" clip-path="url(#terminal-1655558888-line-79)"> -</text><text class="terminal-1655558888-r1" x="0" y="1972" textLength="854" clip-path="url(#terminal-1655558888-line-80)">  --get-next            Determine the next version and write to stdout</text><text class="terminal-1655558888-r1" x="976" y="1972" textLength="12.2" clip-path="url(#terminal-1655558888-line-80)"> -</text><text class="terminal-1655558888-r1" x="0" y="1996.4" textLength="744.2" clip-path="url(#terminal-1655558888-line-81)">  --allow-no-commit     bump version without eligible commits</text><text class="terminal-1655558888-r1" x="976" y="1996.4" textLength="12.2" clip-path="url(#terminal-1655558888-line-81)"> -</text><text class="terminal-1655558888-r1" x="976" y="2020.8" textLength="12.2" clip-path="url(#terminal-1655558888-line-82)"> + <g class="terminal-1363677843-matrix"> + <text class="terminal-1363677843-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-1363677843-line-0)">$ cz bump --help</text><text class="terminal-1363677843-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1363677843-line-0)"> +</text><text class="terminal-1363677843-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-1363677843-line-1)">usage: cz bump </text><text class="terminal-1363677843-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1363677843-line-1)">-h</text><text class="terminal-1363677843-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="256.2" y="44.4" textLength="109.8" clip-path="url(#terminal-1363677843-line-1)">--dry-run</text><text class="terminal-1363677843-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="402.6" y="44.4" textLength="146.4" clip-path="url(#terminal-1363677843-line-1)">--files-only</text><text class="terminal-1363677843-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="573.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="585.6" y="44.4" textLength="183" clip-path="url(#terminal-1363677843-line-1)">--local-version</text><text class="terminal-1363677843-r2" x="768.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="793" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="805.2" y="44.4" textLength="134.2" clip-path="url(#terminal-1363677843-line-1)">--changelog</text><text class="terminal-1363677843-r2" x="939.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)"> +</text><text class="terminal-1363677843-r2" x="183" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">[</text><text class="terminal-1363677843-r1" x="195.2" y="68.8" textLength="134.2" clip-path="url(#terminal-1363677843-line-2)">--no-verify</text><text class="terminal-1363677843-r2" x="329.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">]</text><text class="terminal-1363677843-r2" x="353.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">[</text><text class="terminal-1363677843-r1" x="366" y="68.8" textLength="61" clip-path="url(#terminal-1363677843-line-2)">--yes</text><text class="terminal-1363677843-r2" x="427" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">]</text><text class="terminal-1363677843-r2" x="451.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">[</text><text class="terminal-1363677843-r1" x="463.6" y="68.8" textLength="280.6" clip-path="url(#terminal-1363677843-line-2)">--tag-format TAG_FORMAT</text><text class="terminal-1363677843-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">]</text><text class="terminal-1363677843-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)"> +</text><text class="terminal-1363677843-r2" x="183" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">[</text><text class="terminal-1363677843-r1" x="195.2" y="93.2" textLength="329.4" clip-path="url(#terminal-1363677843-line-3)">--bump-message BUMP_MESSAGE</text><text class="terminal-1363677843-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">]</text><text class="terminal-1363677843-r2" x="549" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">[</text><text class="terminal-1363677843-r1" x="561.2" y="93.2" textLength="158.6" clip-path="url(#terminal-1363677843-line-3)">--prerelease </text><text class="terminal-1363677843-r2" x="719.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">{</text><text class="terminal-1363677843-r1" x="732" y="93.2" textLength="158.6" clip-path="url(#terminal-1363677843-line-3)">alpha,beta,rc</text><text class="terminal-1363677843-r2" x="890.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">}</text><text class="terminal-1363677843-r2" x="902.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">]</text><text class="terminal-1363677843-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)"> +</text><text class="terminal-1363677843-r2" x="183" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">[</text><text class="terminal-1363677843-r1" x="195.2" y="117.6" textLength="280.6" clip-path="url(#terminal-1363677843-line-4)">--devrelease DEVRELEASE</text><text class="terminal-1363677843-r2" x="475.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">]</text><text class="terminal-1363677843-r2" x="500.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">[</text><text class="terminal-1363677843-r1" x="512.4" y="117.6" textLength="146.4" clip-path="url(#terminal-1363677843-line-4)">--increment </text><text class="terminal-1363677843-r2" x="658.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">{</text><text class="terminal-1363677843-r1" x="671" y="117.6" textLength="207.4" clip-path="url(#terminal-1363677843-line-4)">MAJOR,MINOR,PATCH</text><text class="terminal-1363677843-r2" x="878.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">}</text><text class="terminal-1363677843-r2" x="890.6" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">]</text><text class="terminal-1363677843-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)"> +</text><text class="terminal-1363677843-r2" x="183" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">[</text><text class="terminal-1363677843-r1" x="195.2" y="142" textLength="207.4" clip-path="url(#terminal-1363677843-line-5)">--increment-mode </text><text class="terminal-1363677843-r2" x="402.6" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">{</text><text class="terminal-1363677843-r1" x="414.8" y="142" textLength="146.4" clip-path="url(#terminal-1363677843-line-5)">linear,exact</text><text class="terminal-1363677843-r2" x="561.2" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">}</text><text class="terminal-1363677843-r2" x="573.4" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">]</text><text class="terminal-1363677843-r2" x="597.8" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">[</text><text class="terminal-1363677843-r1" x="610" y="142" textLength="231.8" clip-path="url(#terminal-1363677843-line-5)">--check-consistency</text><text class="terminal-1363677843-r2" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">]</text><text class="terminal-1363677843-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)"> +</text><text class="terminal-1363677843-r2" x="183" y="166.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-6)">[</text><text class="terminal-1363677843-r1" x="195.2" y="166.4" textLength="183" clip-path="url(#terminal-1363677843-line-6)">--annotated-tag</text><text class="terminal-1363677843-r2" x="378.2" y="166.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-6)">]</text><text class="terminal-1363677843-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-6)"> +</text><text class="terminal-1363677843-r2" x="183" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">[</text><text class="terminal-1363677843-r1" x="195.2" y="190.8" textLength="549" clip-path="url(#terminal-1363677843-line-7)">--annotated-tag-message ANNOTATED_TAG_MESSAGE</text><text class="terminal-1363677843-r2" x="744.2" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">]</text><text class="terminal-1363677843-r2" x="768.6" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">[</text><text class="terminal-1363677843-r1" x="780.8" y="190.8" textLength="122" clip-path="url(#terminal-1363677843-line-7)">--gpg-sign</text><text class="terminal-1363677843-r2" x="902.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">]</text><text class="terminal-1363677843-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)"> +</text><text class="terminal-1363677843-r2" x="183" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">[</text><text class="terminal-1363677843-r1" x="195.2" y="215.2" textLength="256.2" clip-path="url(#terminal-1363677843-line-8)">--changelog-to-stdout</text><text class="terminal-1363677843-r2" x="451.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">]</text><text class="terminal-1363677843-r2" x="475.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">[</text><text class="terminal-1363677843-r1" x="488" y="215.2" textLength="268.4" clip-path="url(#terminal-1363677843-line-8)">--git-output-to-stderr</text><text class="terminal-1363677843-r2" x="756.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">]</text><text class="terminal-1363677843-r2" x="780.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">[</text><text class="terminal-1363677843-r1" x="793" y="215.2" textLength="85.4" clip-path="url(#terminal-1363677843-line-8)">--retry</text><text class="terminal-1363677843-r2" x="878.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">]</text><text class="terminal-1363677843-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)"> +</text><text class="terminal-1363677843-r2" x="183" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">[</text><text class="terminal-1363677843-r1" x="195.2" y="239.6" textLength="244" clip-path="url(#terminal-1363677843-line-9)">--major-version-zero</text><text class="terminal-1363677843-r2" x="439.2" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">]</text><text class="terminal-1363677843-r2" x="463.6" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">[</text><text class="terminal-1363677843-r1" x="475.8" y="239.6" textLength="231.8" clip-path="url(#terminal-1363677843-line-9)">--template TEMPLATE</text><text class="terminal-1363677843-r2" x="707.6" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">]</text><text class="terminal-1363677843-r2" x="732" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">[</text><text class="terminal-1363677843-r1" x="744.2" y="239.6" textLength="158.6" clip-path="url(#terminal-1363677843-line-9)">--extra EXTRA</text><text class="terminal-1363677843-r2" x="902.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">]</text><text class="terminal-1363677843-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)"> +</text><text class="terminal-1363677843-r2" x="183" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">[</text><text class="terminal-1363677843-r1" x="195.2" y="264" textLength="256.2" clip-path="url(#terminal-1363677843-line-10)">--file-name FILE_NAME</text><text class="terminal-1363677843-r2" x="451.4" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">]</text><text class="terminal-1363677843-r2" x="475.8" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">[</text><text class="terminal-1363677843-r1" x="488" y="264" textLength="451.4" clip-path="url(#terminal-1363677843-line-10)">--prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-1363677843-r2" x="939.4" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">]</text><text class="terminal-1363677843-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)"> +</text><text class="terminal-1363677843-r2" x="183" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">[</text><text class="terminal-1363677843-r1" x="195.2" y="288.4" textLength="207.4" clip-path="url(#terminal-1363677843-line-11)">--version-scheme </text><text class="terminal-1363677843-r2" x="402.6" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">{</text><text class="terminal-1363677843-r1" x="414.8" y="288.4" textLength="256.2" clip-path="url(#terminal-1363677843-line-11)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="671" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">}</text><text class="terminal-1363677843-r2" x="683.2" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">]</text><text class="terminal-1363677843-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)"> +</text><text class="terminal-1363677843-r2" x="183" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">[</text><text class="terminal-1363677843-r1" x="195.2" y="312.8" textLength="183" clip-path="url(#terminal-1363677843-line-12)">--version-type </text><text class="terminal-1363677843-r2" x="378.2" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">{</text><text class="terminal-1363677843-r1" x="390.4" y="312.8" textLength="256.2" clip-path="url(#terminal-1363677843-line-12)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="646.6" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">}</text><text class="terminal-1363677843-r2" x="658.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">]</text><text class="terminal-1363677843-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)"> +</text><text class="terminal-1363677843-r2" x="183" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">[</text><text class="terminal-1363677843-r1" x="195.2" y="337.2" textLength="378.2" clip-path="url(#terminal-1363677843-line-13)">--build-metadata BUILD_METADATA</text><text class="terminal-1363677843-r2" x="573.4" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">]</text><text class="terminal-1363677843-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">[</text><text class="terminal-1363677843-r1" x="610" y="337.2" textLength="122" clip-path="url(#terminal-1363677843-line-13)">--get-next</text><text class="terminal-1363677843-r2" x="732" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">]</text><text class="terminal-1363677843-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)"> +</text><text class="terminal-1363677843-r2" x="183" y="361.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-14)">[</text><text class="terminal-1363677843-r1" x="195.2" y="361.6" textLength="207.4" clip-path="url(#terminal-1363677843-line-14)">--allow-no-commit</text><text class="terminal-1363677843-r2" x="402.6" y="361.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-14)">]</text><text class="terminal-1363677843-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-14)"> +</text><text class="terminal-1363677843-r2" x="183" y="386" textLength="12.2" clip-path="url(#terminal-1363677843-line-15)">[</text><text class="terminal-1363677843-r1" x="195.2" y="386" textLength="170.8" clip-path="url(#terminal-1363677843-line-15)">MANUAL_VERSION</text><text class="terminal-1363677843-r2" x="366" y="386" textLength="12.2" clip-path="url(#terminal-1363677843-line-15)">]</text><text class="terminal-1363677843-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1363677843-line-15)"> +</text><text class="terminal-1363677843-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-16)"> +</text><text class="terminal-1363677843-r1" x="0" y="434.8" textLength="512.4" clip-path="url(#terminal-1363677843-line-17)">bump semantic version based on the git log</text><text class="terminal-1363677843-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-17)"> +</text><text class="terminal-1363677843-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-18)"> +</text><text class="terminal-1363677843-r1" x="0" y="483.6" textLength="256.2" clip-path="url(#terminal-1363677843-line-19)">positional arguments:</text><text class="terminal-1363677843-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-19)"> +</text><text class="terminal-1363677843-r1" x="0" y="508" textLength="610" clip-path="url(#terminal-1363677843-line-20)">  MANUAL_VERSION        bump to the given version </text><text class="terminal-1363677843-r2" x="610" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">(</text><text class="terminal-1363677843-r1" x="622.2" y="508" textLength="61" clip-path="url(#terminal-1363677843-line-20)">e.g: </text><text class="terminal-1363677843-r3" x="683.2" y="508" textLength="36.6" clip-path="url(#terminal-1363677843-line-20)">1.5</text><text class="terminal-1363677843-r1" x="719.8" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">.</text><text class="terminal-1363677843-r3" x="732" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">3</text><text class="terminal-1363677843-r2" x="744.2" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">)</text><text class="terminal-1363677843-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)"> +</text><text class="terminal-1363677843-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-21)"> +</text><text class="terminal-1363677843-r1" x="0" y="556.8" textLength="97.6" clip-path="url(#terminal-1363677843-line-22)">options:</text><text class="terminal-1363677843-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-22)"> +</text><text class="terminal-1363677843-r1" x="0" y="581.2" textLength="671" clip-path="url(#terminal-1363677843-line-23)">  -h, --help            show this help message and exit</text><text class="terminal-1363677843-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-23)"> +</text><text class="terminal-1363677843-r1" x="0" y="605.6" textLength="915" clip-path="url(#terminal-1363677843-line-24)">  --dry-run             show output to stdout, no commit, no modified files</text><text class="terminal-1363677843-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-24)"> +</text><text class="terminal-1363677843-r1" x="0" y="630" textLength="793" clip-path="url(#terminal-1363677843-line-25)">  --files-only          bump version in the files from the config</text><text class="terminal-1363677843-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1363677843-line-25)"> +</text><text class="terminal-1363677843-r1" x="0" y="654.4" textLength="719.8" clip-path="url(#terminal-1363677843-line-26)">  --local-version       bump only the local version portion</text><text class="terminal-1363677843-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-26)"> +</text><text class="terminal-1363677843-r1" x="0" y="678.8" textLength="841.8" clip-path="url(#terminal-1363677843-line-27)">  --changelog, -ch      generate the changelog for the newest version</text><text class="terminal-1363677843-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-27)"> +</text><text class="terminal-1363677843-r1" x="0" y="703.2" textLength="902.8" clip-path="url(#terminal-1363677843-line-28)">  --no-verify           this option bypasses the pre-commit and commit-msg</text><text class="terminal-1363677843-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-28)"> +</text><text class="terminal-1363677843-r1" x="0" y="727.6" textLength="353.8" clip-path="url(#terminal-1363677843-line-29)">                        hooks</text><text class="terminal-1363677843-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-29)"> +</text><text class="terminal-1363677843-r1" x="0" y="752" textLength="719.8" clip-path="url(#terminal-1363677843-line-30)">  --yes                 accept automatically questions done</text><text class="terminal-1363677843-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1363677843-line-30)"> +</text><text class="terminal-1363677843-r1" x="0" y="776.4" textLength="305" clip-path="url(#terminal-1363677843-line-31)">  --tag-format TAG_FORMAT</text><text class="terminal-1363677843-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-31)"> +</text><text class="terminal-1363677843-r1" x="0" y="800.8" textLength="939.4" clip-path="url(#terminal-1363677843-line-32)">                        the format used to tag the commit and read it, use it</text><text class="terminal-1363677843-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-32)"> +</text><text class="terminal-1363677843-r1" x="0" y="825.2" textLength="866.2" clip-path="url(#terminal-1363677843-line-33)">                        in existing projects, wrap around simple quotes</text><text class="terminal-1363677843-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-33)"> +</text><text class="terminal-1363677843-r1" x="0" y="849.6" textLength="353.8" clip-path="url(#terminal-1363677843-line-34)">  --bump-message BUMP_MESSAGE</text><text class="terminal-1363677843-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-34)"> +</text><text class="terminal-1363677843-r1" x="0" y="874" textLength="902.8" clip-path="url(#terminal-1363677843-line-35)">                        template used to create the release commit, useful</text><text class="terminal-1363677843-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-1363677843-line-35)"> +</text><text class="terminal-1363677843-r1" x="0" y="898.4" textLength="536.8" clip-path="url(#terminal-1363677843-line-36)">                        when working with CI</text><text class="terminal-1363677843-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-36)"> +</text><text class="terminal-1363677843-r1" x="0" y="922.8" textLength="183" clip-path="url(#terminal-1363677843-line-37)">  --prerelease </text><text class="terminal-1363677843-r2" x="183" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">{</text><text class="terminal-1363677843-r1" x="195.2" y="922.8" textLength="158.6" clip-path="url(#terminal-1363677843-line-37)">alpha,beta,rc</text><text class="terminal-1363677843-r2" x="353.8" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">}</text><text class="terminal-1363677843-r1" x="366" y="922.8" textLength="73.2" clip-path="url(#terminal-1363677843-line-37)">, -pr </text><text class="terminal-1363677843-r2" x="439.2" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">{</text><text class="terminal-1363677843-r1" x="451.4" y="922.8" textLength="158.6" clip-path="url(#terminal-1363677843-line-37)">alpha,beta,rc</text><text class="terminal-1363677843-r2" x="610" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">}</text><text class="terminal-1363677843-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)"> +</text><text class="terminal-1363677843-r1" x="0" y="947.2" textLength="597.8" clip-path="url(#terminal-1363677843-line-38)">                        choose type of prerelease</text><text class="terminal-1363677843-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-38)"> +</text><text class="terminal-1363677843-r1" x="0" y="971.6" textLength="488" clip-path="url(#terminal-1363677843-line-39)">  --devrelease DEVRELEASE, -d DEVRELEASE</text><text class="terminal-1363677843-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-39)"> +</text><text class="terminal-1363677843-r1" x="0" y="996" textLength="841.8" clip-path="url(#terminal-1363677843-line-40)">                        specify non-negative integer for dev. release</text><text class="terminal-1363677843-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-1363677843-line-40)"> +</text><text class="terminal-1363677843-r1" x="0" y="1020.4" textLength="170.8" clip-path="url(#terminal-1363677843-line-41)">  --increment </text><text class="terminal-1363677843-r2" x="170.8" y="1020.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-41)">{</text><text class="terminal-1363677843-r1" x="183" y="1020.4" textLength="207.4" clip-path="url(#terminal-1363677843-line-41)">MAJOR,MINOR,PATCH</text><text class="terminal-1363677843-r2" x="390.4" y="1020.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-41)">}</text><text class="terminal-1363677843-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-41)"> +</text><text class="terminal-1363677843-r1" x="0" y="1044.8" textLength="756.4" clip-path="url(#terminal-1363677843-line-42)">                        manually specify the desired increment</text><text class="terminal-1363677843-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-42)"> +</text><text class="terminal-1363677843-r1" x="0" y="1069.2" textLength="231.8" clip-path="url(#terminal-1363677843-line-43)">  --increment-mode </text><text class="terminal-1363677843-r2" x="231.8" y="1069.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-43)">{</text><text class="terminal-1363677843-r1" x="244" y="1069.2" textLength="146.4" clip-path="url(#terminal-1363677843-line-43)">linear,exact</text><text class="terminal-1363677843-r2" x="390.4" y="1069.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-43)">}</text><text class="terminal-1363677843-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-43)"> +</text><text class="terminal-1363677843-r1" x="0" y="1093.6" textLength="902.8" clip-path="url(#terminal-1363677843-line-44)">                        set the method by which the new version is chosen.</text><text class="terminal-1363677843-r1" x="976" y="1093.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-44)"> +</text><text class="terminal-1363677843-r4" x="292.8" y="1118" textLength="97.6" clip-path="url(#terminal-1363677843-line-45)">'linear'</text><text class="terminal-1363677843-r2" x="402.6" y="1118" textLength="12.2" clip-path="url(#terminal-1363677843-line-45)">(</text><text class="terminal-1363677843-r1" x="414.8" y="1118" textLength="85.4" clip-path="url(#terminal-1363677843-line-45)">default</text><text class="terminal-1363677843-r2" x="500.2" y="1118" textLength="12.2" clip-path="url(#terminal-1363677843-line-45)">)</text><text class="terminal-1363677843-r1" x="512.4" y="1118" textLength="414.8" clip-path="url(#terminal-1363677843-line-45)"> guesses the next version based on</text><text class="terminal-1363677843-r1" x="976" y="1118" textLength="12.2" clip-path="url(#terminal-1363677843-line-45)"> +</text><text class="terminal-1363677843-r1" x="0" y="1142.4" textLength="939.4" clip-path="url(#terminal-1363677843-line-46)">                        typical linear version progression, such that bumping</text><text class="terminal-1363677843-r1" x="976" y="1142.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-46)"> +</text><text class="terminal-1363677843-r1" x="0" y="1166.8" textLength="866.2" clip-path="url(#terminal-1363677843-line-47)">                        of a pre-release with lower precedence than the</text><text class="terminal-1363677843-r1" x="976" y="1166.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-47)"> +</text><text class="terminal-1363677843-r1" x="0" y="1191.2" textLength="939.4" clip-path="url(#terminal-1363677843-line-48)">                        current pre-release phase maintains the current phase</text><text class="terminal-1363677843-r1" x="976" y="1191.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-48)"> +</text><text class="terminal-1363677843-r1" x="0" y="1215.6" textLength="561.2" clip-path="url(#terminal-1363677843-line-49)">                        of higher precedence. </text><text class="terminal-1363677843-r4" x="561.2" y="1215.6" textLength="85.4" clip-path="url(#terminal-1363677843-line-49)">'exact'</text><text class="terminal-1363677843-r1" x="646.6" y="1215.6" textLength="305" clip-path="url(#terminal-1363677843-line-49)"> applies the changes that</text><text class="terminal-1363677843-r1" x="976" y="1215.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-49)"> +</text><text class="terminal-1363677843-r1" x="0" y="1240" textLength="536.8" clip-path="url(#terminal-1363677843-line-50)">                        have been specified </text><text class="terminal-1363677843-r2" x="536.8" y="1240" textLength="12.2" clip-path="url(#terminal-1363677843-line-50)">(</text><text class="terminal-1363677843-r1" x="549" y="1240" textLength="353.8" clip-path="url(#terminal-1363677843-line-50)">or determined from the commit</text><text class="terminal-1363677843-r1" x="976" y="1240" textLength="12.2" clip-path="url(#terminal-1363677843-line-50)"> +</text><text class="terminal-1363677843-r1" x="0" y="1264.4" textLength="329.4" clip-path="url(#terminal-1363677843-line-51)">                        log</text><text class="terminal-1363677843-r2" x="329.4" y="1264.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-51)">)</text><text class="terminal-1363677843-r1" x="341.6" y="1264.4" textLength="585.6" clip-path="url(#terminal-1363677843-line-51)"> without interpretation, such that the increment</text><text class="terminal-1363677843-r1" x="976" y="1264.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-51)"> +</text><text class="terminal-1363677843-r1" x="0" y="1288.8" textLength="707.6" clip-path="url(#terminal-1363677843-line-52)">                        and pre-release are always honored</text><text class="terminal-1363677843-r1" x="976" y="1288.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-52)"> +</text><text class="terminal-1363677843-r1" x="0" y="1313.2" textLength="317.2" clip-path="url(#terminal-1363677843-line-53)">  --check-consistency, -cc</text><text class="terminal-1363677843-r1" x="976" y="1313.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-53)"> +</text><text class="terminal-1363677843-r1" x="0" y="1337.6" textLength="951.6" clip-path="url(#terminal-1363677843-line-54)">                        check consistency among versions defined in commitizen</text><text class="terminal-1363677843-r1" x="976" y="1337.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-54)"> +</text><text class="terminal-1363677843-r1" x="0" y="1362" textLength="671" clip-path="url(#terminal-1363677843-line-55)">                        configuration and version_files</text><text class="terminal-1363677843-r1" x="976" y="1362" textLength="12.2" clip-path="url(#terminal-1363677843-line-55)"> +</text><text class="terminal-1363677843-r1" x="0" y="1386.4" textLength="866.2" clip-path="url(#terminal-1363677843-line-56)">  --annotated-tag, -at  create annotated tag instead of lightweight one</text><text class="terminal-1363677843-r1" x="976" y="1386.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-56)"> +</text><text class="terminal-1363677843-r1" x="0" y="1410.8" textLength="915" clip-path="url(#terminal-1363677843-line-57)">  --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE</text><text class="terminal-1363677843-r1" x="976" y="1410.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-57)"> +</text><text class="terminal-1363677843-r1" x="0" y="1435.2" textLength="634.4" clip-path="url(#terminal-1363677843-line-58)">                        create annotated tag message</text><text class="terminal-1363677843-r1" x="976" y="1435.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-58)"> +</text><text class="terminal-1363677843-r1" x="0" y="1459.6" textLength="719.8" clip-path="url(#terminal-1363677843-line-59)">  --gpg-sign, -s        sign tag instead of lightweight one</text><text class="terminal-1363677843-r1" x="976" y="1459.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-59)"> +</text><text class="terminal-1363677843-r1" x="0" y="1484" textLength="280.6" clip-path="url(#terminal-1363677843-line-60)">  --changelog-to-stdout</text><text class="terminal-1363677843-r1" x="976" y="1484" textLength="12.2" clip-path="url(#terminal-1363677843-line-60)"> +</text><text class="terminal-1363677843-r1" x="0" y="1508.4" textLength="658.8" clip-path="url(#terminal-1363677843-line-61)">                        Output changelog to the stdout</text><text class="terminal-1363677843-r1" x="976" y="1508.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-61)"> +</text><text class="terminal-1363677843-r1" x="0" y="1532.8" textLength="292.8" clip-path="url(#terminal-1363677843-line-62)">  --git-output-to-stderr</text><text class="terminal-1363677843-r1" x="976" y="1532.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-62)"> +</text><text class="terminal-1363677843-r1" x="0" y="1557.2" textLength="646.6" clip-path="url(#terminal-1363677843-line-63)">                        Redirect git output to stderr</text><text class="terminal-1363677843-r1" x="976" y="1557.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-63)"> +</text><text class="terminal-1363677843-r1" x="0" y="1581.6" textLength="744.2" clip-path="url(#terminal-1363677843-line-64)">  --retry               retry commit if it fails the 1st time</text><text class="terminal-1363677843-r1" x="976" y="1581.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-64)"> +</text><text class="terminal-1363677843-r1" x="0" y="1606" textLength="939.4" clip-path="url(#terminal-1363677843-line-65)">  --major-version-zero  keep major version at zero, even for breaking changes</text><text class="terminal-1363677843-r1" x="976" y="1606" textLength="12.2" clip-path="url(#terminal-1363677843-line-65)"> +</text><text class="terminal-1363677843-r1" x="0" y="1630.4" textLength="414.8" clip-path="url(#terminal-1363677843-line-66)">  --template TEMPLATE, -t TEMPLATE</text><text class="terminal-1363677843-r1" x="976" y="1630.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-66)"> +</text><text class="terminal-1363677843-r1" x="0" y="1654.8" textLength="646.6" clip-path="url(#terminal-1363677843-line-67)">                        changelog template file name </text><text class="terminal-1363677843-r2" x="646.6" y="1654.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-67)">(</text><text class="terminal-1363677843-r1" x="658.8" y="1654.8" textLength="280.6" clip-path="url(#terminal-1363677843-line-67)">relative to the current</text><text class="terminal-1363677843-r1" x="976" y="1654.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-67)"> +</text><text class="terminal-1363677843-r1" x="0" y="1679.2" textLength="500.2" clip-path="url(#terminal-1363677843-line-68)">                        working directory</text><text class="terminal-1363677843-r2" x="500.2" y="1679.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-68)">)</text><text class="terminal-1363677843-r1" x="976" y="1679.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-68)"> +</text><text class="terminal-1363677843-r1" x="0" y="1703.6" textLength="305" clip-path="url(#terminal-1363677843-line-69)">  --extra EXTRA, -e EXTRA</text><text class="terminal-1363677843-r1" x="976" y="1703.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-69)"> +</text><text class="terminal-1363677843-r1" x="0" y="1728" textLength="622.2" clip-path="url(#terminal-1363677843-line-70)">                        a changelog extra variable </text><text class="terminal-1363677843-r2" x="622.2" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">(</text><text class="terminal-1363677843-r1" x="634.4" y="1728" textLength="146.4" clip-path="url(#terminal-1363677843-line-70)">in the form </text><text class="terminal-1363677843-r4" x="780.8" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">'</text><text class="terminal-1363677843-r4" x="793" y="1728" textLength="36.6" clip-path="url(#terminal-1363677843-line-70)">key</text><text class="terminal-1363677843-r4" x="829.6" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">=</text><text class="terminal-1363677843-r4" x="841.8" y="1728" textLength="61" clip-path="url(#terminal-1363677843-line-70)">value</text><text class="terminal-1363677843-r4" x="902.8" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">'</text><text class="terminal-1363677843-r2" x="915" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">)</text><text class="terminal-1363677843-r1" x="976" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)"> +</text><text class="terminal-1363677843-r1" x="0" y="1752.4" textLength="280.6" clip-path="url(#terminal-1363677843-line-71)">  --file-name FILE_NAME</text><text class="terminal-1363677843-r1" x="976" y="1752.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-71)"> +</text><text class="terminal-1363677843-r1" x="0" y="1776.8" textLength="573.4" clip-path="url(#terminal-1363677843-line-72)">                        file name of changelog </text><text class="terminal-1363677843-r2" x="573.4" y="1776.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-72)">(</text><text class="terminal-1363677843-r1" x="585.6" y="1776.8" textLength="109.8" clip-path="url(#terminal-1363677843-line-72)">default: </text><text class="terminal-1363677843-r4" x="695.4" y="1776.8" textLength="170.8" clip-path="url(#terminal-1363677843-line-72)">'CHANGELOG.md'</text><text class="terminal-1363677843-r2" x="866.2" y="1776.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-72)">)</text><text class="terminal-1363677843-r1" x="976" y="1776.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-72)"> +</text><text class="terminal-1363677843-r1" x="0" y="1801.2" textLength="475.8" clip-path="url(#terminal-1363677843-line-73)">  --prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-1363677843-r1" x="976" y="1801.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-73)"> +</text><text class="terminal-1363677843-r1" x="0" y="1825.6" textLength="719.8" clip-path="url(#terminal-1363677843-line-74)">                        start pre-releases with this offset</text><text class="terminal-1363677843-r1" x="976" y="1825.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-74)"> +</text><text class="terminal-1363677843-r1" x="0" y="1850" textLength="231.8" clip-path="url(#terminal-1363677843-line-75)">  --version-scheme </text><text class="terminal-1363677843-r2" x="231.8" y="1850" textLength="12.2" clip-path="url(#terminal-1363677843-line-75)">{</text><text class="terminal-1363677843-r1" x="244" y="1850" textLength="256.2" clip-path="url(#terminal-1363677843-line-75)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="500.2" y="1850" textLength="12.2" clip-path="url(#terminal-1363677843-line-75)">}</text><text class="terminal-1363677843-r1" x="976" y="1850" textLength="12.2" clip-path="url(#terminal-1363677843-line-75)"> +</text><text class="terminal-1363677843-r1" x="0" y="1874.4" textLength="549" clip-path="url(#terminal-1363677843-line-76)">                        choose version scheme</text><text class="terminal-1363677843-r1" x="976" y="1874.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-76)"> +</text><text class="terminal-1363677843-r1" x="0" y="1898.8" textLength="207.4" clip-path="url(#terminal-1363677843-line-77)">  --version-type </text><text class="terminal-1363677843-r2" x="207.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-77)">{</text><text class="terminal-1363677843-r1" x="219.6" y="1898.8" textLength="256.2" clip-path="url(#terminal-1363677843-line-77)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="475.8" y="1898.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-77)">}</text><text class="terminal-1363677843-r1" x="976" y="1898.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-77)"> +</text><text class="terminal-1363677843-r1" x="0" y="1923.2" textLength="780.8" clip-path="url(#terminal-1363677843-line-78)">                        Deprecated, use --version-scheme instead</text><text class="terminal-1363677843-r1" x="976" y="1923.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-78)"> +</text><text class="terminal-1363677843-r1" x="0" y="1947.6" textLength="402.6" clip-path="url(#terminal-1363677843-line-79)">  --build-metadata BUILD_METADATA</text><text class="terminal-1363677843-r1" x="976" y="1947.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-79)"> +</text><text class="terminal-1363677843-r1" x="0" y="1972" textLength="915" clip-path="url(#terminal-1363677843-line-80)">                        Add additional build-metadata to the version-number</text><text class="terminal-1363677843-r1" x="976" y="1972" textLength="12.2" clip-path="url(#terminal-1363677843-line-80)"> +</text><text class="terminal-1363677843-r1" x="0" y="1996.4" textLength="854" clip-path="url(#terminal-1363677843-line-81)">  --get-next            Determine the next version and write to stdout</text><text class="terminal-1363677843-r1" x="976" y="1996.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-81)"> +</text><text class="terminal-1363677843-r1" x="0" y="2020.8" textLength="744.2" clip-path="url(#terminal-1363677843-line-82)">  --allow-no-commit     bump version without eligible commits</text><text class="terminal-1363677843-r1" x="976" y="2020.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-82)"> +</text><text class="terminal-1363677843-r1" x="976" y="2045.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-83)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_changelog___help.svg b/docs/images/cli_help/cz_changelog___help.svg index 69304f40cf..1d98c05b38 100644 --- a/docs/images/cli_help/cz_changelog___help.svg +++ b/docs/images/cli_help/cz_changelog___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 1099.2" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 1123.6" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,210 +19,214 @@ font-weight: 700; } - .terminal-2926696453-matrix { + .terminal-192800993-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2926696453-title { + .terminal-192800993-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2926696453-r1 { fill: #c5c8c6 } -.terminal-2926696453-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-2926696453-r3 { fill: #68a0b3;font-weight: bold } -.terminal-2926696453-r4 { fill: #98a84b } + .terminal-192800993-r1 { fill: #c5c8c6 } +.terminal-192800993-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-192800993-r3 { fill: #68a0b3;font-weight: bold } +.terminal-192800993-r4 { fill: #98a84b } </style> <defs> - <clipPath id="terminal-2926696453-clip-terminal"> - <rect x="0" y="0" width="975.0" height="1048.2" /> + <clipPath id="terminal-192800993-clip-terminal"> + <rect x="0" y="0" width="975.0" height="1072.6" /> </clipPath> - <clipPath id="terminal-2926696453-line-0"> + <clipPath id="terminal-192800993-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-1"> +<clipPath id="terminal-192800993-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-2"> +<clipPath id="terminal-192800993-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-3"> +<clipPath id="terminal-192800993-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-4"> +<clipPath id="terminal-192800993-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-5"> +<clipPath id="terminal-192800993-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-6"> +<clipPath id="terminal-192800993-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-7"> +<clipPath id="terminal-192800993-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-8"> +<clipPath id="terminal-192800993-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-9"> +<clipPath id="terminal-192800993-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-10"> +<clipPath id="terminal-192800993-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-11"> +<clipPath id="terminal-192800993-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-12"> +<clipPath id="terminal-192800993-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-13"> +<clipPath id="terminal-192800993-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-14"> +<clipPath id="terminal-192800993-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-15"> +<clipPath id="terminal-192800993-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-16"> +<clipPath id="terminal-192800993-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-17"> +<clipPath id="terminal-192800993-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-18"> +<clipPath id="terminal-192800993-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-19"> +<clipPath id="terminal-192800993-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-20"> +<clipPath id="terminal-192800993-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-21"> +<clipPath id="terminal-192800993-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-22"> +<clipPath id="terminal-192800993-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-23"> +<clipPath id="terminal-192800993-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-24"> +<clipPath id="terminal-192800993-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-25"> +<clipPath id="terminal-192800993-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-26"> +<clipPath id="terminal-192800993-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-27"> +<clipPath id="terminal-192800993-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-28"> +<clipPath id="terminal-192800993-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-29"> +<clipPath id="terminal-192800993-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-30"> +<clipPath id="terminal-192800993-line-30"> <rect x="0" y="733.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-31"> +<clipPath id="terminal-192800993-line-31"> <rect x="0" y="757.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-32"> +<clipPath id="terminal-192800993-line-32"> <rect x="0" y="782.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-33"> +<clipPath id="terminal-192800993-line-33"> <rect x="0" y="806.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-34"> +<clipPath id="terminal-192800993-line-34"> <rect x="0" y="831.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-35"> +<clipPath id="terminal-192800993-line-35"> <rect x="0" y="855.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-36"> +<clipPath id="terminal-192800993-line-36"> <rect x="0" y="879.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-37"> +<clipPath id="terminal-192800993-line-37"> <rect x="0" y="904.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-38"> +<clipPath id="terminal-192800993-line-38"> <rect x="0" y="928.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-39"> +<clipPath id="terminal-192800993-line-39"> <rect x="0" y="953.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-40"> +<clipPath id="terminal-192800993-line-40"> <rect x="0" y="977.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2926696453-line-41"> +<clipPath id="terminal-192800993-line-41"> <rect x="0" y="1001.9" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-192800993-line-42"> + <rect x="0" y="1026.3" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="1097.2" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="1121.6" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-2926696453-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-192800993-clip-terminal)"> - <g class="terminal-2926696453-matrix"> - <text class="terminal-2926696453-r1" x="0" y="20" textLength="256.2" clip-path="url(#terminal-2926696453-line-0)">$ cz changelog --help</text><text class="terminal-2926696453-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-2926696453-line-0)"> -</text><text class="terminal-2926696453-r1" x="0" y="44.4" textLength="244" clip-path="url(#terminal-2926696453-line-1)">usage: cz changelog </text><text class="terminal-2926696453-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)">[</text><text class="terminal-2926696453-r1" x="256.2" y="44.4" textLength="24.4" clip-path="url(#terminal-2926696453-line-1)">-h</text><text class="terminal-2926696453-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)">]</text><text class="terminal-2926696453-r2" x="305" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)">[</text><text class="terminal-2926696453-r1" x="317.2" y="44.4" textLength="109.8" clip-path="url(#terminal-2926696453-line-1)">--dry-run</text><text class="terminal-2926696453-r2" x="427" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)">]</text><text class="terminal-2926696453-r2" x="451.4" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)">[</text><text class="terminal-2926696453-r1" x="463.6" y="44.4" textLength="256.2" clip-path="url(#terminal-2926696453-line-1)">--file-name FILE_NAME</text><text class="terminal-2926696453-r2" x="719.8" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)">]</text><text class="terminal-2926696453-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-1)"> -</text><text class="terminal-2926696453-r2" x="244" y="68.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-2)">[</text><text class="terminal-2926696453-r1" x="256.2" y="68.8" textLength="475.8" clip-path="url(#terminal-2926696453-line-2)">--unreleased-version UNRELEASED_VERSION</text><text class="terminal-2926696453-r2" x="732" y="68.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-2)">]</text><text class="terminal-2926696453-r2" x="756.4" y="68.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-2)">[</text><text class="terminal-2926696453-r1" x="768.6" y="68.8" textLength="158.6" clip-path="url(#terminal-2926696453-line-2)">--incremental</text><text class="terminal-2926696453-r2" x="927.2" y="68.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-2)">]</text><text class="terminal-2926696453-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-2)"> -</text><text class="terminal-2926696453-r2" x="244" y="93.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-3)">[</text><text class="terminal-2926696453-r1" x="256.2" y="93.2" textLength="256.2" clip-path="url(#terminal-2926696453-line-3)">--start-rev START_REV</text><text class="terminal-2926696453-r2" x="512.4" y="93.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-3)">]</text><text class="terminal-2926696453-r2" x="536.8" y="93.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-3)">[</text><text class="terminal-2926696453-r1" x="549" y="93.2" textLength="219.6" clip-path="url(#terminal-2926696453-line-3)">--merge-prerelease</text><text class="terminal-2926696453-r2" x="768.6" y="93.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-3)">]</text><text class="terminal-2926696453-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-3)"> -</text><text class="terminal-2926696453-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-4)">[</text><text class="terminal-2926696453-r1" x="256.2" y="117.6" textLength="207.4" clip-path="url(#terminal-2926696453-line-4)">--version-scheme </text><text class="terminal-2926696453-r2" x="463.6" y="117.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-4)">{</text><text class="terminal-2926696453-r1" x="475.8" y="117.6" textLength="256.2" clip-path="url(#terminal-2926696453-line-4)">pep440,semver,semver2</text><text class="terminal-2926696453-r2" x="732" y="117.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-4)">}</text><text class="terminal-2926696453-r2" x="744.2" y="117.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-4)">]</text><text class="terminal-2926696453-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-4)"> -</text><text class="terminal-2926696453-r2" x="244" y="142" textLength="12.2" clip-path="url(#terminal-2926696453-line-5)">[</text><text class="terminal-2926696453-r1" x="256.2" y="142" textLength="402.6" clip-path="url(#terminal-2926696453-line-5)">--export-template EXPORT_TEMPLATE</text><text class="terminal-2926696453-r2" x="658.8" y="142" textLength="12.2" clip-path="url(#terminal-2926696453-line-5)">]</text><text class="terminal-2926696453-r2" x="683.2" y="142" textLength="12.2" clip-path="url(#terminal-2926696453-line-5)">[</text><text class="terminal-2926696453-r1" x="695.4" y="142" textLength="231.8" clip-path="url(#terminal-2926696453-line-5)">--template TEMPLATE</text><text class="terminal-2926696453-r2" x="927.2" y="142" textLength="12.2" clip-path="url(#terminal-2926696453-line-5)">]</text><text class="terminal-2926696453-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-2926696453-line-5)"> -</text><text class="terminal-2926696453-r2" x="244" y="166.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-6)">[</text><text class="terminal-2926696453-r1" x="256.2" y="166.4" textLength="158.6" clip-path="url(#terminal-2926696453-line-6)">--extra EXTRA</text><text class="terminal-2926696453-r2" x="414.8" y="166.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-6)">]</text><text class="terminal-2926696453-r2" x="439.2" y="166.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-6)">[</text><text class="terminal-2926696453-r1" x="451.4" y="166.4" textLength="280.6" clip-path="url(#terminal-2926696453-line-6)">--tag-format TAG_FORMAT</text><text class="terminal-2926696453-r2" x="732" y="166.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-6)">]</text><text class="terminal-2926696453-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-6)"> -</text><text class="terminal-2926696453-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-7)"> -</text><text class="terminal-2926696453-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-8)"> -</text><text class="terminal-2926696453-r1" x="0" y="239.6" textLength="231.8" clip-path="url(#terminal-2926696453-line-9)">generate changelog </text><text class="terminal-2926696453-r2" x="231.8" y="239.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-9)">(</text><text class="terminal-2926696453-r1" x="244" y="239.6" textLength="500.2" clip-path="url(#terminal-2926696453-line-9)">note that it will overwrite existing file</text><text class="terminal-2926696453-r2" x="744.2" y="239.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-9)">)</text><text class="terminal-2926696453-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-9)"> -</text><text class="terminal-2926696453-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-2926696453-line-10)"> -</text><text class="terminal-2926696453-r1" x="0" y="288.4" textLength="256.2" clip-path="url(#terminal-2926696453-line-11)">positional arguments:</text><text class="terminal-2926696453-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-11)"> -</text><text class="terminal-2926696453-r1" x="0" y="312.8" textLength="805.2" clip-path="url(#terminal-2926696453-line-12)">  rev_range             generates changelog for the given version </text><text class="terminal-2926696453-r2" x="805.2" y="312.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-12)">(</text><text class="terminal-2926696453-r1" x="817.4" y="312.8" textLength="61" clip-path="url(#terminal-2926696453-line-12)">e.g: </text><text class="terminal-2926696453-r3" x="878.4" y="312.8" textLength="36.6" clip-path="url(#terminal-2926696453-line-12)">1.5</text><text class="terminal-2926696453-r1" x="915" y="312.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-12)">.</text><text class="terminal-2926696453-r3" x="927.2" y="312.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-12)">3</text><text class="terminal-2926696453-r2" x="939.4" y="312.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-12)">)</text><text class="terminal-2926696453-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-12)"> -</text><text class="terminal-2926696453-r1" x="0" y="337.2" textLength="500.2" clip-path="url(#terminal-2926696453-line-13)">                        or version range </text><text class="terminal-2926696453-r2" x="500.2" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)">(</text><text class="terminal-2926696453-r1" x="512.4" y="337.2" textLength="61" clip-path="url(#terminal-2926696453-line-13)">e.g: </text><text class="terminal-2926696453-r3" x="573.4" y="337.2" textLength="36.6" clip-path="url(#terminal-2926696453-line-13)">1.5</text><text class="terminal-2926696453-r1" x="610" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)">.</text><text class="terminal-2926696453-r3" x="622.2" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)">3</text><text class="terminal-2926696453-r1" x="634.4" y="337.2" textLength="24.4" clip-path="url(#terminal-2926696453-line-13)">..</text><text class="terminal-2926696453-r3" x="658.8" y="337.2" textLength="36.6" clip-path="url(#terminal-2926696453-line-13)">1.7</text><text class="terminal-2926696453-r1" x="695.4" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)">.</text><text class="terminal-2926696453-r3" x="707.6" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)">9</text><text class="terminal-2926696453-r2" x="719.8" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)">)</text><text class="terminal-2926696453-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-13)"> -</text><text class="terminal-2926696453-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-14)"> -</text><text class="terminal-2926696453-r1" x="0" y="386" textLength="97.6" clip-path="url(#terminal-2926696453-line-15)">options:</text><text class="terminal-2926696453-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-2926696453-line-15)"> -</text><text class="terminal-2926696453-r1" x="0" y="410.4" textLength="671" clip-path="url(#terminal-2926696453-line-16)">  -h, --help            show this help message and exit</text><text class="terminal-2926696453-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-16)"> -</text><text class="terminal-2926696453-r1" x="0" y="434.8" textLength="585.6" clip-path="url(#terminal-2926696453-line-17)">  --dry-run             show changelog to stdout</text><text class="terminal-2926696453-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-17)"> -</text><text class="terminal-2926696453-r1" x="0" y="459.2" textLength="280.6" clip-path="url(#terminal-2926696453-line-18)">  --file-name FILE_NAME</text><text class="terminal-2926696453-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-18)"> -</text><text class="terminal-2926696453-r1" x="0" y="483.6" textLength="573.4" clip-path="url(#terminal-2926696453-line-19)">                        file name of changelog </text><text class="terminal-2926696453-r2" x="573.4" y="483.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-19)">(</text><text class="terminal-2926696453-r1" x="585.6" y="483.6" textLength="109.8" clip-path="url(#terminal-2926696453-line-19)">default: </text><text class="terminal-2926696453-r4" x="695.4" y="483.6" textLength="170.8" clip-path="url(#terminal-2926696453-line-19)">'CHANGELOG.md'</text><text class="terminal-2926696453-r2" x="866.2" y="483.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-19)">)</text><text class="terminal-2926696453-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-19)"> -</text><text class="terminal-2926696453-r1" x="0" y="508" textLength="500.2" clip-path="url(#terminal-2926696453-line-20)">  --unreleased-version UNRELEASED_VERSION</text><text class="terminal-2926696453-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-2926696453-line-20)"> -</text><text class="terminal-2926696453-r1" x="0" y="532.4" textLength="707.6" clip-path="url(#terminal-2926696453-line-21)">                        set the value for the new version </text><text class="terminal-2926696453-r2" x="707.6" y="532.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-21)">(</text><text class="terminal-2926696453-r1" x="719.8" y="532.4" textLength="207.4" clip-path="url(#terminal-2926696453-line-21)">use the tag value</text><text class="terminal-2926696453-r2" x="927.2" y="532.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-21)">)</text><text class="terminal-2926696453-r1" x="939.4" y="532.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-21)">,</text><text class="terminal-2926696453-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-21)"> -</text><text class="terminal-2926696453-r1" x="0" y="556.8" textLength="622.2" clip-path="url(#terminal-2926696453-line-22)">                        instead of using unreleased</text><text class="terminal-2926696453-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-22)"> -</text><text class="terminal-2926696453-r1" x="0" y="581.2" textLength="939.4" clip-path="url(#terminal-2926696453-line-23)">  --incremental         generates changelog from last created version, useful</text><text class="terminal-2926696453-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-23)"> -</text><text class="terminal-2926696453-r1" x="0" y="605.6" textLength="817.4" clip-path="url(#terminal-2926696453-line-24)">                        if the changelog has been manually modified</text><text class="terminal-2926696453-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-24)"> -</text><text class="terminal-2926696453-r1" x="0" y="630" textLength="280.6" clip-path="url(#terminal-2926696453-line-25)">  --start-rev START_REV</text><text class="terminal-2926696453-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-2926696453-line-25)"> -</text><text class="terminal-2926696453-r1" x="0" y="654.4" textLength="866.2" clip-path="url(#terminal-2926696453-line-26)">                        start rev of the changelog. If not set, it will</text><text class="terminal-2926696453-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-26)"> -</text><text class="terminal-2926696453-r1" x="0" y="678.8" textLength="695.4" clip-path="url(#terminal-2926696453-line-27)">                        generate changelog from the start</text><text class="terminal-2926696453-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-27)"> -</text><text class="terminal-2926696453-r1" x="0" y="703.2" textLength="915" clip-path="url(#terminal-2926696453-line-28)">  --merge-prerelease    collect all changes from prereleases into next non-</text><text class="terminal-2926696453-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-28)"> -</text><text class="terminal-2926696453-r1" x="0" y="727.6" textLength="951.6" clip-path="url(#terminal-2926696453-line-29)">                        prerelease. If not set, it will include prereleases in</text><text class="terminal-2926696453-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-29)"> -</text><text class="terminal-2926696453-r1" x="0" y="752" textLength="451.4" clip-path="url(#terminal-2926696453-line-30)">                        the changelog</text><text class="terminal-2926696453-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-2926696453-line-30)"> -</text><text class="terminal-2926696453-r1" x="0" y="776.4" textLength="231.8" clip-path="url(#terminal-2926696453-line-31)">  --version-scheme </text><text class="terminal-2926696453-r2" x="231.8" y="776.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-31)">{</text><text class="terminal-2926696453-r1" x="244" y="776.4" textLength="256.2" clip-path="url(#terminal-2926696453-line-31)">pep440,semver,semver2</text><text class="terminal-2926696453-r2" x="500.2" y="776.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-31)">}</text><text class="terminal-2926696453-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-31)"> -</text><text class="terminal-2926696453-r1" x="0" y="800.8" textLength="549" clip-path="url(#terminal-2926696453-line-32)">                        choose version scheme</text><text class="terminal-2926696453-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-32)"> -</text><text class="terminal-2926696453-r1" x="0" y="825.2" textLength="427" clip-path="url(#terminal-2926696453-line-33)">  --export-template EXPORT_TEMPLATE</text><text class="terminal-2926696453-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-33)"> -</text><text class="terminal-2926696453-r1" x="0" y="849.6" textLength="927.2" clip-path="url(#terminal-2926696453-line-34)">                        Export the changelog template into this file instead</text><text class="terminal-2926696453-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-34)"> -</text><text class="terminal-2926696453-r1" x="0" y="874" textLength="475.8" clip-path="url(#terminal-2926696453-line-35)">                        of rendering it</text><text class="terminal-2926696453-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-2926696453-line-35)"> -</text><text class="terminal-2926696453-r1" x="0" y="898.4" textLength="305" clip-path="url(#terminal-2926696453-line-36)">  --template, -t TEMPLATE</text><text class="terminal-2926696453-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-36)"> -</text><text class="terminal-2926696453-r1" x="0" y="922.8" textLength="646.6" clip-path="url(#terminal-2926696453-line-37)">                        changelog template file name </text><text class="terminal-2926696453-r2" x="646.6" y="922.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-37)">(</text><text class="terminal-2926696453-r1" x="658.8" y="922.8" textLength="280.6" clip-path="url(#terminal-2926696453-line-37)">relative to the current</text><text class="terminal-2926696453-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-37)"> -</text><text class="terminal-2926696453-r1" x="0" y="947.2" textLength="500.2" clip-path="url(#terminal-2926696453-line-38)">                        working directory</text><text class="terminal-2926696453-r2" x="500.2" y="947.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-38)">)</text><text class="terminal-2926696453-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-2926696453-line-38)"> -</text><text class="terminal-2926696453-r1" x="0" y="971.6" textLength="622.2" clip-path="url(#terminal-2926696453-line-39)">  --extra, -e EXTRA     a changelog extra variable </text><text class="terminal-2926696453-r2" x="622.2" y="971.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-39)">(</text><text class="terminal-2926696453-r1" x="634.4" y="971.6" textLength="146.4" clip-path="url(#terminal-2926696453-line-39)">in the form </text><text class="terminal-2926696453-r4" x="780.8" y="971.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-39)">'</text><text class="terminal-2926696453-r4" x="793" y="971.6" textLength="36.6" clip-path="url(#terminal-2926696453-line-39)">key</text><text class="terminal-2926696453-r4" x="829.6" y="971.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-39)">=</text><text class="terminal-2926696453-r4" x="841.8" y="971.6" textLength="61" clip-path="url(#terminal-2926696453-line-39)">value</text><text class="terminal-2926696453-r4" x="902.8" y="971.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-39)">'</text><text class="terminal-2926696453-r2" x="915" y="971.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-39)">)</text><text class="terminal-2926696453-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-2926696453-line-39)"> -</text><text class="terminal-2926696453-r1" x="0" y="996" textLength="305" clip-path="url(#terminal-2926696453-line-40)">  --tag-format TAG_FORMAT</text><text class="terminal-2926696453-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-2926696453-line-40)"> -</text><text class="terminal-2926696453-r1" x="0" y="1020.4" textLength="878.4" clip-path="url(#terminal-2926696453-line-41)">                        The format of the tag, wrap around simple quotes</text><text class="terminal-2926696453-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-2926696453-line-41)"> -</text><text class="terminal-2926696453-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-2926696453-line-42)"> + <g class="terminal-192800993-matrix"> + <text class="terminal-192800993-r1" x="0" y="20" textLength="256.2" clip-path="url(#terminal-192800993-line-0)">$ cz changelog --help</text><text class="terminal-192800993-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-192800993-line-0)"> +</text><text class="terminal-192800993-r1" x="0" y="44.4" textLength="244" clip-path="url(#terminal-192800993-line-1)">usage: cz changelog </text><text class="terminal-192800993-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">[</text><text class="terminal-192800993-r1" x="256.2" y="44.4" textLength="24.4" clip-path="url(#terminal-192800993-line-1)">-h</text><text class="terminal-192800993-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">]</text><text class="terminal-192800993-r2" x="305" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">[</text><text class="terminal-192800993-r1" x="317.2" y="44.4" textLength="109.8" clip-path="url(#terminal-192800993-line-1)">--dry-run</text><text class="terminal-192800993-r2" x="427" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">]</text><text class="terminal-192800993-r2" x="451.4" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">[</text><text class="terminal-192800993-r1" x="463.6" y="44.4" textLength="256.2" clip-path="url(#terminal-192800993-line-1)">--file-name FILE_NAME</text><text class="terminal-192800993-r2" x="719.8" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">]</text><text class="terminal-192800993-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)"> +</text><text class="terminal-192800993-r2" x="244" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">[</text><text class="terminal-192800993-r1" x="256.2" y="68.8" textLength="475.8" clip-path="url(#terminal-192800993-line-2)">--unreleased-version UNRELEASED_VERSION</text><text class="terminal-192800993-r2" x="732" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">]</text><text class="terminal-192800993-r2" x="756.4" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">[</text><text class="terminal-192800993-r1" x="768.6" y="68.8" textLength="158.6" clip-path="url(#terminal-192800993-line-2)">--incremental</text><text class="terminal-192800993-r2" x="927.2" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">]</text><text class="terminal-192800993-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)"> +</text><text class="terminal-192800993-r2" x="244" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">[</text><text class="terminal-192800993-r1" x="256.2" y="93.2" textLength="256.2" clip-path="url(#terminal-192800993-line-3)">--start-rev START_REV</text><text class="terminal-192800993-r2" x="512.4" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">]</text><text class="terminal-192800993-r2" x="536.8" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">[</text><text class="terminal-192800993-r1" x="549" y="93.2" textLength="219.6" clip-path="url(#terminal-192800993-line-3)">--merge-prerelease</text><text class="terminal-192800993-r2" x="768.6" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">]</text><text class="terminal-192800993-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)"> +</text><text class="terminal-192800993-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">[</text><text class="terminal-192800993-r1" x="256.2" y="117.6" textLength="207.4" clip-path="url(#terminal-192800993-line-4)">--version-scheme </text><text class="terminal-192800993-r2" x="463.6" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">{</text><text class="terminal-192800993-r1" x="475.8" y="117.6" textLength="256.2" clip-path="url(#terminal-192800993-line-4)">pep440,semver,semver2</text><text class="terminal-192800993-r2" x="732" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">}</text><text class="terminal-192800993-r2" x="744.2" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">]</text><text class="terminal-192800993-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)"> +</text><text class="terminal-192800993-r2" x="244" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">[</text><text class="terminal-192800993-r1" x="256.2" y="142" textLength="402.6" clip-path="url(#terminal-192800993-line-5)">--export-template EXPORT_TEMPLATE</text><text class="terminal-192800993-r2" x="658.8" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">]</text><text class="terminal-192800993-r2" x="683.2" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">[</text><text class="terminal-192800993-r1" x="695.4" y="142" textLength="231.8" clip-path="url(#terminal-192800993-line-5)">--template TEMPLATE</text><text class="terminal-192800993-r2" x="927.2" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">]</text><text class="terminal-192800993-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)"> +</text><text class="terminal-192800993-r2" x="244" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">[</text><text class="terminal-192800993-r1" x="256.2" y="166.4" textLength="158.6" clip-path="url(#terminal-192800993-line-6)">--extra EXTRA</text><text class="terminal-192800993-r2" x="414.8" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">]</text><text class="terminal-192800993-r2" x="439.2" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">[</text><text class="terminal-192800993-r1" x="451.4" y="166.4" textLength="280.6" clip-path="url(#terminal-192800993-line-6)">--tag-format TAG_FORMAT</text><text class="terminal-192800993-r2" x="732" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">]</text><text class="terminal-192800993-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)"> +</text><text class="terminal-192800993-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-192800993-line-7)"> +</text><text class="terminal-192800993-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-192800993-line-8)"> +</text><text class="terminal-192800993-r1" x="0" y="239.6" textLength="231.8" clip-path="url(#terminal-192800993-line-9)">generate changelog </text><text class="terminal-192800993-r2" x="231.8" y="239.6" textLength="12.2" clip-path="url(#terminal-192800993-line-9)">(</text><text class="terminal-192800993-r1" x="244" y="239.6" textLength="500.2" clip-path="url(#terminal-192800993-line-9)">note that it will overwrite existing file</text><text class="terminal-192800993-r2" x="744.2" y="239.6" textLength="12.2" clip-path="url(#terminal-192800993-line-9)">)</text><text class="terminal-192800993-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-192800993-line-9)"> +</text><text class="terminal-192800993-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-192800993-line-10)"> +</text><text class="terminal-192800993-r1" x="0" y="288.4" textLength="256.2" clip-path="url(#terminal-192800993-line-11)">positional arguments:</text><text class="terminal-192800993-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-192800993-line-11)"> +</text><text class="terminal-192800993-r1" x="0" y="312.8" textLength="805.2" clip-path="url(#terminal-192800993-line-12)">  rev_range             generates changelog for the given version </text><text class="terminal-192800993-r2" x="805.2" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">(</text><text class="terminal-192800993-r1" x="817.4" y="312.8" textLength="61" clip-path="url(#terminal-192800993-line-12)">e.g: </text><text class="terminal-192800993-r3" x="878.4" y="312.8" textLength="36.6" clip-path="url(#terminal-192800993-line-12)">1.5</text><text class="terminal-192800993-r1" x="915" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">.</text><text class="terminal-192800993-r3" x="927.2" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">3</text><text class="terminal-192800993-r2" x="939.4" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">)</text><text class="terminal-192800993-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)"> +</text><text class="terminal-192800993-r1" x="0" y="337.2" textLength="500.2" clip-path="url(#terminal-192800993-line-13)">                        or version range </text><text class="terminal-192800993-r2" x="500.2" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">(</text><text class="terminal-192800993-r1" x="512.4" y="337.2" textLength="61" clip-path="url(#terminal-192800993-line-13)">e.g: </text><text class="terminal-192800993-r3" x="573.4" y="337.2" textLength="36.6" clip-path="url(#terminal-192800993-line-13)">1.5</text><text class="terminal-192800993-r1" x="610" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">.</text><text class="terminal-192800993-r3" x="622.2" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">3</text><text class="terminal-192800993-r1" x="634.4" y="337.2" textLength="24.4" clip-path="url(#terminal-192800993-line-13)">..</text><text class="terminal-192800993-r3" x="658.8" y="337.2" textLength="36.6" clip-path="url(#terminal-192800993-line-13)">1.7</text><text class="terminal-192800993-r1" x="695.4" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">.</text><text class="terminal-192800993-r3" x="707.6" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">9</text><text class="terminal-192800993-r2" x="719.8" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">)</text><text class="terminal-192800993-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)"> +</text><text class="terminal-192800993-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-192800993-line-14)"> +</text><text class="terminal-192800993-r1" x="0" y="386" textLength="97.6" clip-path="url(#terminal-192800993-line-15)">options:</text><text class="terminal-192800993-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-192800993-line-15)"> +</text><text class="terminal-192800993-r1" x="0" y="410.4" textLength="671" clip-path="url(#terminal-192800993-line-16)">  -h, --help            show this help message and exit</text><text class="terminal-192800993-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-192800993-line-16)"> +</text><text class="terminal-192800993-r1" x="0" y="434.8" textLength="585.6" clip-path="url(#terminal-192800993-line-17)">  --dry-run             show changelog to stdout</text><text class="terminal-192800993-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-192800993-line-17)"> +</text><text class="terminal-192800993-r1" x="0" y="459.2" textLength="280.6" clip-path="url(#terminal-192800993-line-18)">  --file-name FILE_NAME</text><text class="terminal-192800993-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-192800993-line-18)"> +</text><text class="terminal-192800993-r1" x="0" y="483.6" textLength="573.4" clip-path="url(#terminal-192800993-line-19)">                        file name of changelog </text><text class="terminal-192800993-r2" x="573.4" y="483.6" textLength="12.2" clip-path="url(#terminal-192800993-line-19)">(</text><text class="terminal-192800993-r1" x="585.6" y="483.6" textLength="109.8" clip-path="url(#terminal-192800993-line-19)">default: </text><text class="terminal-192800993-r4" x="695.4" y="483.6" textLength="170.8" clip-path="url(#terminal-192800993-line-19)">'CHANGELOG.md'</text><text class="terminal-192800993-r2" x="866.2" y="483.6" textLength="12.2" clip-path="url(#terminal-192800993-line-19)">)</text><text class="terminal-192800993-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-192800993-line-19)"> +</text><text class="terminal-192800993-r1" x="0" y="508" textLength="500.2" clip-path="url(#terminal-192800993-line-20)">  --unreleased-version UNRELEASED_VERSION</text><text class="terminal-192800993-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-192800993-line-20)"> +</text><text class="terminal-192800993-r1" x="0" y="532.4" textLength="707.6" clip-path="url(#terminal-192800993-line-21)">                        set the value for the new version </text><text class="terminal-192800993-r2" x="707.6" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)">(</text><text class="terminal-192800993-r1" x="719.8" y="532.4" textLength="207.4" clip-path="url(#terminal-192800993-line-21)">use the tag value</text><text class="terminal-192800993-r2" x="927.2" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)">)</text><text class="terminal-192800993-r1" x="939.4" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)">,</text><text class="terminal-192800993-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)"> +</text><text class="terminal-192800993-r1" x="0" y="556.8" textLength="622.2" clip-path="url(#terminal-192800993-line-22)">                        instead of using unreleased</text><text class="terminal-192800993-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-192800993-line-22)"> +</text><text class="terminal-192800993-r1" x="0" y="581.2" textLength="939.4" clip-path="url(#terminal-192800993-line-23)">  --incremental         generates changelog from last created version, useful</text><text class="terminal-192800993-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-192800993-line-23)"> +</text><text class="terminal-192800993-r1" x="0" y="605.6" textLength="817.4" clip-path="url(#terminal-192800993-line-24)">                        if the changelog has been manually modified</text><text class="terminal-192800993-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-192800993-line-24)"> +</text><text class="terminal-192800993-r1" x="0" y="630" textLength="280.6" clip-path="url(#terminal-192800993-line-25)">  --start-rev START_REV</text><text class="terminal-192800993-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-192800993-line-25)"> +</text><text class="terminal-192800993-r1" x="0" y="654.4" textLength="866.2" clip-path="url(#terminal-192800993-line-26)">                        start rev of the changelog. If not set, it will</text><text class="terminal-192800993-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-192800993-line-26)"> +</text><text class="terminal-192800993-r1" x="0" y="678.8" textLength="695.4" clip-path="url(#terminal-192800993-line-27)">                        generate changelog from the start</text><text class="terminal-192800993-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-192800993-line-27)"> +</text><text class="terminal-192800993-r1" x="0" y="703.2" textLength="915" clip-path="url(#terminal-192800993-line-28)">  --merge-prerelease    collect all changes from prereleases into next non-</text><text class="terminal-192800993-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-192800993-line-28)"> +</text><text class="terminal-192800993-r1" x="0" y="727.6" textLength="951.6" clip-path="url(#terminal-192800993-line-29)">                        prerelease. If not set, it will include prereleases in</text><text class="terminal-192800993-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-192800993-line-29)"> +</text><text class="terminal-192800993-r1" x="0" y="752" textLength="451.4" clip-path="url(#terminal-192800993-line-30)">                        the changelog</text><text class="terminal-192800993-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-192800993-line-30)"> +</text><text class="terminal-192800993-r1" x="0" y="776.4" textLength="231.8" clip-path="url(#terminal-192800993-line-31)">  --version-scheme </text><text class="terminal-192800993-r2" x="231.8" y="776.4" textLength="12.2" clip-path="url(#terminal-192800993-line-31)">{</text><text class="terminal-192800993-r1" x="244" y="776.4" textLength="256.2" clip-path="url(#terminal-192800993-line-31)">pep440,semver,semver2</text><text class="terminal-192800993-r2" x="500.2" y="776.4" textLength="12.2" clip-path="url(#terminal-192800993-line-31)">}</text><text class="terminal-192800993-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-192800993-line-31)"> +</text><text class="terminal-192800993-r1" x="0" y="800.8" textLength="549" clip-path="url(#terminal-192800993-line-32)">                        choose version scheme</text><text class="terminal-192800993-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-192800993-line-32)"> +</text><text class="terminal-192800993-r1" x="0" y="825.2" textLength="427" clip-path="url(#terminal-192800993-line-33)">  --export-template EXPORT_TEMPLATE</text><text class="terminal-192800993-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-192800993-line-33)"> +</text><text class="terminal-192800993-r1" x="0" y="849.6" textLength="927.2" clip-path="url(#terminal-192800993-line-34)">                        Export the changelog template into this file instead</text><text class="terminal-192800993-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-192800993-line-34)"> +</text><text class="terminal-192800993-r1" x="0" y="874" textLength="475.8" clip-path="url(#terminal-192800993-line-35)">                        of rendering it</text><text class="terminal-192800993-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-192800993-line-35)"> +</text><text class="terminal-192800993-r1" x="0" y="898.4" textLength="414.8" clip-path="url(#terminal-192800993-line-36)">  --template TEMPLATE, -t TEMPLATE</text><text class="terminal-192800993-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-192800993-line-36)"> +</text><text class="terminal-192800993-r1" x="0" y="922.8" textLength="646.6" clip-path="url(#terminal-192800993-line-37)">                        changelog template file name </text><text class="terminal-192800993-r2" x="646.6" y="922.8" textLength="12.2" clip-path="url(#terminal-192800993-line-37)">(</text><text class="terminal-192800993-r1" x="658.8" y="922.8" textLength="280.6" clip-path="url(#terminal-192800993-line-37)">relative to the current</text><text class="terminal-192800993-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-192800993-line-37)"> +</text><text class="terminal-192800993-r1" x="0" y="947.2" textLength="500.2" clip-path="url(#terminal-192800993-line-38)">                        working directory</text><text class="terminal-192800993-r2" x="500.2" y="947.2" textLength="12.2" clip-path="url(#terminal-192800993-line-38)">)</text><text class="terminal-192800993-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-192800993-line-38)"> +</text><text class="terminal-192800993-r1" x="0" y="971.6" textLength="305" clip-path="url(#terminal-192800993-line-39)">  --extra EXTRA, -e EXTRA</text><text class="terminal-192800993-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-192800993-line-39)"> +</text><text class="terminal-192800993-r1" x="0" y="996" textLength="622.2" clip-path="url(#terminal-192800993-line-40)">                        a changelog extra variable </text><text class="terminal-192800993-r2" x="622.2" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">(</text><text class="terminal-192800993-r1" x="634.4" y="996" textLength="146.4" clip-path="url(#terminal-192800993-line-40)">in the form </text><text class="terminal-192800993-r4" x="780.8" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">'</text><text class="terminal-192800993-r4" x="793" y="996" textLength="36.6" clip-path="url(#terminal-192800993-line-40)">key</text><text class="terminal-192800993-r4" x="829.6" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">=</text><text class="terminal-192800993-r4" x="841.8" y="996" textLength="61" clip-path="url(#terminal-192800993-line-40)">value</text><text class="terminal-192800993-r4" x="902.8" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">'</text><text class="terminal-192800993-r2" x="915" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">)</text><text class="terminal-192800993-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)"> +</text><text class="terminal-192800993-r1" x="0" y="1020.4" textLength="305" clip-path="url(#terminal-192800993-line-41)">  --tag-format TAG_FORMAT</text><text class="terminal-192800993-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-192800993-line-41)"> +</text><text class="terminal-192800993-r1" x="0" y="1044.8" textLength="878.4" clip-path="url(#terminal-192800993-line-42)">                        The format of the tag, wrap around simple quotes</text><text class="terminal-192800993-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-192800993-line-42)"> +</text><text class="terminal-192800993-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-192800993-line-43)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_check___help.svg b/docs/images/cli_help/cz_check___help.svg index 397c0a2eeb..0ced75f60a 100644 --- a/docs/images/cli_help/cz_check___help.svg +++ b/docs/images/cli_help/cz_check___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 782.0" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 806.4" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,158 +19,162 @@ font-weight: 700; } - .terminal-2151679122-matrix { + .terminal-3805463-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2151679122-title { + .terminal-3805463-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2151679122-r1 { fill: #c5c8c6 } -.terminal-2151679122-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-2151679122-r3 { fill: #d0b344 } -.terminal-2151679122-r4 { fill: #68a0b3;font-weight: bold } + .terminal-3805463-r1 { fill: #c5c8c6 } +.terminal-3805463-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-3805463-r3 { fill: #d0b344 } +.terminal-3805463-r4 { fill: #68a0b3;font-weight: bold } </style> <defs> - <clipPath id="terminal-2151679122-clip-terminal"> - <rect x="0" y="0" width="975.0" height="731.0" /> + <clipPath id="terminal-3805463-clip-terminal"> + <rect x="0" y="0" width="975.0" height="755.4" /> </clipPath> - <clipPath id="terminal-2151679122-line-0"> + <clipPath id="terminal-3805463-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-1"> +<clipPath id="terminal-3805463-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-2"> +<clipPath id="terminal-3805463-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-3"> +<clipPath id="terminal-3805463-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-4"> +<clipPath id="terminal-3805463-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-5"> +<clipPath id="terminal-3805463-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-6"> +<clipPath id="terminal-3805463-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-7"> +<clipPath id="terminal-3805463-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-8"> +<clipPath id="terminal-3805463-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-9"> +<clipPath id="terminal-3805463-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-10"> +<clipPath id="terminal-3805463-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-11"> +<clipPath id="terminal-3805463-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-12"> +<clipPath id="terminal-3805463-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-13"> +<clipPath id="terminal-3805463-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-14"> +<clipPath id="terminal-3805463-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-15"> +<clipPath id="terminal-3805463-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-16"> +<clipPath id="terminal-3805463-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-17"> +<clipPath id="terminal-3805463-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-18"> +<clipPath id="terminal-3805463-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-19"> +<clipPath id="terminal-3805463-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-20"> +<clipPath id="terminal-3805463-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-21"> +<clipPath id="terminal-3805463-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-22"> +<clipPath id="terminal-3805463-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-23"> +<clipPath id="terminal-3805463-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-24"> +<clipPath id="terminal-3805463-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-25"> +<clipPath id="terminal-3805463-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-26"> +<clipPath id="terminal-3805463-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-27"> +<clipPath id="terminal-3805463-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-2151679122-line-28"> +<clipPath id="terminal-3805463-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-3805463-line-29"> + <rect x="0" y="709.1" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="780" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="804.4" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-2151679122-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-3805463-clip-terminal)"> - <g class="terminal-2151679122-matrix"> - <text class="terminal-2151679122-r1" x="0" y="20" textLength="207.4" clip-path="url(#terminal-2151679122-line-0)">$ cz check --help</text><text class="terminal-2151679122-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-2151679122-line-0)"> -</text><text class="terminal-2151679122-r1" x="0" y="44.4" textLength="195.2" clip-path="url(#terminal-2151679122-line-1)">usage: cz check </text><text class="terminal-2151679122-r2" x="195.2" y="44.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-1)">[</text><text class="terminal-2151679122-r1" x="207.4" y="44.4" textLength="24.4" clip-path="url(#terminal-2151679122-line-1)">-h</text><text class="terminal-2151679122-r2" x="231.8" y="44.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-1)">]</text><text class="terminal-2151679122-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-1)">[</text><text class="terminal-2151679122-r1" x="268.4" y="44.4" textLength="427" clip-path="url(#terminal-2151679122-line-1)">--commit-msg-file COMMIT_MSG_FILE |</text><text class="terminal-2151679122-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-1)"> -</text><text class="terminal-2151679122-r1" x="0" y="68.8" textLength="671" clip-path="url(#terminal-2151679122-line-2)">                --rev-range REV_RANGE | -d | -m MESSAGE</text><text class="terminal-2151679122-r2" x="671" y="68.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-2)">]</text><text class="terminal-2151679122-r2" x="695.4" y="68.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-2)">[</text><text class="terminal-2151679122-r1" x="707.6" y="68.8" textLength="158.6" clip-path="url(#terminal-2151679122-line-2)">--allow-abort</text><text class="terminal-2151679122-r2" x="866.2" y="68.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-2)">]</text><text class="terminal-2151679122-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-2)"> -</text><text class="terminal-2151679122-r2" x="195.2" y="93.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-3)">[</text><text class="terminal-2151679122-r1" x="207.4" y="93.2" textLength="231.8" clip-path="url(#terminal-2151679122-line-3)">--allowed-prefixes </text><text class="terminal-2151679122-r2" x="439.2" y="93.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-3)">[</text><text class="terminal-2151679122-r1" x="451.4" y="93.2" textLength="207.4" clip-path="url(#terminal-2151679122-line-3)">ALLOWED_PREFIXES </text><text class="terminal-2151679122-r3" x="658.8" y="93.2" textLength="36.6" clip-path="url(#terminal-2151679122-line-3)">...</text><text class="terminal-2151679122-r2" x="695.4" y="93.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-3)">]</text><text class="terminal-2151679122-r2" x="707.6" y="93.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-3)">]</text><text class="terminal-2151679122-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-3)"> -</text><text class="terminal-2151679122-r2" x="195.2" y="117.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-4)">[</text><text class="terminal-2151679122-r1" x="207.4" y="117.6" textLength="280.6" clip-path="url(#terminal-2151679122-line-4)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-2151679122-r2" x="488" y="117.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-4)">]</text><text class="terminal-2151679122-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-4)"> -</text><text class="terminal-2151679122-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-2151679122-line-5)"> -</text><text class="terminal-2151679122-r1" x="0" y="166.4" textLength="744.2" clip-path="url(#terminal-2151679122-line-6)">validates that a commit message matches the commitizen schema</text><text class="terminal-2151679122-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-6)"> -</text><text class="terminal-2151679122-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-7)"> -</text><text class="terminal-2151679122-r1" x="0" y="215.2" textLength="97.6" clip-path="url(#terminal-2151679122-line-8)">options:</text><text class="terminal-2151679122-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-8)"> -</text><text class="terminal-2151679122-r1" x="0" y="239.6" textLength="671" clip-path="url(#terminal-2151679122-line-9)">  -h, --help            show this help message and exit</text><text class="terminal-2151679122-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-9)"> -</text><text class="terminal-2151679122-r1" x="0" y="264" textLength="427" clip-path="url(#terminal-2151679122-line-10)">  --commit-msg-file COMMIT_MSG_FILE</text><text class="terminal-2151679122-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-2151679122-line-10)"> -</text><text class="terminal-2151679122-r1" x="0" y="288.4" textLength="915" clip-path="url(#terminal-2151679122-line-11)">                        ask for the name of the temporal file that contains</text><text class="terminal-2151679122-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-11)"> -</text><text class="terminal-2151679122-r1" x="0" y="312.8" textLength="902.8" clip-path="url(#terminal-2151679122-line-12)">                        the commit message. Using it in a git hook script:</text><text class="terminal-2151679122-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-12)"> -</text><text class="terminal-2151679122-r3" x="292.8" y="337.2" textLength="97.6" clip-path="url(#terminal-2151679122-line-13)">MSG_FILE</text><text class="terminal-2151679122-r1" x="390.4" y="337.2" textLength="24.4" clip-path="url(#terminal-2151679122-line-13)">=$</text><text class="terminal-2151679122-r4" x="414.8" y="337.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-13)">1</text><text class="terminal-2151679122-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-13)"> -</text><text class="terminal-2151679122-r1" x="0" y="361.6" textLength="280.6" clip-path="url(#terminal-2151679122-line-14)">  --rev-range REV_RANGE</text><text class="terminal-2151679122-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-14)"> -</text><text class="terminal-2151679122-r1" x="0" y="386" textLength="854" clip-path="url(#terminal-2151679122-line-15)">                        a range of git rev to check. e.g, master..HEAD</text><text class="terminal-2151679122-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-2151679122-line-15)"> -</text><text class="terminal-2151679122-r1" x="0" y="410.4" textLength="305" clip-path="url(#terminal-2151679122-line-16)">  -d, --use-default-range</text><text class="terminal-2151679122-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-16)"> -</text><text class="terminal-2151679122-r1" x="0" y="434.8" textLength="817.4" clip-path="url(#terminal-2151679122-line-17)">                        check from the default branch to HEAD. e.g,</text><text class="terminal-2151679122-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-17)"> -</text><text class="terminal-2151679122-r1" x="0" y="459.2" textLength="683.2" clip-path="url(#terminal-2151679122-line-18)">                        refs/remotes/origin/master..HEAD</text><text class="terminal-2151679122-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-18)"> -</text><text class="terminal-2151679122-r1" x="0" y="483.6" textLength="280.6" clip-path="url(#terminal-2151679122-line-19)">  -m, --message MESSAGE</text><text class="terminal-2151679122-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-19)"> -</text><text class="terminal-2151679122-r1" x="0" y="508" textLength="768.6" clip-path="url(#terminal-2151679122-line-20)">                        commit message that needs to be checked</text><text class="terminal-2151679122-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-2151679122-line-20)"> -</text><text class="terminal-2151679122-r1" x="0" y="532.4" textLength="927.2" clip-path="url(#terminal-2151679122-line-21)">  --allow-abort         allow empty commit messages, which typically abort a</text><text class="terminal-2151679122-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-21)"> -</text><text class="terminal-2151679122-r1" x="0" y="556.8" textLength="366" clip-path="url(#terminal-2151679122-line-22)">                        commit</text><text class="terminal-2151679122-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-22)"> -</text><text class="terminal-2151679122-r1" x="0" y="581.2" textLength="256.2" clip-path="url(#terminal-2151679122-line-23)">  --allowed-prefixes </text><text class="terminal-2151679122-r2" x="256.2" y="581.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-23)">[</text><text class="terminal-2151679122-r1" x="268.4" y="581.2" textLength="207.4" clip-path="url(#terminal-2151679122-line-23)">ALLOWED_PREFIXES </text><text class="terminal-2151679122-r3" x="475.8" y="581.2" textLength="36.6" clip-path="url(#terminal-2151679122-line-23)">...</text><text class="terminal-2151679122-r2" x="512.4" y="581.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-23)">]</text><text class="terminal-2151679122-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-23)"> -</text><text class="terminal-2151679122-r1" x="0" y="605.6" textLength="951.6" clip-path="url(#terminal-2151679122-line-24)">                        allowed commit message prefixes. If the message starts</text><text class="terminal-2151679122-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-24)"> -</text><text class="terminal-2151679122-r1" x="0" y="630" textLength="951.6" clip-path="url(#terminal-2151679122-line-25)">                        by one of these prefixes, the message won't be checked</text><text class="terminal-2151679122-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-2151679122-line-25)"> -</text><text class="terminal-2151679122-r1" x="0" y="654.4" textLength="500.2" clip-path="url(#terminal-2151679122-line-26)">                        against the regex</text><text class="terminal-2151679122-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-2151679122-line-26)"> -</text><text class="terminal-2151679122-r1" x="0" y="678.8" textLength="597.8" clip-path="url(#terminal-2151679122-line-27)">  -l, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-2151679122-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-2151679122-line-27)"> -</text><text class="terminal-2151679122-r1" x="0" y="703.2" textLength="732" clip-path="url(#terminal-2151679122-line-28)">                        length limit of the commit message; </text><text class="terminal-2151679122-r4" x="732" y="703.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-28)">0</text><text class="terminal-2151679122-r1" x="744.2" y="703.2" textLength="158.6" clip-path="url(#terminal-2151679122-line-28)"> for no limit</text><text class="terminal-2151679122-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-2151679122-line-28)"> -</text><text class="terminal-2151679122-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-2151679122-line-29)"> + <g class="terminal-3805463-matrix"> + <text class="terminal-3805463-r1" x="0" y="20" textLength="207.4" clip-path="url(#terminal-3805463-line-0)">$ cz check --help</text><text class="terminal-3805463-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-3805463-line-0)"> +</text><text class="terminal-3805463-r1" x="0" y="44.4" textLength="195.2" clip-path="url(#terminal-3805463-line-1)">usage: cz check </text><text class="terminal-3805463-r2" x="195.2" y="44.4" textLength="12.2" clip-path="url(#terminal-3805463-line-1)">[</text><text class="terminal-3805463-r1" x="207.4" y="44.4" textLength="24.4" clip-path="url(#terminal-3805463-line-1)">-h</text><text class="terminal-3805463-r2" x="231.8" y="44.4" textLength="12.2" clip-path="url(#terminal-3805463-line-1)">]</text><text class="terminal-3805463-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-3805463-line-1)"> +</text><text class="terminal-3805463-r2" x="195.2" y="68.8" textLength="12.2" clip-path="url(#terminal-3805463-line-2)">[</text><text class="terminal-3805463-r1" x="207.4" y="68.8" textLength="768.6" clip-path="url(#terminal-3805463-line-2)">--commit-msg-file COMMIT_MSG_FILE | --rev-range REV_RANGE | -d </text><text class="terminal-3805463-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-3805463-line-2)"> +</text><text class="terminal-3805463-r1" x="0" y="93.2" textLength="146.4" clip-path="url(#terminal-3805463-line-3)">| -m MESSAGE</text><text class="terminal-3805463-r2" x="146.4" y="93.2" textLength="12.2" clip-path="url(#terminal-3805463-line-3)">]</text><text class="terminal-3805463-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-3805463-line-3)"> +</text><text class="terminal-3805463-r2" x="195.2" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">[</text><text class="terminal-3805463-r1" x="207.4" y="117.6" textLength="158.6" clip-path="url(#terminal-3805463-line-4)">--allow-abort</text><text class="terminal-3805463-r2" x="366" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">]</text><text class="terminal-3805463-r2" x="390.4" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">[</text><text class="terminal-3805463-r1" x="402.6" y="117.6" textLength="231.8" clip-path="url(#terminal-3805463-line-4)">--allowed-prefixes </text><text class="terminal-3805463-r2" x="634.4" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">[</text><text class="terminal-3805463-r1" x="646.6" y="117.6" textLength="207.4" clip-path="url(#terminal-3805463-line-4)">ALLOWED_PREFIXES </text><text class="terminal-3805463-r3" x="854" y="117.6" textLength="36.6" clip-path="url(#terminal-3805463-line-4)">...</text><text class="terminal-3805463-r2" x="890.6" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">]</text><text class="terminal-3805463-r2" x="902.8" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">]</text><text class="terminal-3805463-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)"> +</text><text class="terminal-3805463-r2" x="195.2" y="142" textLength="12.2" clip-path="url(#terminal-3805463-line-5)">[</text><text class="terminal-3805463-r1" x="207.4" y="142" textLength="280.6" clip-path="url(#terminal-3805463-line-5)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-3805463-r2" x="488" y="142" textLength="12.2" clip-path="url(#terminal-3805463-line-5)">]</text><text class="terminal-3805463-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-3805463-line-5)"> +</text><text class="terminal-3805463-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-3805463-line-6)"> +</text><text class="terminal-3805463-r1" x="0" y="190.8" textLength="744.2" clip-path="url(#terminal-3805463-line-7)">validates that a commit message matches the commitizen schema</text><text class="terminal-3805463-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-3805463-line-7)"> +</text><text class="terminal-3805463-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-3805463-line-8)"> +</text><text class="terminal-3805463-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-3805463-line-9)">options:</text><text class="terminal-3805463-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-3805463-line-9)"> +</text><text class="terminal-3805463-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-3805463-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-3805463-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-3805463-line-10)"> +</text><text class="terminal-3805463-r1" x="0" y="288.4" textLength="427" clip-path="url(#terminal-3805463-line-11)">  --commit-msg-file COMMIT_MSG_FILE</text><text class="terminal-3805463-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-3805463-line-11)"> +</text><text class="terminal-3805463-r1" x="0" y="312.8" textLength="915" clip-path="url(#terminal-3805463-line-12)">                        ask for the name of the temporal file that contains</text><text class="terminal-3805463-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-3805463-line-12)"> +</text><text class="terminal-3805463-r1" x="0" y="337.2" textLength="902.8" clip-path="url(#terminal-3805463-line-13)">                        the commit message. Using it in a git hook script:</text><text class="terminal-3805463-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-3805463-line-13)"> +</text><text class="terminal-3805463-r3" x="292.8" y="361.6" textLength="97.6" clip-path="url(#terminal-3805463-line-14)">MSG_FILE</text><text class="terminal-3805463-r1" x="390.4" y="361.6" textLength="24.4" clip-path="url(#terminal-3805463-line-14)">=$</text><text class="terminal-3805463-r4" x="414.8" y="361.6" textLength="12.2" clip-path="url(#terminal-3805463-line-14)">1</text><text class="terminal-3805463-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-3805463-line-14)"> +</text><text class="terminal-3805463-r1" x="0" y="386" textLength="280.6" clip-path="url(#terminal-3805463-line-15)">  --rev-range REV_RANGE</text><text class="terminal-3805463-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-3805463-line-15)"> +</text><text class="terminal-3805463-r1" x="0" y="410.4" textLength="854" clip-path="url(#terminal-3805463-line-16)">                        a range of git rev to check. e.g, master..HEAD</text><text class="terminal-3805463-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-3805463-line-16)"> +</text><text class="terminal-3805463-r1" x="0" y="434.8" textLength="305" clip-path="url(#terminal-3805463-line-17)">  -d, --use-default-range</text><text class="terminal-3805463-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-3805463-line-17)"> +</text><text class="terminal-3805463-r1" x="0" y="459.2" textLength="817.4" clip-path="url(#terminal-3805463-line-18)">                        check from the default branch to HEAD. e.g,</text><text class="terminal-3805463-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-3805463-line-18)"> +</text><text class="terminal-3805463-r1" x="0" y="483.6" textLength="683.2" clip-path="url(#terminal-3805463-line-19)">                        refs/remotes/origin/master..HEAD</text><text class="terminal-3805463-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-3805463-line-19)"> +</text><text class="terminal-3805463-r1" x="0" y="508" textLength="378.2" clip-path="url(#terminal-3805463-line-20)">  -m MESSAGE, --message MESSAGE</text><text class="terminal-3805463-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-3805463-line-20)"> +</text><text class="terminal-3805463-r1" x="0" y="532.4" textLength="768.6" clip-path="url(#terminal-3805463-line-21)">                        commit message that needs to be checked</text><text class="terminal-3805463-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-3805463-line-21)"> +</text><text class="terminal-3805463-r1" x="0" y="556.8" textLength="927.2" clip-path="url(#terminal-3805463-line-22)">  --allow-abort         allow empty commit messages, which typically abort a</text><text class="terminal-3805463-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-3805463-line-22)"> +</text><text class="terminal-3805463-r1" x="0" y="581.2" textLength="366" clip-path="url(#terminal-3805463-line-23)">                        commit</text><text class="terminal-3805463-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-3805463-line-23)"> +</text><text class="terminal-3805463-r1" x="0" y="605.6" textLength="256.2" clip-path="url(#terminal-3805463-line-24)">  --allowed-prefixes </text><text class="terminal-3805463-r2" x="256.2" y="605.6" textLength="12.2" clip-path="url(#terminal-3805463-line-24)">[</text><text class="terminal-3805463-r1" x="268.4" y="605.6" textLength="207.4" clip-path="url(#terminal-3805463-line-24)">ALLOWED_PREFIXES </text><text class="terminal-3805463-r3" x="475.8" y="605.6" textLength="36.6" clip-path="url(#terminal-3805463-line-24)">...</text><text class="terminal-3805463-r2" x="512.4" y="605.6" textLength="12.2" clip-path="url(#terminal-3805463-line-24)">]</text><text class="terminal-3805463-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-3805463-line-24)"> +</text><text class="terminal-3805463-r1" x="0" y="630" textLength="951.6" clip-path="url(#terminal-3805463-line-25)">                        allowed commit message prefixes. If the message starts</text><text class="terminal-3805463-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-3805463-line-25)"> +</text><text class="terminal-3805463-r1" x="0" y="654.4" textLength="951.6" clip-path="url(#terminal-3805463-line-26)">                        by one of these prefixes, the message won't be checked</text><text class="terminal-3805463-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-3805463-line-26)"> +</text><text class="terminal-3805463-r1" x="0" y="678.8" textLength="500.2" clip-path="url(#terminal-3805463-line-27)">                        against the regex</text><text class="terminal-3805463-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-3805463-line-27)"> +</text><text class="terminal-3805463-r1" x="0" y="703.2" textLength="854" clip-path="url(#terminal-3805463-line-28)">  -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-3805463-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-3805463-line-28)"> +</text><text class="terminal-3805463-r1" x="0" y="727.6" textLength="732" clip-path="url(#terminal-3805463-line-29)">                        length limit of the commit message; </text><text class="terminal-3805463-r4" x="732" y="727.6" textLength="12.2" clip-path="url(#terminal-3805463-line-29)">0</text><text class="terminal-3805463-r1" x="744.2" y="727.6" textLength="158.6" clip-path="url(#terminal-3805463-line-29)"> for no limit</text><text class="terminal-3805463-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-3805463-line-29)"> +</text><text class="terminal-3805463-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-3805463-line-30)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_commit___help.svg b/docs/images/cli_help/cz_commit___help.svg index 59cdd12b9b..9b68844b57 100644 --- a/docs/images/cli_help/cz_commit___help.svg +++ b/docs/images/cli_help/cz_commit___help.svg @@ -19,96 +19,96 @@ font-weight: 700; } - .terminal-905765158-matrix { + .terminal-650700618-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-905765158-title { + .terminal-650700618-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-905765158-r1 { fill: #c5c8c6 } -.terminal-905765158-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-905765158-r3 { fill: #98a84b } -.terminal-905765158-r4 { fill: #68a0b3;font-weight: bold } + .terminal-650700618-r1 { fill: #c5c8c6 } +.terminal-650700618-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-650700618-r3 { fill: #98a84b } +.terminal-650700618-r4 { fill: #68a0b3;font-weight: bold } </style> <defs> - <clipPath id="terminal-905765158-clip-terminal"> + <clipPath id="terminal-650700618-clip-terminal"> <rect x="0" y="0" width="975.0" height="584.5999999999999" /> </clipPath> - <clipPath id="terminal-905765158-line-0"> + <clipPath id="terminal-650700618-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-1"> +<clipPath id="terminal-650700618-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-2"> +<clipPath id="terminal-650700618-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-3"> +<clipPath id="terminal-650700618-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-4"> +<clipPath id="terminal-650700618-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-5"> +<clipPath id="terminal-650700618-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-6"> +<clipPath id="terminal-650700618-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-7"> +<clipPath id="terminal-650700618-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-8"> +<clipPath id="terminal-650700618-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-9"> +<clipPath id="terminal-650700618-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-10"> +<clipPath id="terminal-650700618-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-11"> +<clipPath id="terminal-650700618-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-12"> +<clipPath id="terminal-650700618-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-13"> +<clipPath id="terminal-650700618-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-14"> +<clipPath id="terminal-650700618-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-15"> +<clipPath id="terminal-650700618-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-16"> +<clipPath id="terminal-650700618-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-17"> +<clipPath id="terminal-650700618-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-18"> +<clipPath id="terminal-650700618-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-19"> +<clipPath id="terminal-650700618-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-20"> +<clipPath id="terminal-650700618-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-21"> +<clipPath id="terminal-650700618-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-905765158-line-22"> +<clipPath id="terminal-650700618-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> </defs> @@ -120,33 +120,33 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-905765158-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-650700618-clip-terminal)"> - <g class="terminal-905765158-matrix"> - <text class="terminal-905765158-r1" x="0" y="20" textLength="219.6" clip-path="url(#terminal-905765158-line-0)">$ cz commit --help</text><text class="terminal-905765158-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-905765158-line-0)"> -</text><text class="terminal-905765158-r1" x="0" y="44.4" textLength="207.4" clip-path="url(#terminal-905765158-line-1)">usage: cz commit </text><text class="terminal-905765158-r2" x="207.4" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">[</text><text class="terminal-905765158-r1" x="219.6" y="44.4" textLength="24.4" clip-path="url(#terminal-905765158-line-1)">-h</text><text class="terminal-905765158-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">]</text><text class="terminal-905765158-r2" x="268.4" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">[</text><text class="terminal-905765158-r1" x="280.6" y="44.4" textLength="85.4" clip-path="url(#terminal-905765158-line-1)">--retry</text><text class="terminal-905765158-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">]</text><text class="terminal-905765158-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">[</text><text class="terminal-905765158-r1" x="402.6" y="44.4" textLength="122" clip-path="url(#terminal-905765158-line-1)">--no-retry</text><text class="terminal-905765158-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">]</text><text class="terminal-905765158-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">[</text><text class="terminal-905765158-r1" x="561.2" y="44.4" textLength="109.8" clip-path="url(#terminal-905765158-line-1)">--dry-run</text><text class="terminal-905765158-r2" x="671" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)">]</text><text class="terminal-905765158-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-905765158-line-1)"> -</text><text class="terminal-905765158-r2" x="207.4" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">[</text><text class="terminal-905765158-r1" x="219.6" y="68.8" textLength="402.6" clip-path="url(#terminal-905765158-line-2)">--write-message-to-file FILE_PATH</text><text class="terminal-905765158-r2" x="622.2" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">]</text><text class="terminal-905765158-r2" x="646.6" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">[</text><text class="terminal-905765158-r1" x="658.8" y="68.8" textLength="24.4" clip-path="url(#terminal-905765158-line-2)">-s</text><text class="terminal-905765158-r2" x="683.2" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">]</text><text class="terminal-905765158-r2" x="707.6" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">[</text><text class="terminal-905765158-r1" x="719.8" y="68.8" textLength="24.4" clip-path="url(#terminal-905765158-line-2)">-a</text><text class="terminal-905765158-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">]</text><text class="terminal-905765158-r2" x="768.6" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">[</text><text class="terminal-905765158-r1" x="780.8" y="68.8" textLength="24.4" clip-path="url(#terminal-905765158-line-2)">-e</text><text class="terminal-905765158-r2" x="805.2" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)">]</text><text class="terminal-905765158-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-905765158-line-2)"> -</text><text class="terminal-905765158-r2" x="207.4" y="93.2" textLength="12.2" clip-path="url(#terminal-905765158-line-3)">[</text><text class="terminal-905765158-r1" x="219.6" y="93.2" textLength="280.6" clip-path="url(#terminal-905765158-line-3)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-905765158-r2" x="500.2" y="93.2" textLength="12.2" clip-path="url(#terminal-905765158-line-3)">]</text><text class="terminal-905765158-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-905765158-line-3)">[</text><text class="terminal-905765158-r1" x="536.8" y="93.2" textLength="24.4" clip-path="url(#terminal-905765158-line-3)">--</text><text class="terminal-905765158-r2" x="561.2" y="93.2" textLength="12.2" clip-path="url(#terminal-905765158-line-3)">]</text><text class="terminal-905765158-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-905765158-line-3)"> -</text><text class="terminal-905765158-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-905765158-line-4)"> -</text><text class="terminal-905765158-r1" x="0" y="142" textLength="207.4" clip-path="url(#terminal-905765158-line-5)">create new commit</text><text class="terminal-905765158-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-905765158-line-5)"> -</text><text class="terminal-905765158-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-905765158-line-6)"> -</text><text class="terminal-905765158-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-905765158-line-7)">options:</text><text class="terminal-905765158-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-905765158-line-7)"> -</text><text class="terminal-905765158-r1" x="0" y="215.2" textLength="671" clip-path="url(#terminal-905765158-line-8)">  -h, --help            show this help message and exit</text><text class="terminal-905765158-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-905765158-line-8)"> -</text><text class="terminal-905765158-r1" x="0" y="239.6" textLength="500.2" clip-path="url(#terminal-905765158-line-9)">  --retry               retry last commit</text><text class="terminal-905765158-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-905765158-line-9)"> -</text><text class="terminal-905765158-r1" x="0" y="264" textLength="878.4" clip-path="url(#terminal-905765158-line-10)">  --no-retry            skip retry if retry_after_failure is set to true</text><text class="terminal-905765158-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-905765158-line-10)"> -</text><text class="terminal-905765158-r1" x="0" y="288.4" textLength="915" clip-path="url(#terminal-905765158-line-11)">  --dry-run             show output to stdout, no commit, no modified files</text><text class="terminal-905765158-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-905765158-line-11)"> -</text><text class="terminal-905765158-r1" x="0" y="312.8" textLength="427" clip-path="url(#terminal-905765158-line-12)">  --write-message-to-file FILE_PATH</text><text class="terminal-905765158-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-905765158-line-12)"> -</text><text class="terminal-905765158-r1" x="0" y="337.2" textLength="780.8" clip-path="url(#terminal-905765158-line-13)">                        write message to file before committing </text><text class="terminal-905765158-r2" x="780.8" y="337.2" textLength="12.2" clip-path="url(#terminal-905765158-line-13)">(</text><text class="terminal-905765158-r1" x="793" y="337.2" textLength="73.2" clip-path="url(#terminal-905765158-line-13)">can be</text><text class="terminal-905765158-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-905765158-line-13)"> -</text><text class="terminal-905765158-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-905765158-line-14)">                        combined with --dry-run</text><text class="terminal-905765158-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-905765158-line-14)">)</text><text class="terminal-905765158-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-905765158-line-14)"> -</text><text class="terminal-905765158-r1" x="0" y="386" textLength="488" clip-path="url(#terminal-905765158-line-15)">  -s, --signoff         Deprecated, use </text><text class="terminal-905765158-r3" x="488" y="386" textLength="207.4" clip-path="url(#terminal-905765158-line-15)">'cz commit -- -s'</text><text class="terminal-905765158-r1" x="695.4" y="386" textLength="97.6" clip-path="url(#terminal-905765158-line-15)"> instead</text><text class="terminal-905765158-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-905765158-line-15)"> -</text><text class="terminal-905765158-r1" x="0" y="410.4" textLength="902.8" clip-path="url(#terminal-905765158-line-16)">  -a, --all             Tell the command to automatically stage files that</text><text class="terminal-905765158-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-905765158-line-16)"> -</text><text class="terminal-905765158-r1" x="0" y="434.8" textLength="951.6" clip-path="url(#terminal-905765158-line-17)">                        have been modified and deleted, but new files you have</text><text class="terminal-905765158-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-905765158-line-17)"> -</text><text class="terminal-905765158-r1" x="0" y="459.2" textLength="732" clip-path="url(#terminal-905765158-line-18)">                        not told Git about are not affected.</text><text class="terminal-905765158-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-905765158-line-18)"> -</text><text class="terminal-905765158-r1" x="0" y="483.6" textLength="793" clip-path="url(#terminal-905765158-line-19)">  -e, --edit            edit the commit message before committing</text><text class="terminal-905765158-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-905765158-line-19)"> -</text><text class="terminal-905765158-r1" x="0" y="508" textLength="597.8" clip-path="url(#terminal-905765158-line-20)">  -l, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-905765158-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-905765158-line-20)"> -</text><text class="terminal-905765158-r1" x="0" y="532.4" textLength="732" clip-path="url(#terminal-905765158-line-21)">                        length limit of the commit message; </text><text class="terminal-905765158-r4" x="732" y="532.4" textLength="12.2" clip-path="url(#terminal-905765158-line-21)">0</text><text class="terminal-905765158-r1" x="744.2" y="532.4" textLength="158.6" clip-path="url(#terminal-905765158-line-21)"> for no limit</text><text class="terminal-905765158-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-905765158-line-21)"> -</text><text class="terminal-905765158-r1" x="0" y="556.8" textLength="671" clip-path="url(#terminal-905765158-line-22)">  --                    Positional arguments separator </text><text class="terminal-905765158-r2" x="671" y="556.8" textLength="12.2" clip-path="url(#terminal-905765158-line-22)">(</text><text class="terminal-905765158-r1" x="683.2" y="556.8" textLength="134.2" clip-path="url(#terminal-905765158-line-22)">recommended</text><text class="terminal-905765158-r2" x="817.4" y="556.8" textLength="12.2" clip-path="url(#terminal-905765158-line-22)">)</text><text class="terminal-905765158-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-905765158-line-22)"> -</text><text class="terminal-905765158-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-905765158-line-23)"> + <g class="terminal-650700618-matrix"> + <text class="terminal-650700618-r1" x="0" y="20" textLength="219.6" clip-path="url(#terminal-650700618-line-0)">$ cz commit --help</text><text class="terminal-650700618-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-650700618-line-0)"> +</text><text class="terminal-650700618-r1" x="0" y="44.4" textLength="207.4" clip-path="url(#terminal-650700618-line-1)">usage: cz commit </text><text class="terminal-650700618-r2" x="207.4" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="219.6" y="44.4" textLength="24.4" clip-path="url(#terminal-650700618-line-1)">-h</text><text class="terminal-650700618-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r2" x="268.4" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="280.6" y="44.4" textLength="85.4" clip-path="url(#terminal-650700618-line-1)">--retry</text><text class="terminal-650700618-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="402.6" y="44.4" textLength="122" clip-path="url(#terminal-650700618-line-1)">--no-retry</text><text class="terminal-650700618-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="561.2" y="44.4" textLength="109.8" clip-path="url(#terminal-650700618-line-1)">--dry-run</text><text class="terminal-650700618-r2" x="671" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)"> +</text><text class="terminal-650700618-r2" x="207.4" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="219.6" y="68.8" textLength="402.6" clip-path="url(#terminal-650700618-line-2)">--write-message-to-file FILE_PATH</text><text class="terminal-650700618-r2" x="622.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r2" x="646.6" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="658.8" y="68.8" textLength="24.4" clip-path="url(#terminal-650700618-line-2)">-s</text><text class="terminal-650700618-r2" x="683.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r2" x="707.6" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="719.8" y="68.8" textLength="24.4" clip-path="url(#terminal-650700618-line-2)">-a</text><text class="terminal-650700618-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r2" x="768.6" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="780.8" y="68.8" textLength="24.4" clip-path="url(#terminal-650700618-line-2)">-e</text><text class="terminal-650700618-r2" x="805.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)"> +</text><text class="terminal-650700618-r2" x="207.4" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">[</text><text class="terminal-650700618-r1" x="219.6" y="93.2" textLength="280.6" clip-path="url(#terminal-650700618-line-3)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-650700618-r2" x="500.2" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">]</text><text class="terminal-650700618-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">[</text><text class="terminal-650700618-r1" x="536.8" y="93.2" textLength="24.4" clip-path="url(#terminal-650700618-line-3)">--</text><text class="terminal-650700618-r2" x="561.2" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">]</text><text class="terminal-650700618-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)"> +</text><text class="terminal-650700618-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-650700618-line-4)"> +</text><text class="terminal-650700618-r1" x="0" y="142" textLength="207.4" clip-path="url(#terminal-650700618-line-5)">create new commit</text><text class="terminal-650700618-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-650700618-line-5)"> +</text><text class="terminal-650700618-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-650700618-line-6)"> +</text><text class="terminal-650700618-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-650700618-line-7)">options:</text><text class="terminal-650700618-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-650700618-line-7)"> +</text><text class="terminal-650700618-r1" x="0" y="215.2" textLength="671" clip-path="url(#terminal-650700618-line-8)">  -h, --help            show this help message and exit</text><text class="terminal-650700618-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-650700618-line-8)"> +</text><text class="terminal-650700618-r1" x="0" y="239.6" textLength="500.2" clip-path="url(#terminal-650700618-line-9)">  --retry               retry last commit</text><text class="terminal-650700618-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-650700618-line-9)"> +</text><text class="terminal-650700618-r1" x="0" y="264" textLength="878.4" clip-path="url(#terminal-650700618-line-10)">  --no-retry            skip retry if retry_after_failure is set to true</text><text class="terminal-650700618-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-650700618-line-10)"> +</text><text class="terminal-650700618-r1" x="0" y="288.4" textLength="915" clip-path="url(#terminal-650700618-line-11)">  --dry-run             show output to stdout, no commit, no modified files</text><text class="terminal-650700618-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-650700618-line-11)"> +</text><text class="terminal-650700618-r1" x="0" y="312.8" textLength="427" clip-path="url(#terminal-650700618-line-12)">  --write-message-to-file FILE_PATH</text><text class="terminal-650700618-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-650700618-line-12)"> +</text><text class="terminal-650700618-r1" x="0" y="337.2" textLength="780.8" clip-path="url(#terminal-650700618-line-13)">                        write message to file before committing </text><text class="terminal-650700618-r2" x="780.8" y="337.2" textLength="12.2" clip-path="url(#terminal-650700618-line-13)">(</text><text class="terminal-650700618-r1" x="793" y="337.2" textLength="73.2" clip-path="url(#terminal-650700618-line-13)">can be</text><text class="terminal-650700618-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-650700618-line-13)"> +</text><text class="terminal-650700618-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-650700618-line-14)">                        combined with --dry-run</text><text class="terminal-650700618-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-650700618-line-14)">)</text><text class="terminal-650700618-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-650700618-line-14)"> +</text><text class="terminal-650700618-r1" x="0" y="386" textLength="488" clip-path="url(#terminal-650700618-line-15)">  -s, --signoff         Deprecated, use </text><text class="terminal-650700618-r3" x="488" y="386" textLength="207.4" clip-path="url(#terminal-650700618-line-15)">'cz commit -- -s'</text><text class="terminal-650700618-r1" x="695.4" y="386" textLength="97.6" clip-path="url(#terminal-650700618-line-15)"> instead</text><text class="terminal-650700618-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-650700618-line-15)"> +</text><text class="terminal-650700618-r1" x="0" y="410.4" textLength="902.8" clip-path="url(#terminal-650700618-line-16)">  -a, --all             Tell the command to automatically stage files that</text><text class="terminal-650700618-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-650700618-line-16)"> +</text><text class="terminal-650700618-r1" x="0" y="434.8" textLength="951.6" clip-path="url(#terminal-650700618-line-17)">                        have been modified and deleted, but new files you have</text><text class="terminal-650700618-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-650700618-line-17)"> +</text><text class="terminal-650700618-r1" x="0" y="459.2" textLength="732" clip-path="url(#terminal-650700618-line-18)">                        not told Git about are not affected.</text><text class="terminal-650700618-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-650700618-line-18)"> +</text><text class="terminal-650700618-r1" x="0" y="483.6" textLength="793" clip-path="url(#terminal-650700618-line-19)">  -e, --edit            edit the commit message before committing</text><text class="terminal-650700618-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-650700618-line-19)"> +</text><text class="terminal-650700618-r1" x="0" y="508" textLength="854" clip-path="url(#terminal-650700618-line-20)">  -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-650700618-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-650700618-line-20)"> +</text><text class="terminal-650700618-r1" x="0" y="532.4" textLength="732" clip-path="url(#terminal-650700618-line-21)">                        length limit of the commit message; </text><text class="terminal-650700618-r4" x="732" y="532.4" textLength="12.2" clip-path="url(#terminal-650700618-line-21)">0</text><text class="terminal-650700618-r1" x="744.2" y="532.4" textLength="158.6" clip-path="url(#terminal-650700618-line-21)"> for no limit</text><text class="terminal-650700618-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-650700618-line-21)"> +</text><text class="terminal-650700618-r1" x="0" y="556.8" textLength="671" clip-path="url(#terminal-650700618-line-22)">  --                    Positional arguments separator </text><text class="terminal-650700618-r2" x="671" y="556.8" textLength="12.2" clip-path="url(#terminal-650700618-line-22)">(</text><text class="terminal-650700618-r1" x="683.2" y="556.8" textLength="134.2" clip-path="url(#terminal-650700618-line-22)">recommended</text><text class="terminal-650700618-r2" x="817.4" y="556.8" textLength="12.2" clip-path="url(#terminal-650700618-line-22)">)</text><text class="terminal-650700618-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-650700618-line-22)"> +</text><text class="terminal-650700618-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-650700618-line-23)"> </text> </g> </g> From f3a4b8388e4574541efb488bb53027bc55df0ef4 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Tue, 30 Dec 2025 22:43:38 +0800 Subject: [PATCH 148/221] ci: use more workers to speed up tests in pipeline --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 55d5f35943..3e63f811ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ check-commit.help = "Check the commit messages" check-commit.cmd = "cz --no-raise 3 check --rev-range origin/master.." test.help = "Run the test suite" -test.cmd = "pytest -n 3 --dist=loadfile" +test.cmd = "pytest -n auto --dist=loadfile" "test:all".help = "Run the test suite on all supported Python versions" "test:all".cmd = "tox --parallel" From 77ab109dfa23dec740c6cebdde4ec19634fad1af Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 10 Dec 2025 22:35:36 +0800 Subject: [PATCH 149/221] docs(writing_commits): improve documentation for writing commits best practice --- docs/tutorials/writing_commits.md | 175 ++++++++++++++++++++++++------ mkdocs.yml | 2 +- 2 files changed, 143 insertions(+), 34 deletions(-) diff --git a/docs/tutorials/writing_commits.md b/docs/tutorials/writing_commits.md index a3cf778dcf..b8aa7f30f0 100644 --- a/docs/tutorials/writing_commits.md +++ b/docs/tutorials/writing_commits.md @@ -1,51 +1,160 @@ -For this project to work well in your pipeline, a commit convention must be followed. +# Commit Message Best Practices -By default, Commitizen uses the known [conventional commits][conventional_commits], but -you can create your own following the documentation information over at -[customization][customization]. +## About -## Conventional commits +For Commitizen to work effectively in your development pipeline, commits must follow a consistent convention. By default, Commitizen uses the [Conventional Commits][conventional_commits] specification, which provides a standardized format for commit messages that enables automatic versioning and changelog generation. -If you are using [conventional commits][conventional_commits], the most important -thing to know is that you must begin your commits with at least one of these tags: -`fix`, `feat`. And if you introduce a breaking change, then you must -add to your commit body the following `BREAKING CHANGE`. -Using these three keywords will allow the proper identification of the semantic version. -Of course, there are other keywords, but I'll leave it to the reader to explore them. +You can also create your own custom commit convention by following the [customization documentation][customization]. -Note: You can also indicate breaking changes by adding an exclamation mark in the commit title -(e.g., `feat!: breaking change`) by setting the `breaking_change_exclamation_in_title` -configuration option to `true`. [Read more][breaking-change-config] +## Conventional Commits Format -## Writing commits +The Conventional Commits specification follows this structure: -Now to the important part: when writing commits, it's important to think about: +``` +<type>[optional scope]: <description> -- Your future self -- Your colleagues +[optional body] -You may think this is trivial, but it's not. It's important for the reader to -understand what happened. +[optional footer] +``` -Emojis may be added as well (e.g., see [cz-emoji][cz_emoji]), which requires the `utf-8`, or equivalent, character encoding to support unicode characters. By default, `commitizen` uses the `utf-8` character encoding, but a different encoding may be set through the `encoding` [configuration option][configuration]. +### Commit Types -### Recommendations +Commit types categorize the nature of your changes. The most important types for semantic versioning are: -- **Keep the message short**: Makes the list of commits more readable (~50 chars). -- **Talk imperative**: Follow this rule: `If applied, this commit will <commit message>` -- **Think about the CHANGELOG**: Your commits will probably end up in the changelog, - so try writing for it, but also keep in mind that you can skip sending commits to the - CHANGELOG by using different keywords (like `build`). -- **Use a commit per new feature**: If you introduce multiple things related to the same - commit, squash them. This is useful for auto-generating CHANGELOG. +- **`feat`**: Introduces a new feature (correlates with **MINOR** version increment) +- **`fix`**: Patches a bug (correlates with **PATCH** version increment) -| Do's | Don'ts | -| ---- | ------ | +Other commonly used types include: + +- **`docs`**: Documentation only changes +- **`style`**: Code style changes (formatting, missing semicolons, etc.) +- **`refactor`**: Code refactoring without changing functionality +- **`perf`**: Performance improvements +- **`test`**: Adding or updating tests +- **`build`**: Changes to build system or dependencies +- **`ci`**: Changes to CI configuration files +- **`chore`**: Other changes that don't modify source or test files + +!!! note + While `feat` and `fix` directly affect semantic versioning, other types (like `build`, `chore`, `docs`) typically don't trigger version bumps unless they include a `BREAKING CHANGE`. + +### Breaking Changes + +Breaking changes trigger a **MAJOR** version increment. You can indicate breaking changes in two ways: + +1. **In the commit body or footer**: + ``` + feat(api): change authentication method + + BREAKING CHANGE: The authentication API now requires OAuth2 instead of API keys. + ``` + +2. **In the commit title** (when enabled): + ``` + feat!: change authentication method + ``` + + To enable this syntax, set `breaking_change_exclamation_in_title = true` in your configuration. [Read more][breaking-change-config] + +### Scope + +An optional scope can be added to provide additional context about the area of the codebase affected: + +``` +feat(parser): add support for JSON arrays +fix(api): handle null response gracefully +``` + +## Writing Effective Commit Messages + +Well-written commit messages are crucial for maintaining a clear project history. When writing commits, consider: + +- **Your future self**: You'll need to understand these changes months later +- **Your team**: Clear messages help colleagues understand the codebase evolution +- **Automated tools**: Good messages enable better changelog generation and versioning + +### Best Practices + +#### 1. Keep the Subject Line Concise + +The subject line should be clear and concise (aim for ~50 characters). It should summarize what the commit does in one line. + +**Good:** +``` +fix(commands): handle missing user input gracefully +feat(api): add pagination support +``` + +**Avoid:** +``` +fix: stuff +feat: commit command introduced +``` + +#### 2. Use Imperative Mood + +Write commit messages in the imperative mood, as if completing the sentence: "If applied, this commit will..." + +**Good:** +``` +feat: add user authentication +fix: resolve memory leak in parser +``` + +**Avoid:** +``` +feat: added user authentication +fix: resolved memory leak in parser +``` + +#### 3. Think About the Changelog + +Your commits will likely appear in the automatically generated changelog. Write messages that make sense in that context. If you want to exclude a commit from the changelog, use types like `build`, `chore`, or `ci`. + +#### 4. One Feature Per Commit + +Keep commits focused on a single change. If you introduce multiple related changes, consider squashing them into a single commit. This makes the history cleaner and improves changelog generation. + +#### 5. Use the Body for Context + +For complex changes, use the commit body to explain: + +- **Why** the change was made +- **What** was changed (if not obvious from the subject) +- **How** it differs from previous behavior + +``` +feat(api): add rate limiting + +Implement rate limiting to prevent API abuse. The system now +enforces a maximum of 100 requests per minute per IP address. +Exceeding this limit returns a 429 status code. +``` + +### Examples + +| ✅ Good Examples | ❌ Poor Examples | +| ---------------- | ---------------- | | `fix(commands): bump error when no user provided` | `fix: stuff` | -| `feat: add new commit command` | `feat: commit command introduced` | +| `feat(api): add pagination to user list endpoint` | `feat: commit command introduced` | +| `docs: update installation instructions` | `docs: changes` | +| `refactor(parser): simplify token extraction logic` | `refactor: code cleanup` | + +## Character Encoding + +Commitizen supports Unicode characters (including emojis) in commit messages. This is useful if you're using commit message formats that include emojis, such as [cz-emoji][cz_emoji]. + +By default, Commitizen uses `utf-8` encoding. You can configure a different encoding through the `encoding` [configuration option][configuration]. + +## Related Documentation + +- [Conventional Commits Specification][conventional_commits] +- [Custom Commit Conventions][customization] +- [Commit Configuration Options](../config/commit.md) [customization]: ../customization/config_file.md [conventional_commits]: https://www.conventionalcommits.org -[cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-plugins/cz-emoji/ +[cz_emoji]: ../third-party-plugins/cz-emoji.md [configuration]: ../config/commit.md#encoding [breaking-change-config]: ../config/commit.md#breaking_change_exclamation_in_title diff --git a/mkdocs.yml b/mkdocs.yml index 9666a203db..28c5b9e382 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -57,7 +57,7 @@ nav: - Customized Python Class: "customization/python_class.md" - Changelog Template: "customization/changelog_template.md" - Tutorials: - - Writing commits: "tutorials/writing_commits.md" + - Commit Message Best Practices: "tutorials/writing_commits.md" - Managing tags formats: "tutorials/tag_format.md" - Auto check commits: "tutorials/auto_check.md" - Auto prepare commit message: "tutorials/auto_prepare_commit_message.md" From 88328040b0acb8b2c2b57e60ff745191ed09d137 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 10 Dec 2025 22:20:45 +0800 Subject: [PATCH 150/221] docs(auto_check.md): rewrite to make the doc read more smoothly, update possibly stale information --- docs/tutorials/auto_check.md | 120 +++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 20 deletions(-) diff --git a/docs/tutorials/auto_check.md b/docs/tutorials/auto_check.md index d143528767..d877d5009f 100644 --- a/docs/tutorials/auto_check.md +++ b/docs/tutorials/auto_check.md @@ -2,47 +2,58 @@ ## About -To automatically check a commit message prior to committing, you can use a [git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). +To automatically check a commit message prior to committing, you can use a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). This ensures that all commit messages follow your project's commitizen format before they are accepted into the repository. + +When a commit message fails validation, Git will reject the commit and display an error message explaining what went wrong. You'll need to amend your commit message to follow the required format before the commit can proceed. ## How to There are two common methods for installing the hooks: -### Method 1: Add a git hook through [pre-commit](https://pre-commit.com/) +### Method 1: Using [pre-commit](https://pre-commit.com/) (Recommended) + +[pre-commit](https://pre-commit.com/) is a framework for managing and maintaining multi-language pre-commit hooks. It's the recommended approach as it handles hook installation, updates, and execution automatically. -- Step 1: Install [pre-commit](https://pre-commit.com/) +#### Step 1: Install pre-commit ```sh python -m pip install pre-commit ``` -- Step 2: Create `.pre-commit-config.yaml` in your root directory with the following content +#### Step 2: Create `.pre-commit-config.yaml` + +Create a `.pre-commit-config.yaml` file in your project root directory with the following content: ```yaml --- repos: - repo: https://github.com/commitizen-tools/commitizen - rev: v1.17.0 + rev: v4.10.0 # Use the latest version or a specific version hooks: - id: commitizen stages: [commit-msg] ``` -- Step 3: Install the configuration into the git hook through `pre-commit` +!!! tip "Using the latest version" + Replace `v4.10.0` with the latest commitizen version. You can find the latest version on [GitHub releases](https://github.com/commitizen-tools/commitizen/releases) or use a specific commit SHA for pinning to an exact version. + +#### Step 3: Install the hook + +Install the configuration into Git's hook system: ```bash pre-commit install --hook-type commit-msg ``` -### Method 2: Manually add a git hook +The hook is now active! Every time you create a commit, commitizen will automatically validate your commit message. -The command might be included inside a Git hook (inside `.git/hooks/` at the root of the project). +### Method 2: Manual Git hook installation -The selected hook might be the file called commit-msg. +If you prefer not to use pre-commit, you can manually create a Git hook. This gives you full control over the hook script but requires manual maintenance. -This example shows how to use the check command inside commit-msg. +#### Step 1: Create the commit-msg hook -At the root of the project: +Navigate to your project's `.git/hooks` directory and create the `commit-msg` hook file: ```bash cd .git/hooks @@ -50,19 +61,88 @@ touch commit-msg chmod +x commit-msg ``` -Open the file and edit it: +#### Step 2: Add the commitizen check command -```sh +Open the `commit-msg` file in your editor and add the following content: + +```bash #!/bin/bash -MSG_FILE=$1 -cz check --allow-abort --commit-msg-file $MSG_FILE +cz check --allow-abort --commit-msg-file $1 +``` + +Where: + +- `$1` is the temporary file path that Git provides, containing the current commit message +- `--allow-abort` allows empty commit messages (which typically instruct Git to abort a commit) +- `--commit-msg-file` tells commitizen to read the commit message from the specified file + +The hook is now active! Each time you create a commit, this hook will automatically validate your commit message. + +## Testing the hook + +After installing the hook, you can test it by attempting to commit with an invalid message: + +```bash +# This should fail with an invalid message +git commit -m "invalid commit message" + +# This should succeed with a valid message +git commit -m "feat: add new feature" ``` -Where `$1` is the name of the temporary file that contains the current commit message. To be more explicit, the previous variable is stored in another variable called `$MSG_FILE`, for didactic purposes. +If the hook is working correctly, invalid commit messages will be rejected with an error message explaining what's wrong. + +## What happens when validation fails? + +When a commit message fails validation: + +1. Git will abort the commit +2. An error message will be displayed showing: + - Which commit failed (if checking multiple commits) + - The invalid commit message + - The expected pattern/format +3. Your changes remain staged, so you can simply amend the commit message and try again + +Example error output: + +<!-- DEPENDENCY: InvalidCommitMessageError --> + +``` +commit validation: failed! +please enter a commit message in the commitizen format. +commit "abc123": "invalid message" +pattern: ^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,} +``` + +## Troubleshooting + +### Hook not running + +- **Verify the hook file exists**: Check that `.git/hooks/commit-msg` exists and is executable +- **Check file permissions**: Ensure the hook has execute permissions (`chmod +x .git/hooks/commit-msg`) +- **Verify commitizen is installed**: Run `cz --version` to confirm commitizen is available in your PATH +- **Check Git version**: Ensure you're using a recent version of Git that supports hooks + +### Pre-commit hook not working + +- **Verify installation**: Run `pre-commit --version` to confirm pre-commit is installed +- **Reinstall the hook**: Try running `pre-commit install --hook-type commit-msg` again +- **Check configuration**: Verify your `.pre-commit-config.yaml` file is valid YAML and in the project root +- **Update hooks**: Run `pre-commit autoupdate` to update to the latest versions + +### Bypassing the hook (when needed) + +If you need to bypass the hook temporarily (e.g., for merge commits or special cases), you can use: + +```bash +git commit --no-verify -m "your message" +``` -The `--commit-msg-file` flag is required, not optional. +!!! warning "Use with caution" + Only bypass hooks when absolutely necessary, as it defeats the purpose of automated validation. -Each time you create a commit, this hook will automatically analyze it. -If the commit message is invalid, it will be rejected. +## Additional resources -The commit should follow the given committing rules; otherwise, it won't be accepted. +- Learn more about [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) +- See the [check command documentation](../commands/check.md) for more validation options +- Check out [pre-commit documentation](https://pre-commit.com/) for advanced hook management From 743a12e5b1c1b85df3b07490a4fd25d794b11dc4 Mon Sep 17 00:00:00 2001 From: BelpHegoR17 <bel02082024@gmail.com> Date: Fri, 2 Jan 2026 21:21:07 +0530 Subject: [PATCH 151/221] docs: add warning about future removal of cz_customize --- docs/customization/config_file.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/customization/config_file.md b/docs/customization/config_file.md index a5440342bf..db15b71e6a 100644 --- a/docs/customization/config_file.md +++ b/docs/customization/config_file.md @@ -4,6 +4,8 @@ The basic steps are: 1. Define your custom committing or bumping rules in the configuration file. 2. Declare `name = "cz_customize"` in your configuration file, or add `-n cz_customize` when running Commitizen. +!!! warning + `cz_customize` is likely to be removed or renamed in the next major release. Example: From 8778b636deae5672eb908a0570416fe3fd74a9e7 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 29 Dec 2025 17:17:36 +0100 Subject: [PATCH 152/221] test(warnings): ignore our own legit warnings --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3e63f811ab..ac66146d96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -170,6 +170,10 @@ omit = [ [tool.pytest.ini_options] addopts = "--strict-markers" testpaths = ["tests/"] +filterwarnings = [ + # get_smart_tag_range is deprecated and will be removed in v5 + "ignore:Call to deprecated function \\(or staticmethod\\) get_smart_tag_range:DeprecationWarning", +] [tool.tox] requires = ["tox>=4.22"] From 0b0d1ba37c0e3c1d08326638f4d92cc41aba8c9a Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 29 Dec 2025 17:22:25 +0100 Subject: [PATCH 153/221] test(warning): introduce a `UtilFixture` helper and remove git `wait_for_tag()` function, removing the associated warnings --- tests/commands/test_changelog_command.py | 1231 +++++++---------- ...log_config_flag_merge_prerelease_alpha_.md | 2 +- ...elog_config_flag_merge_prerelease_beta_.md | 2 +- ...ngelog_config_flag_merge_prerelease_rc_.md | 2 +- ...te_version_with_merge_prerelease_alpha_.md | 2 +- ...ate_version_with_merge_prerelease_beta_.md | 2 +- ...idate_version_with_merge_prerelease_rc_.md | 2 +- tests/conftest.py | 10 +- tests/utils.py | 131 +- 9 files changed, 635 insertions(+), 749 deletions(-) diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index 17594eaa53..1094e62766 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -1,21 +1,16 @@ +from __future__ import annotations + import itertools import sys -from datetime import datetime from pathlib import Path from textwrap import dedent +from typing import TYPE_CHECKING import pytest -from dateutil import relativedelta from jinja2 import FileSystemLoader -from pytest_mock import MockFixture -from pytest_regressions.file_regression import FileRegressionFixture -from commitizen import __file__ as commitizen_init from commitizen import cli, git -from commitizen.changelog_formats import ChangelogFormat from commitizen.commands.changelog import Changelog -from commitizen.config.base_config import BaseConfig -from commitizen.cz.base import BaseCommitizen from commitizen.exceptions import ( DryRunExit, InvalidCommandArgumentError, @@ -24,76 +19,69 @@ NotAGitProjectError, NotAllowed, ) -from tests.utils import ( - create_branch, - create_file_and_commit, - create_tag, - get_current_branch, - merge_branch, - switch_branch, - wait_for_tag, -) + +if TYPE_CHECKING: + from pytest_mock import MockFixture + from pytest_regressions.file_regression import FileRegressionFixture + + from commitizen.changelog_formats import ChangelogFormat + from commitizen.config.base_config import BaseConfig + from commitizen.config.json_config import JsonConfig + from commitizen.cz.base import BaseCommitizen + from tests.utils import UtilFixture @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_from_version_zero_point_two( - mocker: MockFixture, capsys, file_regression + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - create_file_and_commit("feat: new file") - create_file_and_commit("refactor: not in changelog") + util.create_file_and_commit("feat: new file") + util.create_file_and_commit("refactor: not in changelog") # create tag - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") capsys.readouterr() - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: after 0.2") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: after 0.2") - testargs = ["cz", "changelog", "--start-rev", "0.2.0", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run", "--start-rev", "0.2.0") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") -def test_changelog_with_different_cz(mocker: MockFixture, capsys, file_regression): - create_file_and_commit("JRA-34 #comment corrected indent issue") - create_file_and_commit("JRA-35 #time 1w 2d 4h 30m Total work logged") - - testargs = ["cz", "-n", "cz_jira", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) +def test_changelog_with_different_cz( + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, +): + util.create_file_and_commit("JRA-34 #comment corrected indent issue") + util.create_file_and_commit("JRA-35 #time 1w 2d 4h 30m Total work logged") with pytest.raises(DryRunExit): - cli.main() + util.run_cli("-n", "cz_jira", "changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_from_start( - mocker: MockFixture, capsys, changelog_format: ChangelogFormat, file_regression + changelog_format: ChangelogFormat, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - create_file_and_commit("feat: new file") - create_file_and_commit("refactor: is in changelog") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: new file") + util.create_file_and_commit("refactor: is in changelog") + util.create_file_and_commit("Merge into master") changelog_file = f"CHANGELOG.{changelog_format.extension}" template = f"CHANGELOG.{changelog_format.extension}.j2" - testargs = [ - "cz", - "changelog", - "--file-name", - changelog_file, - "--template", - template, - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--file-name", changelog_file, "--template", template) with open(changelog_file, encoding="utf-8") as f: out = f.read() @@ -101,101 +89,76 @@ def test_changelog_from_start( @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-08-14") def test_changelog_replacing_unreleased_using_incremental( - mocker: MockFixture, capsys, changelog_format: ChangelogFormat, file_regression + changelog_format: ChangelogFormat, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.create_file_and_commit("Merge into master") changelog_file = f"CHANGELOG.{changelog_format.extension}" template = f"CHANGELOG.{changelog_format.extension}.j2" - testargs = [ - "cz", - "changelog", - "--file-name", - changelog_file, - "--template", - template, - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--file-name", changelog_file, "--template", template) - testargs = [ - "cz", - "bump", - "--yes", - "--file-name", - changelog_file, - "--template", - template, - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--file-name", changelog_file, "--template", template) - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - testargs = [ - "cz", + util.run_cli( "changelog", "--incremental", "--file-name", changelog_file, "--template", template, - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + ) with open(changelog_file, encoding="utf-8") as f: - out = f.read().replace( - datetime.strftime(datetime.now(), "%Y-%m-%d"), "2022-08-14" - ) + out = f.read() file_regression.check(out, extension=changelog_format.ext) @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-08-14") def test_changelog_is_persisted_using_incremental( - mocker: MockFixture, capsys, changelog_path, file_regression + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.create_file_and_commit("Merge into master") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog") with open(changelog_path, "a", encoding="utf-8") as f: f.write("\nnote: this should be persisted using increment\n") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") - - testargs = ["cz", "changelog", "--incremental"] + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: - out = f.read().replace( - datetime.strftime(datetime.now(), "%Y-%m-%d"), "2022-08-14" - ) + out = f.read() file_regression.check(out, extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_incremental_angular_sample( - mocker: MockFixture, capsys, changelog_path, file_regression + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): with open(changelog_path, "w", encoding="utf-8") as f: f.write( @@ -205,19 +168,16 @@ def test_changelog_incremental_angular_sample( "\n" "* **common:** format day-periods that cross midnight ([#36611](https://github.com/angular/angular/issues/36611)) ([c6e5fc4](https://github.com/angular/angular/commit/c6e5fc4)), closes [#36566](https://github.com/angular/angular/issues/36566)\n" ) - create_file_and_commit("irrelevant commit") - git.tag("10.0.0-rc.3") + util.create_file_and_commit("irrelevant commit") + util.create_tag("10.0.0-rc.3") - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - testargs = ["cz", "changelog", "--incremental"] - - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -252,23 +212,22 @@ def test_changelog_incremental_angular_sample( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_incremental_keep_a_changelog_sample( - mocker: MockFixture, capsys, changelog_path, file_regression + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): with open(changelog_path, "w", encoding="utf-8") as f: f.write(KEEP_A_CHANGELOG) - create_file_and_commit("irrelevant commit") - git.tag("1.0.0") - - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0") - testargs = ["cz", "changelog", "--incremental"] + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -278,13 +237,15 @@ def test_changelog_incremental_keep_a_changelog_sample( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.parametrize("dry_run", [True, False]) -def test_changelog_hook(mocker: MockFixture, config: BaseConfig, dry_run: bool): +def test_changelog_hook( + mocker: MockFixture, config: BaseConfig, dry_run: bool, util: UtilFixture +): changelog_hook_mock = mocker.Mock() changelog_hook_mock.return_value = "cool changelog hook" - create_file_and_commit("feat: new file") - create_file_and_commit("refactor: is in changelog") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: new file") + util.create_file_and_commit("refactor: is in changelog") + util.create_file_and_commit("Merge into master") config.settings["change_type_order"] = ["Refactor", "Feat"] # type: ignore[typeddict-unknown-key] changelog = Changelog( @@ -308,13 +269,15 @@ def test_changelog_hook(mocker: MockFixture, config: BaseConfig, dry_run: bool): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_changelog_hook_customize(mocker: MockFixture, config_customize): +def test_changelog_hook_customize( + mocker: MockFixture, config_customize: JsonConfig, util: UtilFixture +): changelog_hook_mock = mocker.Mock() changelog_hook_mock.return_value = "cool changelog hook" - create_file_and_commit("feat: new file") - create_file_and_commit("refactor: is in changelog") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: new file") + util.create_file_and_commit("refactor: is in changelog") + util.create_file_and_commit("Merge into master") changelog = Changelog( config_customize, @@ -330,15 +293,17 @@ def test_changelog_hook_customize(mocker: MockFixture, config_customize): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_changelog_release_hook(mocker: MockFixture, config): +def test_changelog_release_hook( + mocker: MockFixture, config: BaseConfig, util: UtilFixture +): def changelog_release_hook(release: dict, tag: git.GitTag) -> dict: return release for i in range(3): - create_file_and_commit("feat: new file") - create_file_and_commit("refactor: is in changelog") - create_file_and_commit("Merge into master") - git.tag(f"0.{i + 1}.0") + util.create_file_and_commit("feat: new file") + util.create_file_and_commit("refactor: is in changelog") + util.create_file_and_commit("Merge into master") + util.create_tag(f"0.{i + 1}.0") # changelog = Changelog(config, {}) changelog = Changelog( @@ -353,7 +318,7 @@ def changelog_release_hook(release: dict, tag: git.GitTag) -> dict: @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_with_non_linear_merges_commit_order( - mocker: MockFixture, config_customize + mocker: MockFixture, config_customize: JsonConfig, util: UtilFixture ): """Test that commits merged non-linearly are correctly ordered in the changelog @@ -385,23 +350,23 @@ def test_changelog_with_non_linear_merges_commit_order( changelog_hook_mock = mocker.Mock() changelog_hook_mock.return_value = "cool changelog hook" - create_file_and_commit("feat: initial commit") + util.create_file_and_commit("feat: initial commit") - main_branch = get_current_branch() + main_branch = util.get_current_branch() - create_branch("branchA") - create_branch("branchB") + util.create_branch("branchA") + util.create_branch("branchB") - switch_branch("branchA") - create_file_and_commit("feat: I will be merged second") + util.switch_branch("branchA") + util.create_file_and_commit("feat: I will be merged second") - switch_branch("branchB") - create_file_and_commit("feat: I will be merged first") + util.switch_branch("branchB") + util.create_file_and_commit("feat: I will be merged first") # Note we merge branches opposite order than author_date - switch_branch(main_branch) - merge_branch("branchB") - merge_branch("branchA") + util.switch_branch(main_branch) + util.merge_branch("branchB") + util.merge_branch("branchA") changelog = Changelog( config_customize, @@ -422,32 +387,26 @@ def test_changelog_with_non_linear_merges_commit_order( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_multiple_incremental_do_not_add_new_lines( - mocker: MockFixture, capsys, changelog_path, file_regression + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): """Test for bug https://github.com/commitizen-tools/commitizen/issues/192""" - create_file_and_commit("feat: add new output") + util.create_file_and_commit("feat: add new output") - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") - create_file_and_commit("fix: output glitch") + util.create_file_and_commit("fix: output glitch") - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") - create_file_and_commit("fix: no more explosions") + util.create_file_and_commit("fix: no more explosions") - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") - create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("feat: add more stuff") - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -457,18 +416,15 @@ def test_changelog_multiple_incremental_do_not_add_new_lines( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_incremental_newline_separates_new_content_from_old( - mocker: MockFixture, changelog_path + changelog_path: str, util: UtilFixture ): """Test for https://github.com/commitizen-tools/commitizen/issues/509""" with open(changelog_path, "w", encoding="utf-8") as f: f.write("Pre-existing content that should be kept\n") - create_file_and_commit("feat: add more cat videos") - - testargs = ["cz", "changelog", "--incremental"] + util.create_file_and_commit("feat: add more cat videos") - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -479,7 +435,7 @@ def test_changelog_incremental_newline_separates_new_content_from_old( ) -def test_changelog_without_revision(mocker: MockFixture, tmp_commitizen_project): +def test_changelog_without_revision(tmp_commitizen_project, util: UtilFixture): changelog_file = tmp_commitizen_project.join("CHANGELOG.md") changelog_file.write( """ @@ -489,26 +445,19 @@ def test_changelog_without_revision(mocker: MockFixture, tmp_commitizen_project) """ ) - # create_file_and_commit("feat: new file") - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(NoRevisionError): - cli.main() + util.run_cli("changelog", "--incremental") @pytest.mark.usefixtures("tmp_commitizen_project") -def test_changelog_incremental_with_revision(mocker): +def test_changelog_incremental_with_revision(util: UtilFixture): """combining incremental with a revision doesn't make sense""" - testargs = ["cz", "changelog", "--incremental", "0.2.0"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(NotAllowed): - cli.main() + util.run_cli("changelog", "--incremental", "0.2.0") def test_changelog_with_different_tag_name_and_changelog_content( - mocker: MockFixture, tmp_commitizen_project + tmp_commitizen_project, util: UtilFixture ): changelog_file = tmp_commitizen_project.join("CHANGELOG.md") changelog_file.write( @@ -518,54 +467,51 @@ def test_changelog_with_different_tag_name_and_changelog_content( ## v1.0.0 """ ) - create_file_and_commit("feat: new file") - git.tag("2.0.0") - - # create_file_and_commit("feat: new file") - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat: new file") + util.create_tag("2.0.0") with pytest.raises(NoRevisionError): - cli.main() + util.run_cli("changelog", "--incremental") -def test_changelog_in_non_git_project(tmpdir, config, mocker: MockFixture): - testargs = ["cz", "changelog", "--incremental"] - mocker.patch.object(sys, "argv", testargs) - - with tmpdir.as_cwd(): - with pytest.raises(NotAGitProjectError): - cli.main() +@pytest.mark.usefixtures("chdir") +def test_changelog_in_non_git_project(util: UtilFixture): + with pytest.raises(NotAGitProjectError): + util.run_cli("changelog", "--incremental") @pytest.mark.usefixtures("tmp_commitizen_project") -def test_breaking_change_content_v1_beta(mocker: MockFixture, capsys, file_regression): +def test_breaking_change_content_v1_beta( + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, +): commit_message = ( "feat(users): email pattern corrected\n\n" "BREAKING CHANGE: migrate by renaming user to users\n\n" "footer content" ) - create_file_and_commit(commit_message) - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit(commit_message) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") -def test_breaking_change_content_v1(mocker: MockFixture, capsys, file_regression): +def test_breaking_change_content_v1( + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, +): commit_message = ( "feat(users): email pattern corrected\n\n" "body content\n\n" "BREAKING CHANGE: migrate by renaming user to users" ) - create_file_and_commit(commit_message) - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit(commit_message) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @@ -573,7 +519,9 @@ def test_breaking_change_content_v1(mocker: MockFixture, capsys, file_regression @pytest.mark.usefixtures("tmp_commitizen_project") def test_breaking_change_content_v1_multiline( - mocker: MockFixture, capsys, file_regression + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, ): commit_message = ( "feat(users): email pattern corrected\n\n" @@ -582,25 +530,23 @@ def test_breaking_change_content_v1_multiline( "and then connect the thingy with the other thingy\n\n" "footer content" ) - create_file_and_commit(commit_message) - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit(commit_message) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") def test_breaking_change_content_v1_with_exclamation_mark( - mocker: MockFixture, capsys, file_regression + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, ): commit_message = "chore!: drop support for py36" - create_file_and_commit(commit_message) - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit(commit_message) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @@ -608,14 +554,14 @@ def test_breaking_change_content_v1_with_exclamation_mark( @pytest.mark.usefixtures("tmp_commitizen_project") def test_breaking_change_content_v1_with_exclamation_mark_feat( - mocker: MockFixture, capsys, file_regression + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, ): commit_message = "feat(pipeline)!: some text with breaking change" - create_file_and_commit(commit_message) - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit(commit_message) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @@ -623,18 +569,19 @@ def test_breaking_change_content_v1_with_exclamation_mark_feat( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_config_flag_increment( - mocker: MockFixture, changelog_path, config_path, file_regression + changelog_path: str, + config_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.write("changelog_incremental = true\n") with open(changelog_path, "a", encoding="utf-8") as f: f.write("\nnote: this should be persisted using increment\n") - create_file_and_commit("feat: add new output") + util.create_file_and_commit("feat: add new output") - testargs = ["cz", "changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -645,31 +592,30 @@ def test_changelog_config_flag_increment( @pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"]) @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2025-12-29") def test_changelog_config_flag_merge_prerelease( - mocker: MockFixture, changelog_path, config_path, file_regression, test_input + changelog_path: str, + config_path: str, + file_regression: FileRegressionFixture, + test_input: str, + util: UtilFixture, ): with open(config_path, "a") as f: f.write("changelog_merge_prerelease = true\n") - create_file_and_commit("irrelevant commit") - mocker.patch("commitizen.git.GitTag.date", "1970-01-01") - git.tag("1.0.0") - - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0") - testargs = ["cz", "bump", "--prerelease", test_input, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.run_cli("bump", "--prerelease", test_input, "--yes") - testargs = ["cz", "changelog"] + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog") with open(changelog_path) as f: out = f.read() @@ -679,25 +625,24 @@ def test_changelog_config_flag_merge_prerelease( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_config_start_rev_option( - mocker: MockFixture, capsys, config_path, file_regression + capsys: pytest.CaptureFixture, + config_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") capsys.readouterr() - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: after 0.2") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: after 0.2") with open(config_path, "a", encoding="utf-8") as f: f.write('changelog_start_rev = "0.2.0"\n') - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") @@ -705,24 +650,23 @@ def test_changelog_config_start_rev_option( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_incremental_keep_a_changelog_sample_with_annotated_tag( - mocker: MockFixture, capsys, changelog_path, file_regression + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): """Fix #378""" with open(changelog_path, "w", encoding="utf-8") as f: f.write(KEEP_A_CHANGELOG) - create_file_and_commit("irrelevant commit") - git.tag("1.0.0", annotated=True) + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0", annotated=True) - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - testargs = ["cz", "changelog", "--incremental"] - - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -734,29 +678,27 @@ def test_changelog_incremental_keep_a_changelog_sample_with_annotated_tag( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2021-06-11") def test_changelog_incremental_with_release_candidate_version( - mocker: MockFixture, changelog_path, file_regression, test_input + changelog_path: str, + file_regression: FileRegressionFixture, + test_input: str, + util: UtilFixture, ): """Fix #357""" with open(changelog_path, "w", encoding="utf-8") as f: f.write(KEEP_A_CHANGELOG) - create_file_and_commit("irrelevant commit") - git.tag("1.0.0", annotated=True) + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0", annotated=True) - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") - testargs = ["cz", "bump", "--changelog", "--prerelease", test_input, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--changelog", "--prerelease", test_input, "--yes") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - testargs = ["cz", "changelog", "--incremental"] - - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -770,23 +712,23 @@ def test_changelog_incremental_with_release_candidate_version( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2021-06-11") def test_changelog_incremental_with_prerelease_version_to_prerelease_version( - mocker: MockFixture, changelog_path, file_regression, from_pre, to_pre + changelog_path: str, + file_regression: FileRegressionFixture, + from_pre: str, + to_pre: str, + util: UtilFixture, ): with open(changelog_path, "w") as f: f.write(KEEP_A_CHANGELOG) - create_file_and_commit("irrelevant commit") - git.tag("1.0.0", annotated=True) + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0", annotated=True) - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") - testargs = ["cz", "bump", "--changelog", "--prerelease", from_pre, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--changelog", "--prerelease", from_pre, "--yes") - testargs = ["cz", "bump", "--changelog", "--prerelease", to_pre, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--changelog", "--prerelease", to_pre, "--yes") with open(changelog_path) as f: out = f.read() @@ -796,31 +738,29 @@ def test_changelog_incremental_with_prerelease_version_to_prerelease_version( @pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"]) @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2025-12-29") def test_changelog_release_candidate_version_with_merge_prerelease( - mocker: MockFixture, changelog_path, file_regression, test_input + changelog_path: str, + file_regression: FileRegressionFixture, + test_input: str, + util: UtilFixture, ): """Fix #357""" with open(changelog_path, "w") as f: f.write(KEEP_A_CHANGELOG) - create_file_and_commit("irrelevant commit") - mocker.patch("commitizen.git.GitTag.date", "1970-01-01") - git.tag("1.0.0") + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0") - create_file_and_commit("feat: add new output") - create_file_and_commit("fix: output glitch") + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") - testargs = ["cz", "bump", "--prerelease", test_input, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.run_cli("bump", "--prerelease", test_input, "--yes") - testargs = ["cz", "changelog", "--merge-prerelease"] + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--merge-prerelease") with open(changelog_path) as f: out = f.read() @@ -832,35 +772,30 @@ def test_changelog_release_candidate_version_with_merge_prerelease( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2023-04-16") def test_changelog_incremental_with_merge_prerelease( - mocker: MockFixture, changelog_path, file_regression, test_input + changelog_path: str, + file_regression: FileRegressionFixture, + test_input: str, + util: UtilFixture, ): """Fix #357""" with open(changelog_path, "w") as f: f.write(KEEP_A_CHANGELOG) - create_file_and_commit("irrelevant commit") - mocker.patch("commitizen.git.GitTag.date", "1970-01-01") - git.tag("1.0.0") + util.create_file_and_commit("irrelevant commit") + util.create_tag("1.0.0") - create_file_and_commit("feat: add new output") + util.create_file_and_commit("feat: add new output") - testargs = ["cz", "bump", "--prerelease", test_input, "--yes", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - - create_file_and_commit("fix: output glitch") + util.run_cli("bump", "--prerelease", test_input, "--yes", "--changelog") - testargs = ["cz", "bump", "--prerelease", test_input, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("fix: output glitch") - create_file_and_commit("fix: mama gotta work") - create_file_and_commit("feat: add more stuff") - create_file_and_commit("Merge into master") + util.run_cli("bump", "--prerelease", test_input, "--yes") - testargs = ["cz", "changelog", "--merge-prerelease", "--incremental"] + util.create_file_and_commit("fix: mama gotta work") + util.create_file_and_commit("feat: add more stuff") + util.create_file_and_commit("Merge into master") - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--merge-prerelease", "--incremental") with open(changelog_path) as f: out = f.read() @@ -870,46 +805,38 @@ def test_changelog_incremental_with_merge_prerelease( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_with_filename_as_empty_string( - mocker: MockFixture, changelog_path, config_path + changelog_path: str, config_path: str, util: UtilFixture ): with open(config_path, "a", encoding="utf-8") as f: f.write("changelog_file = true\n") - create_file_and_commit("feat: add new output") + util.create_file_and_commit("feat: add new output") - testargs = ["cz", "changelog"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(NotAllowed): - cli.main() + util.run_cli("changelog") @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_first_version_from_arg( - mocker: MockFixture, config_path, changelog_path, file_regression + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog", "0.2.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.2.0") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -917,33 +844,26 @@ def test_changelog_from_rev_first_version_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_latest_version_from_arg( - mocker: MockFixture, config_path, changelog_path, file_regression + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - - wait_for_tag() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog", "0.3.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.3.0") with open(changelog_path) as f: out = f.read() @@ -962,43 +882,39 @@ def test_changelog_from_rev_latest_version_from_arg( ), ) def test_changelog_from_rev_range_not_found( - mocker: MockFixture, config_path, rev_range: str, tag: str + config_path: str, rev_range: str, tag: str, util: UtilFixture ): """Provides an invalid revision ID to changelog command""" with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") - create_tag(tag) - create_file_and_commit("feat: new file") - create_tag("1.0.0") + util.create_file_and_commit("feat: new file") + util.create_tag(tag) + util.create_file_and_commit("feat: new file") + util.create_tag("1.0.0") - testargs = ["cz", "changelog", rev_range] # it shouldn't exist - mocker.patch.object(sys, "argv", testargs) with pytest.raises(NoCommitsFoundError) as excinfo: - cli.main() + util.run_cli("changelog", rev_range) # it shouldn't exist assert "Could not find a valid revision" in str(excinfo) @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_multiple_matching_tags( - mocker: MockFixture, config_path, changelog_path + config_path: str, changelog_path: str, util: UtilFixture ): with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "new-$version"\nlegacy_tag_formats = ["legacy-$version"]') - create_file_and_commit("feat: new file") - create_tag("legacy-1.0.0") - create_file_and_commit("feat: new file") - create_tag("legacy-2.0.0") - create_tag("new-2.0.0") + util.create_file_and_commit("feat: new file") + util.create_tag("legacy-1.0.0") + util.create_file_and_commit("feat: new file") + util.create_tag("legacy-2.0.0") + util.create_tag("new-2.0.0") - testargs = ["cz", "changelog", "1.0.0..2.0.0"] # it shouldn't exist - mocker.patch.object(sys, "argv", testargs) with pytest.warns() as warnings: - cli.main() + util.run_cli("changelog", "1.0.0..2.0.0") # it shouldn't exist assert len(warnings) == 1 warning = warnings[0] @@ -1013,27 +929,19 @@ def test_changelog_multiple_matching_tags( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_from_rev_range_default_tag_format( - mocker, config_path, changelog_path + config_path: str, changelog_path: str, util: UtilFixture ): """Checks that rev_range is calculated with the default (None) tag format""" # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog", "0.3.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.3.0") with open(changelog_path) as f: out = f.read() @@ -1042,30 +950,26 @@ def test_changelog_from_rev_range_default_tag_format( @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_range_including_first_tag( - mocker: MockFixture, config_path, changelog_path, file_regression + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog", "0.2.0..0.3.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.2.0..0.3.0") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -1073,38 +977,29 @@ def test_changelog_from_rev_version_range_including_first_tag( @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_range_from_arg( - mocker: MockFixture, config_path, changelog_path, file_regression + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") - create_file_and_commit("feat: getting ready for this") + util.create_file_and_commit("feat: getting ready for this") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog", "0.3.0..0.4.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.3.0..0.4.0") with open(changelog_path) as f: out = f.read() @@ -1112,11 +1007,13 @@ def test_changelog_from_rev_version_range_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_range_with_legacy_tags( - mocker: MockFixture, config_path, changelog_path, file_regression + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - changelog = Path(changelog_path) Path(config_path).write_text( "\n".join( @@ -1132,72 +1029,48 @@ def test_changelog_from_rev_version_range_with_legacy_tags( ), ) - create_file_and_commit("feat: new file") - create_tag("old-0.2.0") - create_file_and_commit("feat: new file") - create_tag("legacy-0.3.0") - create_file_and_commit("feat: new file") - create_tag("legacy-0.4.0") + util.create_file_and_commit("feat: new file") + util.create_tag("old-0.2.0") + util.create_file_and_commit("feat: new file") + util.create_tag("legacy-0.3.0") + util.create_file_and_commit("feat: new file") + util.create_tag("legacy-0.4.0") - testargs = ["cz", "changelog", "0.2.0..0.4.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.2.0..0.4.0") file_regression.check(changelog.read_text(), extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_version_with_big_range_from_arg( - mocker: MockFixture, config_path, changelog_path, file_regression + config_path, changelog_path, file_regression, util: UtilFixture ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a", encoding="utf-8") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] # 0.3.0 - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: getting ready for this") + util.run_cli("bump", "--yes") # 0.3.0 + util.create_file_and_commit("feat: getting ready for this") - testargs = ["cz", "bump", "--yes"] # 0.4.0 - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("fix: small error") + util.run_cli("bump", "--yes") # 0.4.0 + util.create_file_and_commit("fix: small error") - testargs = ["cz", "bump", "--yes"] # 0.4.1 - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: new shinny feature") + util.run_cli("bump", "--yes") # 0.4.1 + util.create_file_and_commit("feat: new shinny feature") - testargs = ["cz", "bump", "--yes"] # 0.5.0 - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: amazing different shinny feature") - # dirty hack to avoid same time between tags + util.run_cli("bump", "--yes") # 0.5.0 + util.create_file_and_commit("feat: amazing different shinny feature") - testargs = ["cz", "bump", "--yes"] # 0.6.0 - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") # 0.6.0 - testargs = ["cz", "changelog", "0.3.0..0.5.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.3.0..0.5.0") with open(changelog_path) as f: out = f.read() @@ -1205,34 +1078,29 @@ def test_changelog_from_rev_version_with_big_range_from_arg( @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_rev_latest_version_dry_run( - mocker: MockFixture, capsys, config_path, changelog_path, file_regression + capsys: pytest.CaptureFixture, + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a") as f: f.write('tag_format = "$version"\n') # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") capsys.readouterr() - wait_for_tag() - testargs = ["cz", "changelog", "0.3.0", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "0.3.0", "--dry-run") out, _ = capsys.readouterr() @@ -1240,29 +1108,29 @@ def test_changelog_from_rev_latest_version_dry_run( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_invalid_subject_is_skipped(mocker: MockFixture, capsys): +def test_invalid_subject_is_skipped(capsys: pytest.CaptureFixture, util: UtilFixture): """Fix #510""" non_conformant_commit_title = ( "Merge pull request #487 from manang/master\n\n" "feat: skip merge messages that start with Pull request\n" ) - create_file_and_commit(non_conformant_commit_title) - create_file_and_commit("feat: a new world") - testargs = ["cz", "changelog", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit(non_conformant_commit_title) + util.create_file_and_commit("feat: a new world") with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() assert out == ("## Unreleased\n\n### Feat\n\n- a new world\n\n") @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_with_customized_change_type_order( - mocker, config_path, changelog_path, file_regression + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a") as f: f.write('tag_format = "$version"\n') f.write( @@ -1270,31 +1138,20 @@ def test_changelog_with_customized_change_type_order( ) # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") - create_file_and_commit("fix: fix bug") + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") + util.create_file_and_commit("fix: fix bug") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") - create_file_and_commit("feat: getting ready for this") - create_file_and_commit("perf: perf improvement") + util.create_file_and_commit("feat: getting ready for this") + util.create_file_and_commit("perf: perf improvement") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.run_cli("bump", "--yes") - testargs = ["cz", "changelog", "0.3.0..0.4.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "0.3.0..0.4.0") with open(changelog_path) as f: out = f.read() @@ -1302,67 +1159,56 @@ def test_changelog_with_customized_change_type_order( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_empty_commit_list(mocker): - create_file_and_commit("feat: a new world") +def test_empty_commit_list(mocker: MockFixture, util: UtilFixture): + util.create_file_and_commit("feat: a new world") # test changelog properly handles when no commits are found for the revision mocker.patch("commitizen.git.get_commits", return_value=[]) - testargs = ["cz", "changelog"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(NoCommitsFoundError): - cli.main() + util.run_cli("changelog") @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_prerelease_rev_with_use_scheme_semver( - mocker: MockFixture, capsys, config_path, changelog_path, file_regression + mocker: MockFixture, + capsys: pytest.CaptureFixture, + config_path: str, + changelog_path: str, + file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") - with open(config_path, "a") as f: f.write('tag_format = "$version"\nversion_scheme = "semver"') # create commit and tag - create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() + util.create_file_and_commit("feat: new file") + util.run_cli("bump", "--yes") - create_file_and_commit("feat: after 0.2.0") - create_file_and_commit("feat: another feature") + util.create_file_and_commit("feat: after 0.2.0") + util.create_file_and_commit("feat: another feature") - testargs = ["cz", "bump", "--yes", "--prerelease", "alpha"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--prerelease", "alpha") capsys.readouterr() - wait_for_tag() tag_exists = git.tag_exist("0.3.0-a0") assert tag_exists is True - testargs = ["cz", "changelog", "0.3.0-a0", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "0.3.0-a0", "--dry-run") out, _ = capsys.readouterr() file_regression.check(out, extension=".md") - testargs = ["cz", "bump", "--yes", "--prerelease", "alpha"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--prerelease", "alpha") capsys.readouterr() - wait_for_tag() tag_exists = git.tag_exist("0.3.0-a1") assert tag_exists is True - testargs = ["cz", "changelog", "0.3.0-a1", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("changelog", "0.3.0-a1", "--dry-run") out, _ = capsys.readouterr() @@ -1370,16 +1216,18 @@ def test_changelog_prerelease_rev_with_use_scheme_semver( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_changelog_uses_version_tags_for_header(mocker: MockFixture, config): +def test_changelog_uses_version_tags_for_header( + mocker: MockFixture, config: BaseConfig, util: UtilFixture +): """Tests that changelog headers always use version tags even if there are non-version tags This tests a scenario fixed in this commit: The first header was using a non-version tag and outputting "## 0-not-a-version" instead of "## 1.0.0 """ - create_file_and_commit("feat: commit in 1.0.0") - create_tag("0-not-a-version") - create_tag("1.0.0") - create_tag("also-not-a-version") + util.create_file_and_commit("feat: commit in 1.0.0") + util.create_tag("0-not-a-version") + util.create_tag("1.0.0") + util.create_tag("also-not-a-version") write_patch = mocker.patch("commitizen.commands.changelog.out.write") @@ -1398,8 +1246,9 @@ def test_changelog_uses_version_tags_for_header(mocker: MockFixture, config): @pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2022-02-13") def test_changelog_from_current_version_tag_with_nonversion_tag( - mocker: MockFixture, config + mocker: MockFixture, config: BaseConfig, util: UtilFixture ): """Tests that changelog generation for a single version works even if there is a non-version tag in the list of tags @@ -1408,33 +1257,17 @@ def test_changelog_from_current_version_tag_with_nonversion_tag( You have a commit in between two versions (1.0.0..2.0.0) which is tagged with a non-version tag (not-a-version). In this case commitizen should disregard the non-version tag when determining the rev-range & generating the changelog. """ - create_file_and_commit( - "feat: initial commit", - committer_date=( - datetime.now() - relativedelta.relativedelta(seconds=3) - ).isoformat(), - ) - create_tag("1.0.0") + util.create_file_and_commit("feat: initial commit") + util.create_tag("1.0.0") - create_file_and_commit( - "feat: commit 1", - committer_date=( - datetime.now() - relativedelta.relativedelta(seconds=2) - ).isoformat(), - ) - create_tag("1-not-a-version") + util.create_file_and_commit("feat: commit 1") + util.create_tag("1-not-a-version") - create_file_and_commit( - "feat: commit 2", - committer_date=( - datetime.now() - relativedelta.relativedelta(seconds=1) - ).isoformat(), - ) + util.create_file_and_commit("feat: commit 2") - create_file_and_commit("bump: version 1.0.0 → 2.0.0") - create_tag("2.0.0") + util.create_file_and_commit("bump: version 1.0.0 → 2.0.0") + util.create_tag("2.0.0") - mocker.patch("commitizen.git.GitTag.date", "2022-02-13") write_patch = mocker.patch("commitizen.commands.changelog.out.write") changelog = Changelog( @@ -1476,6 +1309,7 @@ def test_changelog_template_option_precedence( arg: str, cfg: str, expected: str, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) cfg_template = project_root / "changelog.cfg" @@ -1487,7 +1321,7 @@ def test_changelog_template_option_precedence( cmd_template.write_text("from cmd") default_template.write_text("default") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") if cfg: pyproject = project_root / "pyproject.toml" @@ -1501,11 +1335,10 @@ def test_changelog_template_option_precedence( ) ) - testargs = ["cz", "changelog"] + testargs = ["changelog"] if arg: testargs.append(arg) - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli(*testargs) out = changelog.read_text() assert out == expected @@ -1516,6 +1349,7 @@ def test_changelog_template_extras_precedence( tmp_commitizen_project: Path, mock_plugin: BaseCommitizen, any_changelog_format: ChangelogFormat, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) changelog_tpl = project_root / any_changelog_format.template @@ -1538,11 +1372,9 @@ def test_changelog_template_extras_precedence( ) ) - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "changelog", "--extra", "first=from-command"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "--extra", "first=from-command") changelog = project_root / any_changelog_format.default_changelog_file assert changelog.read_text() == "from-command - from-config - from-plugin" @@ -1554,20 +1386,18 @@ def test_changelog_only_tag_matching_tag_format_included_prefix( mocker: MockFixture, changelog_path: Path, config_path: Path, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.write('\ntag_format = "custom${version}"\n') - create_file_and_commit("feat: new file") - git.tag("v0.2.0") - create_file_and_commit("feat: another new file") - git.tag("0.2.0") - git.tag("random0.2.0") - testargs = ["cz", "bump", "--changelog", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: another new file") - cli.main() + util.create_file_and_commit("feat: new file") + util.create_tag("v0.2.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("0.2.0") + util.create_tag("random0.2.0") + util.run_cli("bump", "--changelog", "--yes") + util.create_file_and_commit("feat: another new file") + util.run_cli("bump", "--changelog", "--yes") with open(changelog_path) as f: out = f.read() assert out.startswith("## custom0.3.0 (2021-06-11)") @@ -1580,25 +1410,21 @@ def test_changelog_only_tag_matching_tag_format_included_prefix_sep( mocker: MockFixture, changelog_path: Path, config_path: Path, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.write('\ntag_format = "custom-${version}"\n') - create_file_and_commit("feat: new file") - git.tag("v0.2.0") - create_file_and_commit("feat: another new file") - git.tag("0.2.0") - git.tag("random0.2.0") - wait_for_tag() - testargs = ["cz", "bump", "--changelog", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new file") + util.create_tag("v0.2.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("0.2.0") + util.create_tag("random0.2.0") + util.run_cli("bump", "--changelog", "--yes") with open(changelog_path) as f: out = f.read() - create_file_and_commit("feat: new version another new file") - create_file_and_commit("feat: new version some new file") - testargs = ["cz", "bump", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new version another new file") + util.create_file_and_commit("feat: new version some new file") + util.run_cli("bump", "--changelog") with open(changelog_path) as f: out = f.read() assert out.startswith("## custom-0.3.0") @@ -1609,26 +1435,23 @@ def test_changelog_only_tag_matching_tag_format_included_prefix_sep( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2021-06-11") def test_changelog_only_tag_matching_tag_format_included_suffix( - mocker: MockFixture, changelog_path: Path, config_path: Path, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.write('\ntag_format = "${version}custom"\n') - create_file_and_commit("feat: new file") - git.tag("v0.2.0") - create_file_and_commit("feat: another new file") - git.tag("0.2.0") - git.tag("random0.2.0") - testargs = ["cz", "bump", "--changelog", "--yes"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat: new file") + util.create_tag("v0.2.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("0.2.0") + util.create_tag("random0.2.0") # bump to 0.2.0custom - cli.main() - wait_for_tag() - create_file_and_commit("feat: another new file") + util.run_cli("bump", "--changelog", "--yes") + + util.create_file_and_commit("feat: another new file") # bump to 0.3.0custom - cli.main() - wait_for_tag() + util.run_cli("bump", "--changelog", "--yes") with open(changelog_path) as f: out = f.read() assert out.startswith("## 0.3.0custom (2021-06-11)") @@ -1639,24 +1462,20 @@ def test_changelog_only_tag_matching_tag_format_included_suffix( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2021-06-11") def test_changelog_only_tag_matching_tag_format_included_suffix_sep( - mocker: MockFixture, changelog_path: Path, config_path: Path, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.write('\ntag_format = "${version}-custom"\n') - create_file_and_commit("feat: new file") - git.tag("v0.2.0") - create_file_and_commit("feat: another new file") - git.tag("0.2.0") - git.tag("random0.2.0") - testargs = ["cz", "bump", "--changelog", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() - wait_for_tag() - create_file_and_commit("feat: another new file") - cli.main() - wait_for_tag() + util.create_file_and_commit("feat: new file") + util.create_tag("v0.2.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("0.2.0") + util.create_tag("random0.2.0") + util.run_cli("bump", "--changelog", "--yes") + util.create_file_and_commit("feat: another new file") + util.run_cli("bump", "--changelog", "--yes") with open(changelog_path) as f: out = f.read() assert out.startswith("## 0.3.0-custom (2021-06-11)") @@ -1669,6 +1488,7 @@ def test_changelog_legacy_tags( mocker: MockFixture, changelog_path: Path, config_path: Path, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.writelines( @@ -1680,17 +1500,15 @@ def test_changelog_legacy_tags( "]\n", ] ) - create_file_and_commit("feat: new file") - git.tag("oldest-0.1.0") - create_file_and_commit("feat: new file") - git.tag("older-0.2.0") - create_file_and_commit("feat: another new file") - git.tag("v0.3.0") - create_file_and_commit("feat: another new file") - git.tag("not-0.3.1") - testargs = ["cz", "bump", "--changelog", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new file") + util.create_tag("oldest-0.1.0") + util.create_file_and_commit("feat: new file") + util.create_tag("older-0.2.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("v0.3.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("not-0.3.1") + util.run_cli("bump", "--changelog", "--yes") out = open(changelog_path).read() assert "## v0.3.0" in out assert "## older-0.2.0" in out @@ -1706,8 +1524,9 @@ def test_changelog_incremental_change_tag_format( changelog_path: Path, config_path: Path, file_regression: FileRegressionFixture, + util: UtilFixture, ): - mocker.patch("commitizen.git.GitTag.date", "2024-11-18") + util.freezer.move_to("2024-11-18") config = Path(config_path) base_config = config.read_text() config.write_text( @@ -1718,12 +1537,11 @@ def test_changelog_incremental_change_tag_format( ) ) ) - create_file_and_commit("feat: new file") - git.tag("older-0.1.0") - create_file_and_commit("feat: new file") - git.tag("older-0.2.0") - mocker.patch.object(sys, "argv", ["cz", "changelog"]) - cli.main() + util.create_file_and_commit("feat: new file") + util.create_tag("older-0.1.0") + util.create_file_and_commit("feat: new file") + util.create_tag("older-0.2.0") + util.run_cli("changelog") config.write_text( "\n".join( @@ -1734,10 +1552,9 @@ def test_changelog_incremental_change_tag_format( ) ) ) - create_file_and_commit("feat: another new file") - git.tag("v0.3.0") - mocker.patch.object(sys, "argv", ["cz", "changelog", "--incremental"]) - cli.main() + util.create_file_and_commit("feat: another new file") + util.create_tag("v0.3.0") + util.run_cli("changelog", "--incremental") out = open(changelog_path).read() assert "## v0.3.0" in out assert "## older-0.2.0" in out @@ -1751,6 +1568,7 @@ def test_changelog_ignored_tags( changelog_path: Path, config_path: Path, capsys: pytest.CaptureFixture, + util: UtilFixture, ): with open(config_path, "a", encoding="utf-8") as f: f.writelines( @@ -1762,17 +1580,15 @@ def test_changelog_ignored_tags( "]\n", ] ) - create_file_and_commit("feat: new file") - git.tag("ignore-0.1.0") - create_file_and_commit("feat: new file") - git.tag("ignored") - create_file_and_commit("feat: another new file") - git.tag("v0.3.0") - create_file_and_commit("feat: another new file") - git.tag("not-ignored") - testargs = ["cz", "bump", "--changelog", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new file") + util.create_tag("ignore-0.1.0") + util.create_file_and_commit("feat: new file") + util.create_tag("ignored") + util.create_file_and_commit("feat: another new file") + util.create_tag("v0.3.0") + util.create_file_and_commit("feat: another new file") + util.create_tag("not-ignored") + util.run_cli("bump", "--changelog", "--yes") out = open(changelog_path).read() _, err = capsys.readouterr() assert "## ignore-0.1.0" not in out @@ -1786,18 +1602,17 @@ def test_changelog_ignored_tags( def test_changelog_template_extra_quotes( - mocker: MockFixture, tmp_commitizen_project: Path, any_changelog_format: ChangelogFormat, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("{{first}} - {{second}} - {{third}}") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = [ - "cz", + util.run_cli( "changelog", "-e", "first=no-quote", @@ -1805,9 +1620,7 @@ def test_changelog_template_extra_quotes( "second='single quotes'", "-e", 'third="double quotes"', - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + ) changelog = project_root / any_changelog_format.default_changelog_file assert changelog.read_text() == "no-quote - single quotes - double quotes" @@ -1822,21 +1635,19 @@ def test_changelog_template_extra_quotes( ), ) def test_changelog_template_extra_weird_but_valid( - mocker: MockFixture, tmp_commitizen_project: Path, any_changelog_format: ChangelogFormat, extra: str, - expected, + expected: str, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("{{key}}") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "changelog", "-e", extra] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("changelog", "-e", extra) changelog = project_root / any_changelog_format.default_changelog_file assert changelog.read_text() == expected @@ -1844,36 +1655,32 @@ def test_changelog_template_extra_weird_but_valid( @pytest.mark.parametrize("extra", ("no-equal", "", "=no-key")) def test_changelog_template_extra_bad_format( - mocker: MockFixture, tmp_commitizen_project: Path, any_changelog_format: ChangelogFormat, extra: str, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "changelog", "-e", extra] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(InvalidCommandArgumentError): - cli.main() + util.run_cli("changelog", "-e", extra) def test_export_changelog_template_from_default( - mocker: MockFixture, tmp_commitizen_project: Path, any_changelog_format: ChangelogFormat, + util: UtilFixture, + repo_root: Path, ): project_root = Path(tmp_commitizen_project) target = project_root / "changelog.jinja" - src = Path(commitizen_init).parent / "templates" / any_changelog_format.template - - args = ["cz", "changelog", "--export-template", str(target)] + src = repo_root / "commitizen" / "templates" / any_changelog_format.template - mocker.patch.object(sys, "argv", args) - cli.main() + util.run_cli("changelog", "--export-template", str(target)) assert target.exists() assert target.read_text() == src.read_text() diff --git a/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_alpha_.md b/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_alpha_.md index dca7824480..f20281df71 100644 --- a/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_alpha_.md +++ b/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_alpha_.md @@ -10,4 +10,4 @@ - mama gotta work - output glitch -## 1.0.0 (1970-01-01) +## 1.0.0 (2025-12-29) diff --git a/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_beta_.md b/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_beta_.md index dca7824480..f20281df71 100644 --- a/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_beta_.md +++ b/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_beta_.md @@ -10,4 +10,4 @@ - mama gotta work - output glitch -## 1.0.0 (1970-01-01) +## 1.0.0 (2025-12-29) diff --git a/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_rc_.md b/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_rc_.md index dca7824480..f20281df71 100644 --- a/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_rc_.md +++ b/tests/commands/test_changelog_command/test_changelog_config_flag_merge_prerelease_rc_.md @@ -10,4 +10,4 @@ - mama gotta work - output glitch -## 1.0.0 (1970-01-01) +## 1.0.0 (2025-12-29) diff --git a/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_alpha_.md b/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_alpha_.md index dca7824480..f20281df71 100644 --- a/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_alpha_.md +++ b/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_alpha_.md @@ -10,4 +10,4 @@ - mama gotta work - output glitch -## 1.0.0 (1970-01-01) +## 1.0.0 (2025-12-29) diff --git a/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_beta_.md b/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_beta_.md index dca7824480..f20281df71 100644 --- a/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_beta_.md +++ b/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_beta_.md @@ -10,4 +10,4 @@ - mama gotta work - output glitch -## 1.0.0 (1970-01-01) +## 1.0.0 (2025-12-29) diff --git a/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_rc_.md b/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_rc_.md index dca7824480..f20281df71 100644 --- a/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_rc_.md +++ b/tests/commands/test_changelog_command/test_changelog_release_candidate_version_with_merge_prerelease_rc_.md @@ -10,4 +10,4 @@ - mama gotta work - output glitch -## 1.0.0 (1970-01-01) +## 1.0.0 (2025-12-29) diff --git a/tests/conftest.py b/tests/conftest.py index dc68da555a..b7f9b2fde8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,7 +16,6 @@ from commitizen.config import BaseConfig from commitizen.cz import registry from commitizen.cz.base import BaseCommitizen -from tests.utils import create_file_and_commit if TYPE_CHECKING: from collections.abc import Iterator, Mapping @@ -24,11 +23,16 @@ from pytest_mock import MockerFixture from commitizen.question import CzQuestion + from tests.utils import UtilFixture SIGNER = "GitHub Action" SIGNER_MAIL = "action@github.com" +pytest_plugins = [ + "tests.utils", +] + @pytest.fixture def repo_root() -> Path: @@ -83,7 +87,7 @@ def tmp_commitizen_project(tmp_git_project): @pytest.fixture(scope="function") -def tmp_commitizen_project_initial(tmp_git_project): +def tmp_commitizen_project_initial(tmp_git_project, util: UtilFixture): def _initial( config_extra: str | None = None, version="0.1.0", @@ -102,7 +106,7 @@ def _initial( ) if config_extra: tmp_commitizen_cfg_file.write(config_extra, mode="a") - create_file_and_commit(initial_commit) + util.create_file_and_commit(initial_commit) return tmp_git_project diff --git a/tests/utils.py b/tests/utils.py index f5557f76d6..57161d83b1 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,15 +1,20 @@ from __future__ import annotations -import time +import sys import uuid +from dataclasses import dataclass +from datetime import datetime from pathlib import Path from typing import TYPE_CHECKING, NamedTuple -from deprecated import deprecated +import pytest -from commitizen import cmd, exceptions, git +from commitizen import cli, cmd, exceptions, git if TYPE_CHECKING: + from freezegun.api import FrozenDateTimeFactory + from pytest_mock import MockerFixture + from commitizen.version_schemes import Increment, Prerelease @@ -61,36 +66,106 @@ def merge_branch(branch: str): raise exceptions.GitCommandError(c.err) -def get_current_branch() -> str: - c = cmd.run("git rev-parse --abbrev-ref HEAD") - if c.return_code != 0: - raise exceptions.GitCommandError(c.err) - return c.out - - def create_tag(tag: str, message: str | None = None) -> None: c = git.tag(tag, annotated=(message is not None), msg=message) if c.return_code != 0: raise exceptions.CommitError(c.err) -@deprecated( - reason="\n\ -Prefer using `create_file_and_commit(filename, committer_date={your_date})` to influence the order of tags.\n\ -This is because lightweight tags (like the ones created here) use the commit's creatordate which we can specify \ -with the GIT_COMMITTER_DATE flag, instead of waiting entire seconds during tests." -) -def wait_for_tag(): - """Deprecated -- use `create_file_and_commit(filename, committer_date={your_date})` to order tags instead - - Wait for tag. - - The resolution of timestamps is 1 second, so we need to wait - to create another tag unfortunately. - - This means: - If we create 2 tags under the same second, they might be returned in the wrong order +@dataclass +class UtilFixture: + """ + An helper fixture providing most common operations for tests. - See https://stackoverflow.com/questions/28237043/what-is-the-resolution-of-gits-commit-date-or-author-date-timestamps + git and cli operations grant control over time. """ - time.sleep(1.1) + + mocker: MockerFixture + monkeypatch: pytest.MonkeyPatch + freezer: FrozenDateTimeFactory + + def __post_init__(self): + self.patch_env() + + def create_file_and_commit( + self, + message: str, + filename: str | None = None, + committer_date: str | None = None, + ) -> None: + """Create a file and commit it.""" + if not filename: + filename = str(uuid.uuid4()) + + Path(filename).touch() + c = cmd.run("git add .") + if c.return_code != 0: + raise exceptions.CommitError(c.err) + c = git.commit(message, committer_date=committer_date) + if c.return_code != 0: + raise exceptions.CommitError(c.err) + self.tick() + + def create_branch(self, name: str) -> None: + """Create a new branch.""" + c = cmd.run(f"git branch {name}") + if c.return_code != 0: + raise exceptions.GitCommandError(c.err) + + def switch_branch(self, branch: str) -> None: + """Switch to given branch.""" + c = cmd.run(f"git switch {branch}") + if c.return_code != 0: + raise exceptions.GitCommandError(c.err) + + def merge_branch(self, branch: str) -> None: + """Merge given branch into current branch.""" + c = cmd.run(f"git merge {branch}") + if c.return_code != 0: + raise exceptions.GitCommandError(c.err) + self.tick() + + def get_current_branch(self) -> str: + """Get current git branch name.""" + c = cmd.run("git rev-parse --abbrev-ref HEAD") + if c.return_code != 0: + raise exceptions.GitCommandError(c.err) + return c.out + + def create_tag( + self, tag: str, message: str | None = None, annotated: bool | None = None + ) -> None: + """Create a git tag.""" + c = git.tag( + tag, annotated=(annotated is True or message is not None), msg=message + ) + if c.return_code != 0: + raise exceptions.CommitError(c.err) + self.tick() + + def run_cli(self, *args: str) -> None: + """Execute commitizen CLI with given args.""" + self.mocker.patch.object(sys, "argv", ["cz", *args]) + cli.main() + self.tick() + + def patch_env(self) -> None: + """Patch environment variables to sync with FreezeGun time.""" + self.monkeypatch.setenv("DATE", datetime.now().isoformat()) + self.monkeypatch.setenv("GIT_AUTHOR_DATE", datetime.now().isoformat()) + self.monkeypatch.setenv("GIT_COMMITTER_DATE", datetime.now().isoformat()) + + def tick(self) -> None: + """Advance time by 1 second.""" + self.freezer.tick() + self.patch_env() + + +@pytest.fixture +def util( + monkeypatch: pytest.MonkeyPatch, + mocker: MockerFixture, + freezer: FrozenDateTimeFactory, +) -> UtilFixture: + """An helper fixture""" + return UtilFixture(mocker=mocker, monkeypatch=monkeypatch, freezer=freezer) From 01f424ca618ac75c70dca3f1e6defe743b1c5b54 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 29 Dec 2025 19:15:51 +0100 Subject: [PATCH 154/221] build(tox): use `tox-uv` to automatically install required Python versions --- pyproject.toml | 2 +- uv.lock | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ac66146d96..8e2f1eadba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ semver = "commitizen.version_schemes:SemVer" semver2 = "commitizen.version_schemes:SemVer2" [dependency-groups] -dev = ["ipython>=8.0", "tox>4", "poethepoet>=0.34.0"] +dev = ["ipython>=8.0", "tox>4", "tox-uv", "poethepoet>=0.34.0"] test = [ "pytest>=7.2", diff --git a/uv.lock b/uv.lock index d7a1b2511c..202ed0d5a8 100644 --- a/uv.lock +++ b/uv.lock @@ -219,6 +219,7 @@ dev = [ { name = "ipython", version = "9.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "poethepoet" }, { name = "tox" }, + { name = "tox-uv" }, ] documentation = [ { name = "mkdocs" }, @@ -270,6 +271,7 @@ dev = [ { name = "ipython", specifier = ">=8.0" }, { name = "poethepoet", specifier = ">=0.34.0" }, { name = "tox", specifier = ">4" }, + { name = "tox-uv" }, ] documentation = [ { name = "mkdocs", specifier = ">=1.4.2" }, @@ -1501,6 +1503,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl", hash = "sha256:451e81dc02ba8d1ed20efd52ee409641ae4b5d5830e008af10fe8823ef1bd551", size = 175905, upload-time = "2025-10-24T18:03:36.337Z" }, ] +[[package]] +name = "tox-uv" +version = "1.29.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tox" }, + { name = "uv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/90/06752775b8cfadba8856190f5beae9f552547e0f287e0246677972107375/tox_uv-1.29.0.tar.gz", hash = "sha256:30fa9e6ad507df49d3c6a2f88894256bcf90f18e240a00764da6ecab1db24895", size = 23427, upload-time = "2025-10-09T20:40:27.384Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/17/221d62937c4130b044bb437caac4181e7e13d5536bbede65264db1f0ac9f/tox_uv-1.29.0-py3-none-any.whl", hash = "sha256:b1d251286edeeb4bc4af1e24c8acfdd9404700143c2199ccdbb4ea195f7de6cc", size = 17254, upload-time = "2025-10-09T20:40:25.885Z" }, +] + [[package]] name = "traitlets" version = "5.14.3" @@ -1573,6 +1590,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, ] +[[package]] +name = "uv" +version = "0.9.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/20/c7598c4a8b0a7d19a1927287876d5fabb4ad5150103c9b751740bea33396/uv-0.9.20.tar.gz", hash = "sha256:a8b45804a84e5dfd01127abea663f7ca508551cd705e3476cc050751e5788b32", size = 3832559, upload-time = "2025-12-29T20:54:08.844Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/2e/ff66dbb7389f03097ff83e4d08c093f32bed96752df58b9992ec5e7aa0ea/uv-0.9.20-py3-none-linux_armv6l.whl", hash = "sha256:025ff1890f7ae2ea93a6c9ba326d25e56ba6d9e4f05c372b82ff5a947d21c400", size = 21294993, upload-time = "2025-12-29T20:54:23.877Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e0/5c14ac09dfebda68df962524cd191c5a4d7e0b02ac5503c34dce6788ffe6/uv-0.9.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:94f716f0e6e609d8c6804faa74797024c43e7aa2ea876778fa16ceb68dc4d80a", size = 20487595, upload-time = "2025-12-29T20:54:26.506Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ba/089a115a898a8729074fcc2bf00dfbf8a90ef79eadf738b531c89794528e/uv-0.9.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:288fdf29b22b3034285e244c006bcdf5575e35fe14f1f2dd55bbb477d6c22d99", size = 18972327, upload-time = "2025-12-29T20:54:31.292Z" }, + { url = "https://files.pythonhosted.org/packages/b8/9f/3a880df832196a4113ed5b16322bd6d6cc21b80338406f2bdab7cbc31361/uv-0.9.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:44076e26038fe37bd6aad7aaf411b72006ec01f124af3c1227d47a3fafa11b1b", size = 20825991, upload-time = "2025-12-29T20:54:21.359Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c1/5b4bdc9b4637f061955200eda21d2285701b8dd979d745a9f5ac2f789abb/uv-0.9.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b66e83fa1558b322194a297e9477e7e49f31136f95b88830a971ba23d8778fb5", size = 20885060, upload-time = "2025-12-29T20:54:10.973Z" }, + { url = "https://files.pythonhosted.org/packages/4d/11/9c44cea9b30dda6a9268d3496aae0c83afa6096afa83559de33181877ab8/uv-0.9.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ae848f6760fce321a2be6cc98b37a31353178295c9e0ebb64e70be8a3c73b07", size = 21992898, upload-time = "2025-12-29T20:54:49.959Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/6d5eaefec10ef5aceeb0957ebd49afede80c446354ecb463cc8f457144da/uv-0.9.20-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:47cda4b2dcdfb55fb4d77fe3ef138d30e89d69e138e96c30325509462e4c4386", size = 23540946, upload-time = "2025-12-29T20:54:15.976Z" }, + { url = "https://files.pythonhosted.org/packages/df/87/a8ce66e5ee35351a2c50f9cf125407e582e1d790e78cad79b614944f3f4a/uv-0.9.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7551cd1a3a1516583021d43b2daef41ce36c2249aa19de10c0f108264099388", size = 23156794, upload-time = "2025-12-29T20:54:03.745Z" }, + { url = "https://files.pythonhosted.org/packages/c4/43/ca9653caba6123f83842ac81de2411316570fda3b7a5916c2b1ef858ab5a/uv-0.9.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143783954e48abaea83d100eb7ca70a614c089d5933b55d59a5638d630b3f7c3", size = 22225527, upload-time = "2025-12-29T20:54:06.663Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a4/f88d4e6806894a37b4018edfd196cd3689194e6ecbcee05fd7ae5ed4cf6f/uv-0.9.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d86724ae303c80d52712b335cfc9f1b5aa785244c18905fd605067303a305854", size = 22205705, upload-time = "2025-12-29T20:54:44.766Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bc/202cfb8d47f83b633502b0b32e00abc019f91255e54aa6672a87495ef06c/uv-0.9.20-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:19e4ce680230f9148c777af4664a6a534821222dd4e8f06844c3d23b79e4778b", size = 20943437, upload-time = "2025-12-29T20:54:34.237Z" }, + { url = "https://files.pythonhosted.org/packages/a3/15/de8ecbf504c96cfb5af7fdf621e5497f0496a403d0883c31ee97702b97db/uv-0.9.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:02383c09eadd2518afb0eebbc651d74b2dd59ad5818d28037cbf7bcef76f8b56", size = 22071434, upload-time = "2025-12-29T20:54:47.395Z" }, + { url = "https://files.pythonhosted.org/packages/30/32/283604c72142e4550f04252d53ab591ed71a178ae044b3debbea1700018c/uv-0.9.20-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:277a7fc7e5229a809e6cc4dacc936dea1fa7260fb5802895ddbba0873fc4b6ec", size = 20838373, upload-time = "2025-12-29T20:54:28.975Z" }, + { url = "https://files.pythonhosted.org/packages/c4/d4/c56a14ae2a693260d227e60358f09f924b7e347bed4aef7a85f4d52e06f5/uv-0.9.20-py3-none-musllinux_1_1_i686.whl", hash = "sha256:c9a073116da198b0533e80828d765bbb30137eef37de68cbc3d21b0f614c843d", size = 21399009, upload-time = "2025-12-29T20:54:13.458Z" }, + { url = "https://files.pythonhosted.org/packages/99/35/e717a53df2d579fd57e9236ef3e13d9127c34e006c6ea1bb4294164d04df/uv-0.9.20-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:56bb00bc0d13f9e4913ef773f31659423faaffe408f6c24b24e25f2c1d5a93cf", size = 22426264, upload-time = "2025-12-29T20:54:37.053Z" }, + { url = "https://files.pythonhosted.org/packages/d4/18/563fc6703e882167b39270db83a57e36834b0d75a51c97a9e5e30a5b2a47/uv-0.9.20-py3-none-win32.whl", hash = "sha256:e620adcbd2e6d714e26928c1674af4581ba9e4b74c38745d6987b4d323d80edc", size = 20034131, upload-time = "2025-12-29T20:54:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/c8/32/3359f7afeebadcaa472535f72ca48dc2d7f234de8570039ee556b470734e/uv-0.9.20-py3-none-win_amd64.whl", hash = "sha256:42d43b6cb7d84a3d4fce8a8a46f0b2c6c8b5d58b3b8062980cbfdb65b559fa8f", size = 22203935, upload-time = "2025-12-29T20:54:18.997Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c4/65fd3981884a51971135547ebb0dddc5c32161374f90e162aca227f4832f/uv-0.9.20-py3-none-win_arm64.whl", hash = "sha256:d63f501a95ef74ea6d2004665eb2ae65429d039150f2c2e6bc12efb6e03fd702", size = 20578093, upload-time = "2025-12-29T20:54:41.944Z" }, +] + [[package]] name = "virtualenv" version = "20.35.4" From 5519b06f5717aa70d2b95a2dd24a96ac49d01570 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 29 Dec 2025 19:17:58 +0100 Subject: [PATCH 155/221] test(snapshots): provide a `test:regen` command to regenerate all snapshots, including those depending on Python version --- docs/contributing.md | 1 + pyproject.toml | 6 ++++++ tests/commands/test_common_command.py | 7 ++----- tests/conftest.py | 10 +++++++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index 0e3ae4df0f..750fb0bc18 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -64,6 +64,7 @@ If you're a first-time contributor, please check out issues labeled [good first - Run the full test suite: `uv run poe all` - Ensure test coverage doesn't drop (we use [CodeCov](https://app.codecov.io/gh/commitizen-tools/commitizen)) - For documentation changes, run `uv run poe doc` to check for warnings/errors + - If you need to change some file regression snapshots, run: `uv run poe test:regen` 4. **Committing Changes** - Use Commitizen to make commits (we follow [conventional commits](https://www.conventionalcommits.org/)) - Example: `cz commit` diff --git a/pyproject.toml b/pyproject.toml index 8e2f1eadba..8ec4e8e16e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -267,6 +267,12 @@ test.cmd = "pytest -n auto --dist=loadfile" "test:all".help = "Run the test suite on all supported Python versions" "test:all".cmd = "tox --parallel" +"test:regen".help = "Regenerate the test fixtures" +"test:regen".parallel = [ + { ref = "test -k 'not py_' --regen-all" }, + { ref = "test:all -- -k py_ --regen-all" }, +] + cover.help = "Run the test suite with coverage" cover.ref = "test --cov-report term-missing --cov-report=xml:coverage.xml --cov=commitizen --junitxml=junit.xml -o junit_family=legacy" diff --git a/tests/commands/test_common_command.py b/tests/commands/test_common_command.py index 71ade5eda4..bb9de90bbe 100644 --- a/tests/commands/test_common_command.py +++ b/tests/commands/test_common_command.py @@ -7,10 +7,6 @@ from commitizen.commands import Example, Info, ListCz, Schema -@pytest.mark.skipif( - sys.version_info < (3, 13), - reason="The output message of argparse is different between Python 3.13 and lower than Python 3.13", -) @pytest.mark.parametrize( "command", [ @@ -26,6 +22,7 @@ "version", ], ) +@pytest.mark.usefixtures("python_version") def test_command_shows_description_when_use_help_option( mocker: MockFixture, capsys, @@ -35,7 +32,7 @@ def test_command_shows_description_when_use_help_option( ): """Test that the command shows the description when the help option is used. - Note: If the command description changes, please run `pytest tests/commands/test_common_command.py --regen-all` to regenerate the test files. + Note: If the command description changes, please run `poe test:regen` to regenerate the test files. """ # Force consistent terminal output monkeypatch.setenv("COLUMNS", "80") diff --git a/tests/conftest.py b/tests/conftest.py index b7f9b2fde8..d7fb6a23de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,9 +2,10 @@ import os import re +import sys import tempfile from pathlib import Path -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast import pytest @@ -28,6 +29,7 @@ SIGNER = "GitHub Action" SIGNER_MAIL = "action@github.com" +PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}" pytest_plugins = [ "tests.utils", @@ -294,3 +296,9 @@ def any_changelog_format(config: BaseConfig) -> ChangelogFormat: """For test not relying on formats specifics, use the default""" config.settings["changelog_format"] = defaults.CHANGELOG_FORMAT return get_changelog_format(config) + + +@pytest.fixture(params=[pytest.param(PYTHON_VERSION, id=f"py_{PYTHON_VERSION}")]) +def python_version(request: pytest.FixtureRequest) -> str: + """The current python version in '{major}.{minor}' format""" + return cast("str", request.param) From 4cb3f95f1fd93d8f9ab49d8553519888a9c62d87 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 29 Dec 2025 19:33:19 +0100 Subject: [PATCH 156/221] test(snapshots): regenerate snapshots for all Python versions --- ...ion_when_use_help_option_py_3_10_bump_.txt | 82 +++++++++++++++++++ ...hen_use_help_option_py_3_10_changelog_.txt | 42 ++++++++++ ...on_when_use_help_option_py_3_10_check_.txt | 28 +++++++ ...n_when_use_help_option_py_3_10_commit_.txt | 22 +++++ ...when_use_help_option_py_3_10_example_.txt} | 0 ...on_when_use_help_option_py_3_10_info_.txt} | 0 ...on_when_use_help_option_py_3_10_init_.txt} | 0 ...tion_when_use_help_option_py_3_10_ls_.txt} | 0 ..._when_use_help_option_py_3_10_schema_.txt} | 0 ...when_use_help_option_py_3_10_version_.txt} | 0 ...ion_when_use_help_option_py_3_11_bump_.txt | 82 +++++++++++++++++++ ...hen_use_help_option_py_3_11_changelog_.txt | 42 ++++++++++ ...on_when_use_help_option_py_3_11_check_.txt | 28 +++++++ ...n_when_use_help_option_py_3_11_commit_.txt | 22 +++++ ..._when_use_help_option_py_3_11_example_.txt | 6 ++ ...ion_when_use_help_option_py_3_11_info_.txt | 6 ++ ...ion_when_use_help_option_py_3_11_init_.txt | 6 ++ ...ption_when_use_help_option_py_3_11_ls_.txt | 6 ++ ...n_when_use_help_option_py_3_11_schema_.txt | 6 ++ ..._when_use_help_option_py_3_11_version_.txt | 16 ++++ ...ion_when_use_help_option_py_3_12_bump_.txt | 82 +++++++++++++++++++ ...hen_use_help_option_py_3_12_changelog_.txt | 42 ++++++++++ ...on_when_use_help_option_py_3_12_check_.txt | 28 +++++++ ...n_when_use_help_option_py_3_12_commit_.txt | 22 +++++ ..._when_use_help_option_py_3_12_example_.txt | 6 ++ ...ion_when_use_help_option_py_3_12_info_.txt | 6 ++ ...ion_when_use_help_option_py_3_12_init_.txt | 6 ++ ...ption_when_use_help_option_py_3_12_ls_.txt | 6 ++ ...n_when_use_help_option_py_3_12_schema_.txt | 6 ++ ..._when_use_help_option_py_3_12_version_.txt | 16 ++++ ...on_when_use_help_option_py_3_13_bump_.txt} | 0 ...en_use_help_option_py_3_13_changelog_.txt} | 0 ...n_when_use_help_option_py_3_13_check_.txt} | 0 ..._when_use_help_option_py_3_13_commit_.txt} | 0 ..._when_use_help_option_py_3_13_example_.txt | 6 ++ ...ion_when_use_help_option_py_3_13_info_.txt | 6 ++ ...ion_when_use_help_option_py_3_13_init_.txt | 6 ++ ...ption_when_use_help_option_py_3_13_ls_.txt | 6 ++ ...n_when_use_help_option_py_3_13_schema_.txt | 6 ++ ..._when_use_help_option_py_3_13_version_.txt | 16 ++++ ...ion_when_use_help_option_py_3_14_bump_.txt | 81 ++++++++++++++++++ ...hen_use_help_option_py_3_14_changelog_.txt | 41 ++++++++++ ...on_when_use_help_option_py_3_14_check_.txt | 28 +++++++ ...n_when_use_help_option_py_3_14_commit_.txt | 22 +++++ ..._when_use_help_option_py_3_14_example_.txt | 6 ++ ...ion_when_use_help_option_py_3_14_info_.txt | 6 ++ ...ion_when_use_help_option_py_3_14_init_.txt | 6 ++ ...ption_when_use_help_option_py_3_14_ls_.txt | 6 ++ ...n_when_use_help_option_py_3_14_schema_.txt | 6 ++ ..._when_use_help_option_py_3_14_version_.txt | 16 ++++ 50 files changed, 878 insertions(+) create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_example_.txt => test_command_shows_description_when_use_help_option_py_3_10_example_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_info_.txt => test_command_shows_description_when_use_help_option_py_3_10_info_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_init_.txt => test_command_shows_description_when_use_help_option_py_3_10_init_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_ls_.txt => test_command_shows_description_when_use_help_option_py_3_10_ls_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_schema_.txt => test_command_shows_description_when_use_help_option_py_3_10_schema_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_version_.txt => test_command_shows_description_when_use_help_option_py_3_10_version_.txt} (100%) create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_bump_.txt => test_command_shows_description_when_use_help_option_py_3_13_bump_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_changelog_.txt => test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_check_.txt => test_command_shows_description_when_use_help_option_py_3_13_check_.txt} (100%) rename tests/commands/test_common_command/{test_command_shows_description_when_use_help_option_commit_.txt => test_command_shows_description_when_use_help_option_py_3_13_commit_.txt} (100%) create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt create mode 100644 tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt new file mode 100644 index 0000000000..ad0a693278 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt @@ -0,0 +1,82 @@ +usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] + [--no-verify] [--yes] [--tag-format TAG_FORMAT] + [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] + [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] + [--increment-mode {linear,exact}] [--check-consistency] + [--annotated-tag] + [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] + [--changelog-to-stdout] [--git-output-to-stderr] [--retry] + [--major-version-zero] [--template TEMPLATE] [--extra EXTRA] + [--file-name FILE_NAME] [--prerelease-offset PRERELEASE_OFFSET] + [--version-scheme {pep440,semver,semver2}] + [--version-type {pep440,semver,semver2}] + [--build-metadata BUILD_METADATA] [--get-next] + [--allow-no-commit] + [MANUAL_VERSION] + +bump semantic version based on the git log + +positional arguments: + MANUAL_VERSION bump to the given version (e.g: 1.5.3) + +options: + -h, --help show this help message and exit + --dry-run show output to stdout, no commit, no modified files + --files-only bump version in the files from the config + --local-version bump only the local version portion + --changelog, -ch generate the changelog for the newest version + --no-verify this option bypasses the pre-commit and commit-msg + hooks + --yes accept automatically questions done + --tag-format TAG_FORMAT + the format used to tag the commit and read it, use it + in existing projects, wrap around simple quotes + --bump-message BUMP_MESSAGE + template used to create the release commit, useful + when working with CI + --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc} + choose type of prerelease + --devrelease DEVRELEASE, -d DEVRELEASE + specify non-negative integer for dev. release + --increment {MAJOR,MINOR,PATCH} + manually specify the desired increment + --increment-mode {linear,exact} + set the method by which the new version is chosen. + 'linear' (default) guesses the next version based on + typical linear version progression, such that bumping + of a pre-release with lower precedence than the + current pre-release phase maintains the current phase + of higher precedence. 'exact' applies the changes that + have been specified (or determined from the commit + log) without interpretation, such that the increment + and pre-release are always honored + --check-consistency, -cc + check consistency among versions defined in commitizen + configuration and version_files + --annotated-tag, -at create annotated tag instead of lightweight one + --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE + create annotated tag message + --gpg-sign, -s sign tag instead of lightweight one + --changelog-to-stdout + Output changelog to the stdout + --git-output-to-stderr + Redirect git output to stderr + --retry retry commit if it fails the 1st time + --major-version-zero keep major version at zero, even for breaking changes + --template TEMPLATE, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra EXTRA, -e EXTRA + a changelog extra variable (in the form 'key=value') + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --prerelease-offset PRERELEASE_OFFSET + start pre-releases with this offset + --version-scheme {pep440,semver,semver2} + choose version scheme + --version-type {pep440,semver,semver2} + Deprecated, use --version-scheme instead + --build-metadata BUILD_METADATA + Add additional build-metadata to the version-number + --get-next Determine the next version and write to stdout + --allow-no-commit bump version without eligible commits diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt new file mode 100644 index 0000000000..f4aa1ca2a6 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt @@ -0,0 +1,42 @@ +usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] + [--unreleased-version UNRELEASED_VERSION] [--incremental] + [--start-rev START_REV] [--merge-prerelease] + [--version-scheme {pep440,semver,semver2}] + [--export-template EXPORT_TEMPLATE] [--template TEMPLATE] + [--extra EXTRA] [--tag-format TAG_FORMAT] + [rev_range] + +generate changelog (note that it will overwrite existing file) + +positional arguments: + rev_range generates changelog for the given version (e.g: 1.5.3) + or version range (e.g: 1.5.3..1.7.9) + +options: + -h, --help show this help message and exit + --dry-run show changelog to stdout + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --unreleased-version UNRELEASED_VERSION + set the value for the new version (use the tag value), + instead of using unreleased + --incremental generates changelog from last created version, useful + if the changelog has been manually modified + --start-rev START_REV + start rev of the changelog. If not set, it will + generate changelog from the start + --merge-prerelease collect all changes from prereleases into next non- + prerelease. If not set, it will include prereleases in + the changelog + --version-scheme {pep440,semver,semver2} + choose version scheme + --export-template EXPORT_TEMPLATE + Export the changelog template into this file instead + of rendering it + --template TEMPLATE, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra EXTRA, -e EXTRA + a changelog extra variable (in the form 'key=value') + --tag-format TAG_FORMAT + The format of the tag, wrap around simple quotes diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt new file mode 100644 index 0000000000..53c4e7ed10 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt @@ -0,0 +1,28 @@ +usage: cz check [-h] + [--commit-msg-file COMMIT_MSG_FILE | --rev-range REV_RANGE | -d | -m MESSAGE] + [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] + [-l MESSAGE_LENGTH_LIMIT] + +validates that a commit message matches the commitizen schema + +options: + -h, --help show this help message and exit + --commit-msg-file COMMIT_MSG_FILE + ask for the name of the temporal file that contains + the commit message. Using it in a git hook script: + MSG_FILE=$1 + --rev-range REV_RANGE + a range of git rev to check. e.g, master..HEAD + -d, --use-default-range + check from the default branch to HEAD. e.g, + refs/remotes/origin/master..HEAD + -m MESSAGE, --message MESSAGE + commit message that needs to be checked + --allow-abort allow empty commit messages, which typically abort a + commit + --allowed-prefixes [ALLOWED_PREFIXES ...] + allowed commit message prefixes. If the message starts + by one of these prefixes, the message won't be checked + against the regex + -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt new file mode 100644 index 0000000000..c842433427 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt @@ -0,0 +1,22 @@ +usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] + [--write-message-to-file FILE_PATH] [-s] [-a] [-e] + [-l MESSAGE_LENGTH_LIMIT] [--] + +create new commit + +options: + -h, --help show this help message and exit + --retry retry last commit + --no-retry skip retry if retry_after_failure is set to true + --dry-run show output to stdout, no commit, no modified files + --write-message-to-file FILE_PATH + write message to file before committing (can be + combined with --dry-run) + -s, --signoff Deprecated, use 'cz commit -- -s' instead + -a, --all Tell the command to automatically stage files that + have been modified and deleted, but new files you have + not told Git about are not affected. + -e, --edit edit the commit message before committing + -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit + -- Positional arguments separator (recommended) diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_example_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_example_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_example_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_info_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_info_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_info_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_init_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_init_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_init_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_ls_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_ls_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_ls_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_schema_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_schema_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_schema_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_version_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt new file mode 100644 index 0000000000..ad0a693278 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt @@ -0,0 +1,82 @@ +usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] + [--no-verify] [--yes] [--tag-format TAG_FORMAT] + [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] + [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] + [--increment-mode {linear,exact}] [--check-consistency] + [--annotated-tag] + [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] + [--changelog-to-stdout] [--git-output-to-stderr] [--retry] + [--major-version-zero] [--template TEMPLATE] [--extra EXTRA] + [--file-name FILE_NAME] [--prerelease-offset PRERELEASE_OFFSET] + [--version-scheme {pep440,semver,semver2}] + [--version-type {pep440,semver,semver2}] + [--build-metadata BUILD_METADATA] [--get-next] + [--allow-no-commit] + [MANUAL_VERSION] + +bump semantic version based on the git log + +positional arguments: + MANUAL_VERSION bump to the given version (e.g: 1.5.3) + +options: + -h, --help show this help message and exit + --dry-run show output to stdout, no commit, no modified files + --files-only bump version in the files from the config + --local-version bump only the local version portion + --changelog, -ch generate the changelog for the newest version + --no-verify this option bypasses the pre-commit and commit-msg + hooks + --yes accept automatically questions done + --tag-format TAG_FORMAT + the format used to tag the commit and read it, use it + in existing projects, wrap around simple quotes + --bump-message BUMP_MESSAGE + template used to create the release commit, useful + when working with CI + --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc} + choose type of prerelease + --devrelease DEVRELEASE, -d DEVRELEASE + specify non-negative integer for dev. release + --increment {MAJOR,MINOR,PATCH} + manually specify the desired increment + --increment-mode {linear,exact} + set the method by which the new version is chosen. + 'linear' (default) guesses the next version based on + typical linear version progression, such that bumping + of a pre-release with lower precedence than the + current pre-release phase maintains the current phase + of higher precedence. 'exact' applies the changes that + have been specified (or determined from the commit + log) without interpretation, such that the increment + and pre-release are always honored + --check-consistency, -cc + check consistency among versions defined in commitizen + configuration and version_files + --annotated-tag, -at create annotated tag instead of lightweight one + --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE + create annotated tag message + --gpg-sign, -s sign tag instead of lightweight one + --changelog-to-stdout + Output changelog to the stdout + --git-output-to-stderr + Redirect git output to stderr + --retry retry commit if it fails the 1st time + --major-version-zero keep major version at zero, even for breaking changes + --template TEMPLATE, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra EXTRA, -e EXTRA + a changelog extra variable (in the form 'key=value') + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --prerelease-offset PRERELEASE_OFFSET + start pre-releases with this offset + --version-scheme {pep440,semver,semver2} + choose version scheme + --version-type {pep440,semver,semver2} + Deprecated, use --version-scheme instead + --build-metadata BUILD_METADATA + Add additional build-metadata to the version-number + --get-next Determine the next version and write to stdout + --allow-no-commit bump version without eligible commits diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt new file mode 100644 index 0000000000..f4aa1ca2a6 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt @@ -0,0 +1,42 @@ +usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] + [--unreleased-version UNRELEASED_VERSION] [--incremental] + [--start-rev START_REV] [--merge-prerelease] + [--version-scheme {pep440,semver,semver2}] + [--export-template EXPORT_TEMPLATE] [--template TEMPLATE] + [--extra EXTRA] [--tag-format TAG_FORMAT] + [rev_range] + +generate changelog (note that it will overwrite existing file) + +positional arguments: + rev_range generates changelog for the given version (e.g: 1.5.3) + or version range (e.g: 1.5.3..1.7.9) + +options: + -h, --help show this help message and exit + --dry-run show changelog to stdout + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --unreleased-version UNRELEASED_VERSION + set the value for the new version (use the tag value), + instead of using unreleased + --incremental generates changelog from last created version, useful + if the changelog has been manually modified + --start-rev START_REV + start rev of the changelog. If not set, it will + generate changelog from the start + --merge-prerelease collect all changes from prereleases into next non- + prerelease. If not set, it will include prereleases in + the changelog + --version-scheme {pep440,semver,semver2} + choose version scheme + --export-template EXPORT_TEMPLATE + Export the changelog template into this file instead + of rendering it + --template TEMPLATE, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra EXTRA, -e EXTRA + a changelog extra variable (in the form 'key=value') + --tag-format TAG_FORMAT + The format of the tag, wrap around simple quotes diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt new file mode 100644 index 0000000000..53c4e7ed10 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt @@ -0,0 +1,28 @@ +usage: cz check [-h] + [--commit-msg-file COMMIT_MSG_FILE | --rev-range REV_RANGE | -d | -m MESSAGE] + [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] + [-l MESSAGE_LENGTH_LIMIT] + +validates that a commit message matches the commitizen schema + +options: + -h, --help show this help message and exit + --commit-msg-file COMMIT_MSG_FILE + ask for the name of the temporal file that contains + the commit message. Using it in a git hook script: + MSG_FILE=$1 + --rev-range REV_RANGE + a range of git rev to check. e.g, master..HEAD + -d, --use-default-range + check from the default branch to HEAD. e.g, + refs/remotes/origin/master..HEAD + -m MESSAGE, --message MESSAGE + commit message that needs to be checked + --allow-abort allow empty commit messages, which typically abort a + commit + --allowed-prefixes [ALLOWED_PREFIXES ...] + allowed commit message prefixes. If the message starts + by one of these prefixes, the message won't be checked + against the regex + -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt new file mode 100644 index 0000000000..c842433427 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt @@ -0,0 +1,22 @@ +usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] + [--write-message-to-file FILE_PATH] [-s] [-a] [-e] + [-l MESSAGE_LENGTH_LIMIT] [--] + +create new commit + +options: + -h, --help show this help message and exit + --retry retry last commit + --no-retry skip retry if retry_after_failure is set to true + --dry-run show output to stdout, no commit, no modified files + --write-message-to-file FILE_PATH + write message to file before committing (can be + combined with --dry-run) + -s, --signoff Deprecated, use 'cz commit -- -s' instead + -a, --all Tell the command to automatically stage files that + have been modified and deleted, but new files you have + not told Git about are not affected. + -e, --edit edit the commit message before committing + -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit + -- Positional arguments separator (recommended) diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt new file mode 100644 index 0000000000..b9bf7f84fc --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt @@ -0,0 +1,6 @@ +usage: cz example [-h] + +show commit example + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt new file mode 100644 index 0000000000..99b1ba8a4a --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt @@ -0,0 +1,6 @@ +usage: cz info [-h] + +show information about the cz + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt new file mode 100644 index 0000000000..0f72042f88 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt @@ -0,0 +1,6 @@ +usage: cz init [-h] + +init commitizen configuration + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt new file mode 100644 index 0000000000..5fa8fe1f79 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt @@ -0,0 +1,6 @@ +usage: cz ls [-h] + +show available commitizens + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt new file mode 100644 index 0000000000..6666db4d41 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt @@ -0,0 +1,6 @@ +usage: cz schema [-h] + +show commit schema + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt new file mode 100644 index 0000000000..a194615a98 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt @@ -0,0 +1,16 @@ +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] + +get the version of the installed commitizen or the current project (default: +installed commitizen) + +options: + -h, --help show this help message and exit + -r, --report get system information for reporting bugs + -p, --project get the version of the current project + -c, --commitizen get the version of the installed commitizen + -v, --verbose get the version of both the installed commitizen and the + current project + --major get just the major version. Need to be used with --project + or --verbose. + --minor get just the minor version. Need to be used with --project + or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt new file mode 100644 index 0000000000..ad0a693278 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt @@ -0,0 +1,82 @@ +usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] + [--no-verify] [--yes] [--tag-format TAG_FORMAT] + [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] + [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] + [--increment-mode {linear,exact}] [--check-consistency] + [--annotated-tag] + [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] + [--changelog-to-stdout] [--git-output-to-stderr] [--retry] + [--major-version-zero] [--template TEMPLATE] [--extra EXTRA] + [--file-name FILE_NAME] [--prerelease-offset PRERELEASE_OFFSET] + [--version-scheme {pep440,semver,semver2}] + [--version-type {pep440,semver,semver2}] + [--build-metadata BUILD_METADATA] [--get-next] + [--allow-no-commit] + [MANUAL_VERSION] + +bump semantic version based on the git log + +positional arguments: + MANUAL_VERSION bump to the given version (e.g: 1.5.3) + +options: + -h, --help show this help message and exit + --dry-run show output to stdout, no commit, no modified files + --files-only bump version in the files from the config + --local-version bump only the local version portion + --changelog, -ch generate the changelog for the newest version + --no-verify this option bypasses the pre-commit and commit-msg + hooks + --yes accept automatically questions done + --tag-format TAG_FORMAT + the format used to tag the commit and read it, use it + in existing projects, wrap around simple quotes + --bump-message BUMP_MESSAGE + template used to create the release commit, useful + when working with CI + --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc} + choose type of prerelease + --devrelease DEVRELEASE, -d DEVRELEASE + specify non-negative integer for dev. release + --increment {MAJOR,MINOR,PATCH} + manually specify the desired increment + --increment-mode {linear,exact} + set the method by which the new version is chosen. + 'linear' (default) guesses the next version based on + typical linear version progression, such that bumping + of a pre-release with lower precedence than the + current pre-release phase maintains the current phase + of higher precedence. 'exact' applies the changes that + have been specified (or determined from the commit + log) without interpretation, such that the increment + and pre-release are always honored + --check-consistency, -cc + check consistency among versions defined in commitizen + configuration and version_files + --annotated-tag, -at create annotated tag instead of lightweight one + --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE + create annotated tag message + --gpg-sign, -s sign tag instead of lightweight one + --changelog-to-stdout + Output changelog to the stdout + --git-output-to-stderr + Redirect git output to stderr + --retry retry commit if it fails the 1st time + --major-version-zero keep major version at zero, even for breaking changes + --template TEMPLATE, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra EXTRA, -e EXTRA + a changelog extra variable (in the form 'key=value') + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --prerelease-offset PRERELEASE_OFFSET + start pre-releases with this offset + --version-scheme {pep440,semver,semver2} + choose version scheme + --version-type {pep440,semver,semver2} + Deprecated, use --version-scheme instead + --build-metadata BUILD_METADATA + Add additional build-metadata to the version-number + --get-next Determine the next version and write to stdout + --allow-no-commit bump version without eligible commits diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt new file mode 100644 index 0000000000..f4aa1ca2a6 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt @@ -0,0 +1,42 @@ +usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] + [--unreleased-version UNRELEASED_VERSION] [--incremental] + [--start-rev START_REV] [--merge-prerelease] + [--version-scheme {pep440,semver,semver2}] + [--export-template EXPORT_TEMPLATE] [--template TEMPLATE] + [--extra EXTRA] [--tag-format TAG_FORMAT] + [rev_range] + +generate changelog (note that it will overwrite existing file) + +positional arguments: + rev_range generates changelog for the given version (e.g: 1.5.3) + or version range (e.g: 1.5.3..1.7.9) + +options: + -h, --help show this help message and exit + --dry-run show changelog to stdout + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --unreleased-version UNRELEASED_VERSION + set the value for the new version (use the tag value), + instead of using unreleased + --incremental generates changelog from last created version, useful + if the changelog has been manually modified + --start-rev START_REV + start rev of the changelog. If not set, it will + generate changelog from the start + --merge-prerelease collect all changes from prereleases into next non- + prerelease. If not set, it will include prereleases in + the changelog + --version-scheme {pep440,semver,semver2} + choose version scheme + --export-template EXPORT_TEMPLATE + Export the changelog template into this file instead + of rendering it + --template TEMPLATE, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra EXTRA, -e EXTRA + a changelog extra variable (in the form 'key=value') + --tag-format TAG_FORMAT + The format of the tag, wrap around simple quotes diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt new file mode 100644 index 0000000000..53c4e7ed10 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt @@ -0,0 +1,28 @@ +usage: cz check [-h] + [--commit-msg-file COMMIT_MSG_FILE | --rev-range REV_RANGE | -d | -m MESSAGE] + [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] + [-l MESSAGE_LENGTH_LIMIT] + +validates that a commit message matches the commitizen schema + +options: + -h, --help show this help message and exit + --commit-msg-file COMMIT_MSG_FILE + ask for the name of the temporal file that contains + the commit message. Using it in a git hook script: + MSG_FILE=$1 + --rev-range REV_RANGE + a range of git rev to check. e.g, master..HEAD + -d, --use-default-range + check from the default branch to HEAD. e.g, + refs/remotes/origin/master..HEAD + -m MESSAGE, --message MESSAGE + commit message that needs to be checked + --allow-abort allow empty commit messages, which typically abort a + commit + --allowed-prefixes [ALLOWED_PREFIXES ...] + allowed commit message prefixes. If the message starts + by one of these prefixes, the message won't be checked + against the regex + -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt new file mode 100644 index 0000000000..c842433427 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt @@ -0,0 +1,22 @@ +usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] + [--write-message-to-file FILE_PATH] [-s] [-a] [-e] + [-l MESSAGE_LENGTH_LIMIT] [--] + +create new commit + +options: + -h, --help show this help message and exit + --retry retry last commit + --no-retry skip retry if retry_after_failure is set to true + --dry-run show output to stdout, no commit, no modified files + --write-message-to-file FILE_PATH + write message to file before committing (can be + combined with --dry-run) + -s, --signoff Deprecated, use 'cz commit -- -s' instead + -a, --all Tell the command to automatically stage files that + have been modified and deleted, but new files you have + not told Git about are not affected. + -e, --edit edit the commit message before committing + -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit + -- Positional arguments separator (recommended) diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt new file mode 100644 index 0000000000..b9bf7f84fc --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt @@ -0,0 +1,6 @@ +usage: cz example [-h] + +show commit example + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt new file mode 100644 index 0000000000..99b1ba8a4a --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt @@ -0,0 +1,6 @@ +usage: cz info [-h] + +show information about the cz + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt new file mode 100644 index 0000000000..0f72042f88 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt @@ -0,0 +1,6 @@ +usage: cz init [-h] + +init commitizen configuration + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt new file mode 100644 index 0000000000..5fa8fe1f79 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt @@ -0,0 +1,6 @@ +usage: cz ls [-h] + +show available commitizens + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt new file mode 100644 index 0000000000..6666db4d41 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt @@ -0,0 +1,6 @@ +usage: cz schema [-h] + +show commit schema + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt new file mode 100644 index 0000000000..a194615a98 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt @@ -0,0 +1,16 @@ +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] + +get the version of the installed commitizen or the current project (default: +installed commitizen) + +options: + -h, --help show this help message and exit + -r, --report get system information for reporting bugs + -p, --project get the version of the current project + -c, --commitizen get the version of the installed commitizen + -v, --verbose get the version of both the installed commitizen and the + current project + --major get just the major version. Need to be used with --project + or --verbose. + --minor get just the minor version. Need to be used with --project + or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_bump_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_changelog_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_check_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_check_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_check_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_commit_.txt similarity index 100% rename from tests/commands/test_common_command/test_command_shows_description_when_use_help_option_commit_.txt rename to tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_commit_.txt diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt new file mode 100644 index 0000000000..b9bf7f84fc --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt @@ -0,0 +1,6 @@ +usage: cz example [-h] + +show commit example + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt new file mode 100644 index 0000000000..99b1ba8a4a --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt @@ -0,0 +1,6 @@ +usage: cz info [-h] + +show information about the cz + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt new file mode 100644 index 0000000000..0f72042f88 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt @@ -0,0 +1,6 @@ +usage: cz init [-h] + +init commitizen configuration + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt new file mode 100644 index 0000000000..5fa8fe1f79 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt @@ -0,0 +1,6 @@ +usage: cz ls [-h] + +show available commitizens + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt new file mode 100644 index 0000000000..6666db4d41 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt @@ -0,0 +1,6 @@ +usage: cz schema [-h] + +show commit schema + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt new file mode 100644 index 0000000000..a194615a98 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt @@ -0,0 +1,16 @@ +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] + +get the version of the installed commitizen or the current project (default: +installed commitizen) + +options: + -h, --help show this help message and exit + -r, --report get system information for reporting bugs + -p, --project get the version of the current project + -c, --commitizen get the version of the installed commitizen + -v, --verbose get the version of both the installed commitizen and the + current project + --major get just the major version. Need to be used with --project + or --verbose. + --minor get just the minor version. Need to be used with --project + or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt new file mode 100644 index 0000000000..4cf8e6c91b --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt @@ -0,0 +1,81 @@ +usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] + [--no-verify] [--yes] [--tag-format TAG_FORMAT] + [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] + [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] + [--increment-mode {linear,exact}] [--check-consistency] + [--annotated-tag] + [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] + [--changelog-to-stdout] [--git-output-to-stderr] [--retry] + [--major-version-zero] [--template TEMPLATE] [--extra EXTRA] + [--file-name FILE_NAME] [--prerelease-offset PRERELEASE_OFFSET] + [--version-scheme {pep440,semver,semver2}] + [--version-type {pep440,semver,semver2}] + [--build-metadata BUILD_METADATA] [--get-next] + [--allow-no-commit] + [MANUAL_VERSION] + +bump semantic version based on the git log + +positional arguments: + MANUAL_VERSION bump to the given version (e.g: 1.5.3) + +options: + -h, --help show this help message and exit + --dry-run show output to stdout, no commit, no modified files + --files-only bump version in the files from the config + --local-version bump only the local version portion + --changelog, -ch generate the changelog for the newest version + --no-verify this option bypasses the pre-commit and commit-msg + hooks + --yes accept automatically questions done + --tag-format TAG_FORMAT + the format used to tag the commit and read it, use it + in existing projects, wrap around simple quotes + --bump-message BUMP_MESSAGE + template used to create the release commit, useful + when working with CI + --prerelease, -pr {alpha,beta,rc} + choose type of prerelease + --devrelease, -d DEVRELEASE + specify non-negative integer for dev. release + --increment {MAJOR,MINOR,PATCH} + manually specify the desired increment + --increment-mode {linear,exact} + set the method by which the new version is chosen. + 'linear' (default) guesses the next version based on + typical linear version progression, such that bumping + of a pre-release with lower precedence than the + current pre-release phase maintains the current phase + of higher precedence. 'exact' applies the changes that + have been specified (or determined from the commit + log) without interpretation, such that the increment + and pre-release are always honored + --check-consistency, -cc + check consistency among versions defined in commitizen + configuration and version_files + --annotated-tag, -at create annotated tag instead of lightweight one + --annotated-tag-message, -atm ANNOTATED_TAG_MESSAGE + create annotated tag message + --gpg-sign, -s sign tag instead of lightweight one + --changelog-to-stdout + Output changelog to the stdout + --git-output-to-stderr + Redirect git output to stderr + --retry retry commit if it fails the 1st time + --major-version-zero keep major version at zero, even for breaking changes + --template, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra, -e EXTRA a changelog extra variable (in the form 'key=value') + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --prerelease-offset PRERELEASE_OFFSET + start pre-releases with this offset + --version-scheme {pep440,semver,semver2} + choose version scheme + --version-type {pep440,semver,semver2} + Deprecated, use --version-scheme instead + --build-metadata BUILD_METADATA + Add additional build-metadata to the version-number + --get-next Determine the next version and write to stdout + --allow-no-commit bump version without eligible commits diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt new file mode 100644 index 0000000000..91b7f389b5 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt @@ -0,0 +1,41 @@ +usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] + [--unreleased-version UNRELEASED_VERSION] [--incremental] + [--start-rev START_REV] [--merge-prerelease] + [--version-scheme {pep440,semver,semver2}] + [--export-template EXPORT_TEMPLATE] [--template TEMPLATE] + [--extra EXTRA] [--tag-format TAG_FORMAT] + [rev_range] + +generate changelog (note that it will overwrite existing file) + +positional arguments: + rev_range generates changelog for the given version (e.g: 1.5.3) + or version range (e.g: 1.5.3..1.7.9) + +options: + -h, --help show this help message and exit + --dry-run show changelog to stdout + --file-name FILE_NAME + file name of changelog (default: 'CHANGELOG.md') + --unreleased-version UNRELEASED_VERSION + set the value for the new version (use the tag value), + instead of using unreleased + --incremental generates changelog from last created version, useful + if the changelog has been manually modified + --start-rev START_REV + start rev of the changelog. If not set, it will + generate changelog from the start + --merge-prerelease collect all changes from prereleases into next non- + prerelease. If not set, it will include prereleases in + the changelog + --version-scheme {pep440,semver,semver2} + choose version scheme + --export-template EXPORT_TEMPLATE + Export the changelog template into this file instead + of rendering it + --template, -t TEMPLATE + changelog template file name (relative to the current + working directory) + --extra, -e EXTRA a changelog extra variable (in the form 'key=value') + --tag-format TAG_FORMAT + The format of the tag, wrap around simple quotes diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt new file mode 100644 index 0000000000..4066748557 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt @@ -0,0 +1,28 @@ +usage: cz check [-h] [--commit-msg-file COMMIT_MSG_FILE | + --rev-range REV_RANGE | -d | -m MESSAGE] [--allow-abort] + [--allowed-prefixes [ALLOWED_PREFIXES ...]] + [-l MESSAGE_LENGTH_LIMIT] + +validates that a commit message matches the commitizen schema + +options: + -h, --help show this help message and exit + --commit-msg-file COMMIT_MSG_FILE + ask for the name of the temporal file that contains + the commit message. Using it in a git hook script: + MSG_FILE=$1 + --rev-range REV_RANGE + a range of git rev to check. e.g, master..HEAD + -d, --use-default-range + check from the default branch to HEAD. e.g, + refs/remotes/origin/master..HEAD + -m, --message MESSAGE + commit message that needs to be checked + --allow-abort allow empty commit messages, which typically abort a + commit + --allowed-prefixes [ALLOWED_PREFIXES ...] + allowed commit message prefixes. If the message starts + by one of these prefixes, the message won't be checked + against the regex + -l, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt new file mode 100644 index 0000000000..ba531042aa --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt @@ -0,0 +1,22 @@ +usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] + [--write-message-to-file FILE_PATH] [-s] [-a] [-e] + [-l MESSAGE_LENGTH_LIMIT] [--] + +create new commit + +options: + -h, --help show this help message and exit + --retry retry last commit + --no-retry skip retry if retry_after_failure is set to true + --dry-run show output to stdout, no commit, no modified files + --write-message-to-file FILE_PATH + write message to file before committing (can be + combined with --dry-run) + -s, --signoff Deprecated, use 'cz commit -- -s' instead + -a, --all Tell the command to automatically stage files that + have been modified and deleted, but new files you have + not told Git about are not affected. + -e, --edit edit the commit message before committing + -l, --message-length-limit MESSAGE_LENGTH_LIMIT + length limit of the commit message; 0 for no limit + -- Positional arguments separator (recommended) diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt new file mode 100644 index 0000000000..b9bf7f84fc --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt @@ -0,0 +1,6 @@ +usage: cz example [-h] + +show commit example + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt new file mode 100644 index 0000000000..99b1ba8a4a --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt @@ -0,0 +1,6 @@ +usage: cz info [-h] + +show information about the cz + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt new file mode 100644 index 0000000000..0f72042f88 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt @@ -0,0 +1,6 @@ +usage: cz init [-h] + +init commitizen configuration + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt new file mode 100644 index 0000000000..5fa8fe1f79 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt @@ -0,0 +1,6 @@ +usage: cz ls [-h] + +show available commitizens + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt new file mode 100644 index 0000000000..6666db4d41 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt @@ -0,0 +1,6 @@ +usage: cz schema [-h] + +show commit schema + +options: + -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt new file mode 100644 index 0000000000..a194615a98 --- /dev/null +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt @@ -0,0 +1,16 @@ +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] + +get the version of the installed commitizen or the current project (default: +installed commitizen) + +options: + -h, --help show this help message and exit + -r, --report get system information for reporting bugs + -p, --project get the version of the current project + -c, --commitizen get the version of the installed commitizen + -v, --verbose get the version of both the installed commitizen and the + current project + --major get just the major version. Need to be used with --project + or --verbose. + --minor get just the minor version. Need to be used with --project + or --verbose. From f55d567e2c6225919aa42fa410d1473ff3a175ab Mon Sep 17 00:00:00 2001 From: James Harrison <james.harrison@satellitevu.com> Date: Fri, 2 Jan 2026 17:33:34 +0000 Subject: [PATCH 157/221] fix(providers): normalize package names in uv provider for uv.lock matching --- commitizen/providers/uv_provider.py | 4 +- tests/providers/test_uv_provider.py | 26 +++++++++++- ...lock => test_uv_provider_hyphenated_.lock} | 0 ...toml => test_uv_provider_hyphenated_.toml} | 0 .../test_uv_provider_underscore_.lock | 42 +++++++++++++++++++ .../test_uv_provider_underscore_.toml | 8 ++++ 6 files changed, 77 insertions(+), 3 deletions(-) rename tests/providers/test_uv_provider/{test_uv_provider.lock => test_uv_provider_hyphenated_.lock} (100%) rename tests/providers/test_uv_provider/{test_uv_provider.toml => test_uv_provider_hyphenated_.toml} (100%) create mode 100644 tests/providers/test_uv_provider/test_uv_provider_underscore_.lock create mode 100644 tests/providers/test_uv_provider/test_uv_provider_underscore_.toml diff --git a/commitizen/providers/uv_provider.py b/commitizen/providers/uv_provider.py index 4574dc4b6b..4f49a29528 100644 --- a/commitizen/providers/uv_provider.py +++ b/commitizen/providers/uv_provider.py @@ -4,6 +4,7 @@ import tomlkit import tomlkit.items +from packaging.utils import canonicalize_name from commitizen.providers.base_provider import TomlProvider @@ -27,12 +28,13 @@ def set_version(self, version: str) -> None: def set_lock_version(self, version: str) -> None: pyproject_toml_content = tomlkit.parse(self.file.read_text()) project_name = pyproject_toml_content["project"]["name"] # type: ignore[index] + normalized_project_name = canonicalize_name(str(project_name)) document = tomlkit.parse(self.lock_file.read_text()) packages: tomlkit.items.AoT = document["package"] # type: ignore[assignment] for i, package in enumerate(packages): - if package["name"] == project_name: + if package["name"] == normalized_project_name: document["package"][i]["version"] = version # type: ignore[index] break self.lock_file.write_text(tomlkit.dumps(document)) diff --git a/tests/providers/test_uv_provider.py b/tests/providers/test_uv_provider.py index 7cb0782dd6..3dc55a91bd 100644 --- a/tests/providers/test_uv_provider.py +++ b/tests/providers/test_uv_provider.py @@ -2,6 +2,8 @@ from typing import TYPE_CHECKING +import pytest + from commitizen.providers import get_provider from commitizen.providers.uv_provider import UvProvider @@ -21,6 +23,16 @@ dependencies = ["commitizen==4.2.1"] """ +PYPROJECT_TOML_UNDERSCORE = """ +[project] +name = "test_uv" +version = "4.2.1" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = ["commitizen==4.2.1"] +""" + UV_LOCK_SIMPLIFIED = """ version = 1 revision = 1 @@ -66,12 +78,22 @@ """ +@pytest.mark.parametrize( + "pyproject_content", + [ + pytest.param(PYPROJECT_TOML, id="hyphenated"), + pytest.param(PYPROJECT_TOML_UNDERSCORE, id="underscore"), + ], +) def test_uv_provider( - config: BaseConfig, tmpdir, file_regression: FileRegressionFixture + config: BaseConfig, + tmpdir, + file_regression: FileRegressionFixture, + pyproject_content: str, ): with tmpdir.as_cwd(): pyproject_toml_file = tmpdir / UvProvider.filename - pyproject_toml_file.write_text(PYPROJECT_TOML, encoding="utf-8") + pyproject_toml_file.write_text(pyproject_content, encoding="utf-8") uv_lock_file = tmpdir / UvProvider.lock_filename uv_lock_file.write_text(UV_LOCK_SIMPLIFIED, encoding="utf-8") diff --git a/tests/providers/test_uv_provider/test_uv_provider.lock b/tests/providers/test_uv_provider/test_uv_provider_hyphenated_.lock similarity index 100% rename from tests/providers/test_uv_provider/test_uv_provider.lock rename to tests/providers/test_uv_provider/test_uv_provider_hyphenated_.lock diff --git a/tests/providers/test_uv_provider/test_uv_provider.toml b/tests/providers/test_uv_provider/test_uv_provider_hyphenated_.toml similarity index 100% rename from tests/providers/test_uv_provider/test_uv_provider.toml rename to tests/providers/test_uv_provider/test_uv_provider_hyphenated_.toml diff --git a/tests/providers/test_uv_provider/test_uv_provider_underscore_.lock b/tests/providers/test_uv_provider/test_uv_provider_underscore_.lock new file mode 100644 index 0000000000..d353763ce3 --- /dev/null +++ b/tests/providers/test_uv_provider/test_uv_provider_underscore_.lock @@ -0,0 +1,42 @@ + +version = 1 +revision = 1 +requires-python = ">=3.13" + +[[package]] +name = "commitizen" +version = "4.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argcomplete" }, + { name = "charset-normalizer" }, + { name = "colorama" }, + { name = "decli" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "questionary" }, + { name = "termcolor" }, + { name = "tomlkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/a3/77ffc9aee014cbf46c84c9f156a1ddef2d4c7cfb87d567decf2541464245/commitizen-4.2.1.tar.gz", hash = "sha256:5255416f6d6071068159f0b97605777f3e25d00927ff157b7a8d01efeda7b952", size = 50645 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/ce/2f5d8ebe8376991b5f805e9f33d20c7f4c9ca6155bdbda761117dc41dff1/commitizen-4.2.1-py3-none-any.whl", hash = "sha256:a347889e0fe408c3b920a34130d8f35616be3ea8ac6b7b20c5b9aac19762661b", size = 72646 }, +] + +[[package]] +name = "decli" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/a0/a4658f93ecb589f479037b164dc13c68d108b50bf6594e54c820749f97ac/decli-0.6.2.tar.gz", hash = "sha256:36f71eb55fd0093895efb4f416ec32b7f6e00147dda448e3365cf73ceab42d6f", size = 7424 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/70/3ea48dc9e958d7d66c44c9944809181f1ca79aaef25703c023b5092d34ff/decli-0.6.2-py3-none-any.whl", hash = "sha256:2fc84106ce9a8f523ed501ca543bdb7e416c064917c12a59ebdc7f311a97b7ed", size = 7854 }, +] + +[[package]] +name = "test-uv" +version = "100.100.100" +source = { virtual = "." } +dependencies = [ + { name = "commitizen" }, +] diff --git a/tests/providers/test_uv_provider/test_uv_provider_underscore_.toml b/tests/providers/test_uv_provider/test_uv_provider_underscore_.toml new file mode 100644 index 0000000000..99b24ee8f2 --- /dev/null +++ b/tests/providers/test_uv_provider/test_uv_provider_underscore_.toml @@ -0,0 +1,8 @@ + +[project] +name = "test_uv" +version = "100.100.100" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = ["commitizen==4.2.1"] From 2e4f4b26b5b0a0c0ebc660c1f78aca1e28d912bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Sat, 3 Jan 2026 17:26:01 +0000 Subject: [PATCH 158/221] =?UTF-8?q?bump:=20version=204.11.0=20=E2=86=92=20?= =?UTF-8?q?4.11.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 31bc6fb073..4a7efc7f9c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.0 # automatically updated by Commitizen + rev: v4.11.1 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf5f7a090..88ac00b6f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.11.1 (2026-01-03) + +### Fix + +- **providers**: normalize package names in uv provider for uv.lock matching + ## v4.11.0 (2025-12-29) ### Feat diff --git a/commitizen/__version__.py b/commitizen/__version__.py index bdb8bda6ae..601b9bb2b3 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.0" +__version__ = "4.11.1" diff --git a/pyproject.toml b/pyproject.toml index 8ec4e8e16e..c180e3f9be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.0" +version = "4.11.1" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ @@ -122,7 +122,7 @@ build-backend = "uv_build" [tool.commitizen] -version = "4.11.0" +version = "4.11.1" tag_format = "v$version" version_files = [ "pyproject.toml:version", From 8d21d87c866d34d9116ece63393b8cc33108f73b Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sun, 4 Jan 2026 01:39:43 +0800 Subject: [PATCH 159/221] build: manually update uv.lock --- uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index 202ed0d5a8..5896f26f32 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.0" +version = "4.11.1" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 2cb2108cc20989f84cdd6efab2b0219935ecc299 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@users.noreply.github.com> Date: Mon, 5 Jan 2026 03:53:21 +0100 Subject: [PATCH 160/221] build(dev): ensure `uv sync --dev` install all dev dependencies (#1763) --- pyproject.toml | 11 ++++++++++- uv.lock | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c180e3f9be..d234b9a780 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,16 @@ semver = "commitizen.version_schemes:SemVer" semver2 = "commitizen.version_schemes:SemVer2" [dependency-groups] -dev = ["ipython>=8.0", "tox>4", "tox-uv", "poethepoet>=0.34.0"] +dev = [ + { include-group = "test" }, + { include-group = "linters" }, + { include-group = "documentation" }, + { include-group = "script" }, + "ipython>=8.0", + "tox>4", + "tox-uv", + "poethepoet>=0.34.0", +] test = [ "pytest>=7.2", diff --git a/uv.lock b/uv.lock index 5896f26f32..30e2970095 100644 --- a/uv.lock +++ b/uv.lock @@ -217,9 +217,27 @@ dependencies = [ dev = [ { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "ipython", version = "9.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "mkdocs" }, + { name = "mkdocs-material" }, + { name = "mypy" }, { name = "poethepoet" }, + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-freezer" }, + { name = "pytest-gitconfig" }, + { name = "pytest-mock" }, + { name = "pytest-regressions" }, + { name = "pytest-xdist" }, + { name = "rich" }, + { name = "ruff" }, { name = "tox" }, { name = "tox-uv" }, + { name = "types-colorama" }, + { name = "types-deprecated" }, + { name = "types-python-dateutil" }, + { name = "types-pyyaml" }, + { name = "types-termcolor" }, ] documentation = [ { name = "mkdocs" }, @@ -269,9 +287,27 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ { name = "ipython", specifier = ">=8.0" }, + { name = "mkdocs", specifier = ">=1.4.2" }, + { name = "mkdocs-material", specifier = ">=9.1.6" }, + { name = "mypy", specifier = ">=1.16.0" }, { name = "poethepoet", specifier = ">=0.34.0" }, + { name = "pre-commit", specifier = ">=3.2.0" }, + { name = "pytest", specifier = ">=7.2" }, + { name = "pytest-cov", specifier = ">=4" }, + { name = "pytest-freezer", specifier = ">=0.4.6" }, + { name = "pytest-gitconfig", specifier = ">=0.9.0" }, + { name = "pytest-mock", specifier = ">=3.10" }, + { name = "pytest-regressions", specifier = ">=2.4.0" }, + { name = "pytest-xdist", specifier = ">=3.1.0" }, + { name = "rich", specifier = ">=13.7.1" }, + { name = "ruff", specifier = ">=0.11.5" }, { name = "tox", specifier = ">4" }, { name = "tox-uv" }, + { name = "types-colorama", specifier = ">=0.4.15.20240311" }, + { name = "types-deprecated", specifier = ">=1.2.9.2" }, + { name = "types-python-dateutil", specifier = ">=2.8.19.13" }, + { name = "types-pyyaml", specifier = ">=5.4.3" }, + { name = "types-termcolor", specifier = ">=0.1.1" }, ] documentation = [ { name = "mkdocs", specifier = ">=1.4.2" }, From 095913ab4923506b3cb8f1d17b7a0e00aa175511 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@users.noreply.github.com> Date: Mon, 5 Jan 2026 03:54:38 +0100 Subject: [PATCH 161/221] build(commitizen): use `uv` version provider (fix #1759) (#1762) --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d234b9a780..eb5e8959f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -131,13 +131,12 @@ build-backend = "uv_build" [tool.commitizen] -version = "4.11.1" tag_format = "v$version" version_files = [ - "pyproject.toml:version", "commitizen/__version__.py", ".pre-commit-config.yaml:rev:.+Commitizen", ] +version_provider = "uv" version_scheme = "pep440" From e6690352c3bca0ae458f02c9c325e50f27b94e49 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 5 Jan 2026 05:03:18 +0100 Subject: [PATCH 162/221] ci(uv): use `uv sync --frozen` everywhere --- .github/workflows/docspublish.yml | 4 ++-- .github/workflows/pythonpackage.yml | 2 +- .pre-commit-config.yaml | 2 +- docs/contributing.md | 2 +- docs/contributing_tldr.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index c7eb973fb0..f30d8c1de9 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -19,7 +19,7 @@ jobs: - name: Install dependencies run: | uv --version - uv sync --locked --group script + uv sync --frozen --group script - name: Update CLI screenshots run: | uv run poe doc:screenshots @@ -52,7 +52,7 @@ jobs: - name: Install dependencies run: | uv --version - uv sync --locked --only-group documentation + uv sync --frozen --only-group documentation - name: Generate Sponsors 💖 uses: JamesIves/github-sponsors-readme-action@v1 with: diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 4772e8b5d6..95db733649 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -25,7 +25,7 @@ jobs: - name: Install dependencies run: | uv --version - uv sync --locked --dev --group test --group linters + uv sync --frozen --group test --group linters - name: Run tests and linters run: | git config --global user.email "action@github.com" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4a7efc7f9c..7358db3e3f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: hooks: - id: uv-lock - id: uv-sync - args: [ --locked, --all-groups ] + args: [ --frozen, --all-groups ] stages: [ pre-commit, post-checkout, post-merge, post-rewrite ] - repo: https://github.com/asottile/blacken-docs diff --git a/docs/contributing.md b/docs/contributing.md index 750fb0bc18..827dfc7ac2 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -40,7 +40,7 @@ If you're a first-time contributor, please check out issues labeled [good first ``` 4. Set up the development environment: ```bash - uv sync --dev + uv sync --dev --frozen ``` 5. Set up pre-commit hooks: ```bash diff --git a/docs/contributing_tldr.md b/docs/contributing_tldr.md index cbb83fb3c0..91f49d1ca4 100644 --- a/docs/contributing_tldr.md +++ b/docs/contributing_tldr.md @@ -13,7 +13,7 @@ Please check the [pyproject.toml](https://github.com/commitizen-tools/commitizen ```bash # Ensure you have the correct dependencies -uv sync --dev +uv sync --dev --frozen # Make ruff happy uv run poe format From 9cdd357571bb22e65564405565d66015b92c6fac Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 5 Jan 2026 05:20:21 +0100 Subject: [PATCH 163/221] build(deps): move `poethepoet` into a separate `base` group --- .github/workflows/docspublish.yml | 4 ++-- .github/workflows/pythonpackage.yml | 2 +- pyproject.toml | 4 +++- uv.lock | 4 ++++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index f30d8c1de9..2c5e7dbf23 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -19,7 +19,7 @@ jobs: - name: Install dependencies run: | uv --version - uv sync --frozen --group script + uv sync --frozen --group base --group script - name: Update CLI screenshots run: | uv run poe doc:screenshots @@ -52,7 +52,7 @@ jobs: - name: Install dependencies run: | uv --version - uv sync --frozen --only-group documentation + uv sync --frozen --only-group base --only-group documentation - name: Generate Sponsors 💖 uses: JamesIves/github-sponsors-readme-action@v1 with: diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 95db733649..d062fe2c7a 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -25,7 +25,7 @@ jobs: - name: Install dependencies run: | uv --version - uv sync --frozen --group test --group linters + uv sync --frozen --group base --group test --group linters - name: Run tests and linters run: | git config --global user.email "action@github.com" diff --git a/pyproject.toml b/pyproject.toml index eb5e8959f6..e27f97fcb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,6 +87,7 @@ semver2 = "commitizen.version_schemes:SemVer2" [dependency-groups] dev = [ + { include-group = "base" }, { include-group = "test" }, { include-group = "linters" }, { include-group = "documentation" }, @@ -94,9 +95,10 @@ dev = [ "ipython>=8.0", "tox>4", "tox-uv", - "poethepoet>=0.34.0", ] +base = ["poethepoet>=0.34.0"] + test = [ "pytest>=7.2", "pytest-cov>=4", diff --git a/uv.lock b/uv.lock index 30e2970095..d23b812146 100644 --- a/uv.lock +++ b/uv.lock @@ -214,6 +214,9 @@ dependencies = [ ] [package.dev-dependencies] +base = [ + { name = "poethepoet" }, +] dev = [ { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "ipython", version = "9.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, @@ -285,6 +288,7 @@ requires-dist = [ ] [package.metadata.requires-dev] +base = [{ name = "poethepoet", specifier = ">=0.34.0" }] dev = [ { name = "ipython", specifier = ">=8.0" }, { name = "mkdocs", specifier = ">=1.4.2" }, From 51b99b05020868a1a22d86f0868b10920fab4652 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@gmail.com> Date: Mon, 5 Jan 2026 05:22:49 +0100 Subject: [PATCH 164/221] ci(uv): prevent auto sync on run --- .github/workflows/docspublish.yml | 4 ++-- .github/workflows/pythonpackage.yml | 2 +- .pre-commit-config.yaml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docspublish.yml b/.github/workflows/docspublish.yml index 2c5e7dbf23..cb5d78e751 100644 --- a/.github/workflows/docspublish.yml +++ b/.github/workflows/docspublish.yml @@ -22,7 +22,7 @@ jobs: uv sync --frozen --group base --group script - name: Update CLI screenshots run: | - uv run poe doc:screenshots + uv run --no-sync poe doc:screenshots - name: Commit and push updated CLI screenshots run: | git config --global user.name "github-actions[bot]" @@ -63,7 +63,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - uv run poe doc:build + uv run --no-sync poe doc:build - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@v4 with: diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index d062fe2c7a..cdf0d1d17d 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -30,7 +30,7 @@ jobs: run: | git config --global user.email "action@github.com" git config --global user.name "GitHub Action" - uv run poe ci + uv run --no-sync poe ci shell: bash - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7358db3e3f..f8d29aed7c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,12 +74,12 @@ repos: name: Format Python code language: system pass_filenames: false - entry: uv run poe format + entry: uv run --no-sync poe format types: [ python ] - id: linter and test name: Linters language: system pass_filenames: false - entry: uv run poe lint + entry: uv run --no-sync poe lint types: [ python ] From d00cf03d2b52463865453acc0546261b266b4180 Mon Sep 17 00:00:00 2001 From: BelpHegoR17 <bel02082024@gmail.com> Date: Mon, 5 Jan 2026 17:53:24 +0530 Subject: [PATCH 165/221] docs(commands/bump.md): document --yes option for cz bump (#1758) * docs: documented --yes option for cz bump * docs(commands/bump.md): moved reference links at the end of file --- docs/commands/bump.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/commands/bump.md b/docs/commands/bump.md index e20a20d5f7..e7a7c04030 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -504,6 +504,14 @@ Supported variables: | `$prerelease`, `${prerelease}` | Prerelease (alpha, beta, release candidate) | | `$devrelease`, `${devrelease}` | Development release | +### `--yes` + +Automatically answers “yes” to all interactive prompts during the bump process, allowing the command to run without manual confirmation. + +```bash +cz bump --yes +``` + [pep440]: https://www.python.org/dev/peps/pep-0440/ [semver]: https://semver.org/ [version_files]: ../config/bump.md#version_files From d46e49c8b75eede976dafdcb6eb5e45525aaea3c Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:15:04 +0100 Subject: [PATCH 166/221] test(utils): uses `util` fixture for all git operations and cli executions (#1766) --- tests/commands/test_bump_command.py | 740 +++++++++-------------- tests/commands/test_changelog_command.py | 15 +- tests/commands/test_check_command.py | 121 ++-- tests/commands/test_common_command.py | 10 +- tests/providers/test_scm_provider.py | 76 +-- tests/test_bump_create_commit_message.py | 35 +- tests/test_cli.py | 60 +- tests/test_git.py | 237 ++++---- tests/utils.py | 54 +- 9 files changed, 521 insertions(+), 827 deletions(-) diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index d8cac56f75..c781e25263 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -2,7 +2,6 @@ import inspect import re -import sys from pathlib import Path from textwrap import dedent from typing import TYPE_CHECKING @@ -11,7 +10,7 @@ import pytest import commitizen.commands.bump as bump -from commitizen import cli, cmd, defaults, git, hooks +from commitizen import cmd, defaults, git, hooks from commitizen.config.base_config import BaseConfig from commitizen.exceptions import ( BumpTagFailedError, @@ -28,7 +27,6 @@ NotAllowed, NoVersionSpecifiedError, ) -from tests.utils import create_file_and_commit, create_tag if TYPE_CHECKING: import py @@ -36,6 +34,7 @@ from commitizen.changelog_formats import ChangelogFormat from commitizen.cz.base import BaseCommitizen + from tests.utils import UtilFixture @pytest.mark.parametrize( @@ -50,22 +49,18 @@ ), ) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_patch_increment(commit_msg, mocker: MockFixture): - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_patch_increment(commit_msg: str, util: UtilFixture): + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.1.1") assert tag_exists is True @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_minor_increment(commit_msg, mocker: MockFixture): - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_minor_increment(commit_msg: str, util: UtilFixture): + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') assert tag_exists is True and "commit:refs/tags/0.2.0\n" in cmd_res.out @@ -73,11 +68,9 @@ def test_bump_minor_increment(commit_msg, mocker: MockFixture): @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_minor_increment_annotated(commit_msg, mocker: MockFixture): - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes", "--annotated-tag"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_minor_increment_annotated(commit_msg: str, util: UtilFixture): + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes", "--annotated-tag") tag_exists = git.tag_exist("0.2.0") cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out @@ -88,11 +81,9 @@ def test_bump_minor_increment_annotated(commit_msg, mocker: MockFixture): @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @pytest.mark.usefixtures("tmp_commitizen_project_with_gpg") -def test_bump_minor_increment_signed(commit_msg, mocker: MockFixture): - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes", "--gpg-sign"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_minor_increment_signed(commit_msg: str, util: UtilFixture): + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes", "--gpg-sign") tag_exists = git.tag_exist("0.2.0") cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out @@ -103,16 +94,14 @@ def test_bump_minor_increment_signed(commit_msg, mocker: MockFixture): @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) def test_bump_minor_increment_annotated_config_file( - commit_msg, mocker: MockFixture, tmp_commitizen_project + commit_msg: str, util: UtilFixture, tmp_commitizen_project ): tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") tmp_commitizen_cfg_file.write( f"{tmp_commitizen_cfg_file.read()}\nannotated_tag = 1" ) - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out @@ -123,14 +112,12 @@ def test_bump_minor_increment_annotated_config_file( @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) def test_bump_minor_increment_signed_config_file( - commit_msg, mocker: MockFixture, tmp_commitizen_project_with_gpg + commit_msg: str, util: UtilFixture, tmp_commitizen_project_with_gpg ): tmp_commitizen_cfg_file = tmp_commitizen_project_with_gpg.join("pyproject.toml") tmp_commitizen_cfg_file.write(f"{tmp_commitizen_cfg_file.read()}\ngpg_sign = 1") - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out @@ -153,12 +140,10 @@ def test_bump_minor_increment_signed_config_file( "BREAKING-CHANGE: age is no longer supported", ), ) -def test_bump_major_increment(commit_msg, mocker: MockFixture): - create_file_and_commit(commit_msg) +def test_bump_major_increment(commit_msg: str, util: UtilFixture): + util.create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("1.0.0") assert tag_exists is True @@ -178,12 +163,10 @@ def test_bump_major_increment(commit_msg, mocker: MockFixture): "BREAKING-CHANGE: age is no longer supported", ), ) -def test_bump_major_increment_major_version_zero(commit_msg, mocker): - create_file_and_commit(commit_msg) +def test_bump_major_increment_major_version_zero(commit_msg: str, util: UtilFixture): + util.create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes", "--major-version-zero"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--major-version-zero") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @@ -200,43 +183,35 @@ def test_bump_major_increment_major_version_zero(commit_msg, mocker): ], ) def test_bump_command_increment_option( - commit_msg, increment, expected_tag, mocker: MockFixture + commit_msg: str, increment: str, expected_tag: str, util: UtilFixture ): - create_file_and_commit(commit_msg) + util.create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--increment", increment, "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--increment", increment, "--yes") tag_exists = git.tag_exist(expected_tag) assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_command_prerelease(mocker: MockFixture): - create_file_and_commit("feat: location") +def test_bump_command_prerelease(util: UtilFixture): + util.create_file_and_commit("feat: location") # Create an alpha pre-release. - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("0.2.0a0") assert tag_exists is True # Create a beta pre-release. - testargs = ["cz", "bump", "--prerelease", "beta", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "beta", "--yes") tag_exists = git.tag_exist("0.2.0b0") assert tag_exists is True # With a current beta pre-release, bumping alpha must bump beta # because we can't bump "backwards". - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("0.2.0a1") assert tag_exists is False @@ -244,17 +219,13 @@ def test_bump_command_prerelease(mocker: MockFixture): assert tag_exists is True # Create a rc pre-release. - testargs = ["cz", "bump", "--prerelease", "rc", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "rc", "--yes") tag_exists = git.tag_exist("0.2.0rc0") assert tag_exists is True # With a current rc pre-release, bumping alpha must bump rc. - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("0.2.0a1") assert tag_exists is False @@ -264,9 +235,7 @@ def test_bump_command_prerelease(mocker: MockFixture): assert tag_exists is True # With a current rc pre-release, bumping beta must bump rc. - testargs = ["cz", "bump", "--prerelease", "beta", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "beta", "--yes") tag_exists = git.tag_exist("0.2.0a2") assert tag_exists is False @@ -276,115 +245,81 @@ def test_bump_command_prerelease(mocker: MockFixture): assert tag_exists is True # Create a final release from the current pre-release. - testargs = ["cz", "bump"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_command_prerelease_increment(mocker: MockFixture): +def test_bump_command_prerelease_increment(util: UtilFixture): # FINAL RELEASE - create_file_and_commit("fix: location") + util.create_file_and_commit("fix: location") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") assert git.tag_exist("0.1.1") # PRERELEASE - create_file_and_commit("fix: location") + util.create_file_and_commit("fix: location") - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") assert git.tag_exist("0.1.2a0") - create_file_and_commit("feat: location") + util.create_file_and_commit("feat: location") - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") assert git.tag_exist("0.2.0a0") - create_file_and_commit("feat!: breaking") + util.create_file_and_commit("feat!: breaking") - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") assert git.tag_exist("1.0.0a0") @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_command_prerelease_exact_mode(mocker: MockFixture): +def test_bump_command_prerelease_exact_mode(util: UtilFixture): # PRERELEASE - create_file_and_commit("feat: location") + util.create_file_and_commit("feat: location") - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("0.2.0a0") assert tag_exists is True # PRERELEASE + PATCH BUMP - testargs = [ - "cz", - "bump", - "--prerelease", - "alpha", - "--yes", - "--increment-mode=exact", - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() - + util.run_cli("bump", "--prerelease", "alpha", "--yes", "--increment-mode=exact") tag_exists = git.tag_exist("0.2.0a1") assert tag_exists is True # PRERELEASE + MINOR BUMP # --increment-mode allows the minor version to bump, and restart the prerelease - create_file_and_commit("feat: location") + util.create_file_and_commit("feat: location") - testargs = [ - "cz", - "bump", - "--prerelease", - "alpha", - "--yes", - "--increment-mode=exact", - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes", "--increment-mode=exact") tag_exists = git.tag_exist("0.3.0a0") assert tag_exists is True # PRERELEASE + MAJOR BUMP # --increment-mode=exact allows the major version to bump, and restart the prerelease - testargs = [ - "cz", + util.run_cli( "bump", "--prerelease", "alpha", "--yes", "--increment=MAJOR", "--increment-mode=exact", - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + ) tag_exists = git.tag_exist("1.0.0a0") assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_on_git_with_hooks_no_verify_disabled(mocker: MockFixture): +def test_bump_on_git_with_hooks_no_verify_disabled(util: UtilFixture): """Bump commit without --no-verify""" cmd.run("mkdir .git/hooks") with open(".git/hooks/pre-commit", "w", encoding="utf-8") as f: @@ -392,103 +327,84 @@ def test_bump_on_git_with_hooks_no_verify_disabled(mocker: MockFixture): cmd.run("chmod +x .git/hooks/pre-commit") # MINOR - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat: new file") - cli.main() + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_tag_exists_raises_exception(mocker: MockFixture): +def test_bump_tag_exists_raises_exception(util: UtilFixture): cmd.run("mkdir .git/hooks") with open(".git/hooks/post-commit", "w", encoding="utf-8") as f: f.write("#!/usr/bin/env bash\nexit 9") cmd.run("chmod +x .git/hooks/post-commit") # MINOR - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") git.tag("0.2.0") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(BumpTagFailedError) as excinfo: - cli.main() + util.run_cli("bump", "--yes") assert "0.2.0" in str(excinfo.value) # This should be a fatal error @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_on_git_with_hooks_no_verify_enabled(mocker: MockFixture): +def test_bump_on_git_with_hooks_no_verify_enabled(util: UtilFixture): cmd.run("mkdir .git/hooks") with open(".git/hooks/pre-commit", "w", encoding="utf-8") as f: f.write('#!/usr/bin/env bash\necho "0.1.0"') cmd.run("chmod +x .git/hooks/pre-commit") # MINOR - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes", "--no-verify"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--no-verify") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_when_bumping_is_not_support(mocker: MockFixture): - create_file_and_commit( +def test_bump_when_bumping_is_not_support(util: UtilFixture): + util.create_file_and_commit( "feat: new user interface\n\nBREAKING CHANGE: age is no longer supported" ) - testargs = ["cz", "-n", "cz_jira", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - with pytest.raises(NoPatternMapError) as excinfo: - cli.main() + util.run_cli("-n", "cz_jira", "bump", "--yes") assert "'cz_jira' rule does not support bump" in str(excinfo.value) @pytest.mark.usefixtures("tmp_git_project") -def test_bump_when_version_is_not_specify(mocker: MockFixture): - mocker.patch.object(sys, "argv", ["cz", "bump"]) - +def test_bump_when_version_is_not_specify(util: UtilFixture): with pytest.raises(NoVersionSpecifiedError) as excinfo: - cli.main() + util.run_cli("bump") assert NoVersionSpecifiedError.message in str(excinfo.value) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_when_no_new_commit(mocker: MockFixture): +def test_bump_when_no_new_commit(util: UtilFixture): """bump without any commits since the last bump.""" # We need this first commit otherwise the revision is invalid. - create_file_and_commit("feat: initial") - - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat: initial") - # First bump. - # The next bump should fail since - # there is not a commit between the two bumps. - cli.main() + util.run_cli("bump", "--yes") # bump without a new commit. with pytest.raises(NoCommitsFoundError) as excinfo: - cli.main() + util.run_cli("bump", "--yes") expected_error_message = "[NO_COMMITS_FOUND]\nNo new commits found." assert expected_error_message in str(excinfo.value) def test_bump_when_version_inconsistent_in_version_files( - tmp_commitizen_project, mocker: MockFixture + tmp_commitizen_project, util: UtilFixture ): tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_version_file.write("100.999.10000") @@ -499,19 +415,18 @@ def test_bump_when_version_inconsistent_in_version_files( f'version_files = ["{tmp_version_file_string}"]' ) - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes", "--check-consistency"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat: new file") with pytest.raises(CurrentVersionNotFoundError) as excinfo: - cli.main() + util.run_cli("bump", "--yes", "--check-consistency") partial_expected_error_message = "Current version 0.1.0 is not found in" assert partial_expected_error_message in str(excinfo.value) -def test_bump_major_version_zero_when_major_is_not_zero(mocker, tmp_commitizen_project): +def test_bump_major_version_zero_when_major_is_not_zero( + tmp_commitizen_project, util: UtilFixture +): tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_version_file.write("1.0.0") tmp_version_file_string = str(tmp_version_file).replace("\\", "/") @@ -524,15 +439,12 @@ def test_bump_major_version_zero_when_major_is_not_zero(mocker, tmp_commitizen_p tmp_changelog_file = tmp_commitizen_project.join("CHANGELOG.md") tmp_changelog_file.write("## v1.0.0") - create_file_and_commit("feat(user): new file") - create_tag("v1.0.0") - create_file_and_commit("feat(user)!: new file") - - testargs = ["cz", "bump", "--yes", "--major-version-zero"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat(user): new file") + util.create_tag("v1.0.0") + util.create_file_and_commit("feat(user)!: new file") with pytest.raises(NotAllowed) as excinfo: - cli.main() + util.run_cli("bump", "--yes", "--major-version-zero") expected_error_message = ( "--major-version-zero is meaningless for current version 1.0.0" @@ -540,7 +452,7 @@ def test_bump_major_version_zero_when_major_is_not_zero(mocker, tmp_commitizen_p assert expected_error_message in str(excinfo.value) -def test_bump_files_only(mocker: MockFixture, tmp_commitizen_project): +def test_bump_files_only(tmp_commitizen_project, util: UtilFixture): tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_version_file.write("0.1.0") tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") @@ -550,18 +462,14 @@ def test_bump_files_only(mocker: MockFixture, tmp_commitizen_project): f'version_files = ["{tmp_version_file_string}"]' ) - create_file_and_commit("feat: new user interface") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new user interface") + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True - create_file_and_commit("feat: another new feature") - testargs = ["cz", "bump", "--yes", "--files-only"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat: another new feature") with pytest.raises(ExpectedExit): - cli.main() + util.run_cli("bump", "--yes", "--files-only") tag_exists = git.tag_exist("0.3.0") assert tag_exists is False @@ -573,7 +481,7 @@ def test_bump_files_only(mocker: MockFixture, tmp_commitizen_project): assert "0.3.0" in f.read() -def test_bump_local_version(mocker: MockFixture, tmp_commitizen_project): +def test_bump_local_version(tmp_commitizen_project, util: UtilFixture): tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_version_file.write("4.5.1+0.1.0") tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") @@ -584,10 +492,8 @@ def test_bump_local_version(mocker: MockFixture, tmp_commitizen_project): f'version_files = ["{tmp_version_file_string}"]' ) - create_file_and_commit("feat: new user interface") - testargs = ["cz", "bump", "--yes", "--local-version"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat: new user interface") + util.run_cli("bump", "--yes", "--local-version") tag_exists = git.tag_exist("4.5.1+0.2.0") assert tag_exists is True @@ -596,13 +502,11 @@ def test_bump_local_version(mocker: MockFixture, tmp_commitizen_project): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_dry_run(mocker: MockFixture, capsys): - create_file_and_commit("feat: new file") +def test_bump_dry_run(util: UtilFixture, capsys): + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("bump", "--yes", "--dry-run") out, _ = capsys.readouterr() assert "0.2.0" in out @@ -611,14 +515,11 @@ def test_bump_dry_run(mocker: MockFixture, capsys): assert tag_exists is False -def test_bump_in_non_git_project(tmpdir, config, mocker: MockFixture): - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - +def test_bump_in_non_git_project(tmpdir, config, util: UtilFixture): with tmpdir.as_cwd(): with pytest.raises(NotAGitProjectError): with pytest.raises(ExpectedExit): - cli.main() + util.run_cli("bump", "--yes") def test_none_increment_exit_should_be_a_class(): @@ -639,11 +540,9 @@ def test_none_increment_exit_is_exception(): @pytest.mark.usefixtures("tmp_commitizen_project") def test_none_increment_should_not_call_git_tag_and_error_code_is_not_zero( - mocker: MockFixture, + mocker: MockFixture, util: UtilFixture ): - create_file_and_commit("test(test_get_all_droplets): fix bad comparison test") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("test(test_get_all_droplets): fix bad comparison test") # stash git.tag for later restore stashed_git_tag = git.tag @@ -651,7 +550,7 @@ def test_none_increment_should_not_call_git_tag_and_error_code_is_not_zero( git.tag = MagicMock(return_value=dummy_value) with pytest.raises(NoneIncrementExit) as e: - cli.main() + util.run_cli("bump", "--yes") git.tag.assert_not_called() assert e.value.exit_code == ExitCode.NO_INCREMENT @@ -661,11 +560,9 @@ def test_none_increment_should_not_call_git_tag_and_error_code_is_not_zero( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_changelog_arg(mocker: MockFixture, changelog_path): - create_file_and_commit("feat(user): new file") - testargs = ["cz", "bump", "--yes", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_with_changelog_arg(util: UtilFixture, changelog_path): + util.create_file_and_commit("feat(user): new file") + util.run_cli("bump", "--yes", "--changelog") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @@ -676,14 +573,12 @@ def test_bump_with_changelog_arg(mocker: MockFixture, changelog_path): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_changelog_config(mocker: MockFixture, changelog_path, config_path): - create_file_and_commit("feat(user): new file") +def test_bump_with_changelog_config(util: UtilFixture, changelog_path, config_path): + util.create_file_and_commit("feat(user): new file") with open(config_path, "a", encoding="utf-8") as fp: fp.write("update_changelog_on_bump = true\n") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @@ -694,23 +589,18 @@ def test_bump_with_changelog_config(mocker: MockFixture, changelog_path, config_ @pytest.mark.usefixtures("tmp_commitizen_project") -def test_prevent_prerelease_when_no_increment_detected(mocker: MockFixture, capsys): - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) +def test_prevent_prerelease_when_no_increment_detected(util: UtilFixture, capsys): + util.create_file_and_commit("feat: new file") - cli.main() + util.run_cli("bump", "--yes") out, _ = capsys.readouterr() assert "0.2.0" in out - create_file_and_commit("test: new file") - testargs = ["cz", "bump", "-pr", "beta"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("test: new file") with pytest.raises(NoCommitsFoundError) as excinfo: - cli.main() + util.run_cli("bump", "-pr", "beta") expected_error_message = ( "[NO_COMMITS_FOUND]\nNo commits found to generate a pre-release." @@ -719,11 +609,9 @@ def test_prevent_prerelease_when_no_increment_detected(mocker: MockFixture, caps @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_changelog_to_stdout_arg(mocker: MockFixture, capsys, changelog_path): - create_file_and_commit("feat(user): this should appear in stdout") - testargs = ["cz", "bump", "--yes", "--changelog-to-stdout"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_with_changelog_to_stdout_arg(util: UtilFixture, capsys, changelog_path): + util.create_file_and_commit("feat(user): this should appear in stdout") + util.run_cli("bump", "--yes", "--changelog-to-stdout") out, _ = capsys.readouterr() assert "this should appear in stdout" in out @@ -738,15 +626,13 @@ def test_bump_with_changelog_to_stdout_arg(mocker: MockFixture, capsys, changelo @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_with_changelog_to_stdout_dry_run_arg( - mocker: MockFixture, capsys, changelog_path + util: UtilFixture, capsys, changelog_path ): - create_file_and_commit( + util.create_file_and_commit( "feat(user): this should appear in stdout with dry-run enabled" ) - testargs = ["cz", "bump", "--yes", "--changelog-to-stdout", "--dry-run"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("bump", "--yes", "--changelog-to-stdout", "--dry-run") out, _ = capsys.readouterr() tag_exists = git.tag_exist("0.2.0") @@ -757,11 +643,9 @@ def test_bump_with_changelog_to_stdout_dry_run_arg( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_without_git_to_stdout_arg(mocker: MockFixture, capsys, changelog_path): - create_file_and_commit("feat(user): this should appear in stdout") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_without_git_to_stdout_arg(util: UtilFixture, capsys, changelog_path): + util.create_file_and_commit("feat(user): this should appear in stdout") + util.run_cli("bump", "--yes") out, _ = capsys.readouterr() assert ( @@ -771,11 +655,9 @@ def test_bump_without_git_to_stdout_arg(mocker: MockFixture, capsys, changelog_p @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_git_to_stdout_arg(mocker: MockFixture, capsys, changelog_path): - create_file_and_commit("feat(user): this should appear in stdout") - testargs = ["cz", "bump", "--yes", "--git-output-to-stderr"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_bump_with_git_to_stdout_arg(util: UtilFixture, capsys, changelog_path): + util.create_file_and_commit("feat(user): this should appear in stdout") + util.run_cli("bump", "--yes", "--git-output-to-stderr") out, _ = capsys.readouterr() assert ( @@ -831,9 +713,8 @@ def test_bump_with_git_to_stdout_arg(mocker: MockFixture, capsys, changelog_path @pytest.mark.parametrize( "cli_bump_changelog_args", [ - ("cz", "bump", "--changelog", "--yes"), + ("bump", "--changelog", "--yes"), ( - "cz", "bump", "--changelog", "--changelog-to-stdout", @@ -842,11 +723,13 @@ def test_bump_with_git_to_stdout_arg(mocker: MockFixture, capsys, changelog_path "--yes", ), ], - ids=lambda cmd_tuple: " ".join(cmd_tuple), + ids=lambda cmd_tuple: " ".join(["cz", *cmd_tuple]) + if isinstance(cmd_tuple, tuple) + else cmd_tuple, ) def test_bump_changelog_command_commits_untracked_changelog_and_version_files( tmp_commitizen_project, - mocker, + util: UtilFixture, cli_bump_changelog_args: tuple[str, ...], version_filepath: str, version_regex: str, @@ -872,10 +755,9 @@ def test_bump_changelog_command_commits_untracked_changelog_and_version_files( ) as version_file: version_file.write(version_file_content) - create_file_and_commit("fix: some test commit") + util.create_file_and_commit("fix: some test commit") - mocker.patch.object(sys, "argv", cli_bump_changelog_args) - cli.main() + util.run_cli(*cli_bump_changelog_args) commit_file_names = git.get_filenames_in_commit() assert "CHANGELOG.md" in commit_file_names @@ -885,21 +767,19 @@ def test_bump_changelog_command_commits_untracked_changelog_and_version_files( @pytest.mark.parametrize( "testargs", [ - ["cz", "bump", "--local-version", "1.2.3"], - ["cz", "bump", "--prerelease", "rc", "1.2.3"], - ["cz", "bump", "--devrelease", "0", "1.2.3"], - ["cz", "bump", "--devrelease", "1", "1.2.3"], - ["cz", "bump", "--increment", "PATCH", "1.2.3"], - ["cz", "bump", "--build-metadata=a.b.c", "1.2.3"], - ["cz", "bump", "--local-version", "--build-metadata=a.b.c"], + ["--local-version", "1.2.3"], + ["--prerelease", "rc", "1.2.3"], + ["--devrelease", "0", "1.2.3"], + ["--devrelease", "1", "1.2.3"], + ["--increment", "PATCH", "1.2.3"], + ["--build-metadata=a.b.c", "1.2.3"], + ["--local-version", "--build-metadata=a.b.c"], ], ) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_invalid_manual_args_raises_exception(mocker, testargs): - mocker.patch.object(sys, "argv", testargs) - +def test_bump_invalid_manual_args_raises_exception(util: UtilFixture, testargs): with pytest.raises(NotAllowed): - cli.main() + util.run_cli("bump", *testargs) @pytest.mark.usefixtures("tmp_commitizen_project") @@ -910,14 +790,13 @@ def test_bump_invalid_manual_args_raises_exception(mocker, testargs): "1.2..3", ], ) -def test_bump_invalid_manual_version_raises_exception(mocker, manual_version): - create_file_and_commit("feat: new file") - - testargs = ["cz", "bump", "--yes", manual_version] - mocker.patch.object(sys, "argv", testargs) +def test_bump_invalid_manual_version_raises_exception( + util: UtilFixture, manual_version +): + util.create_file_and_commit("feat: new file") with pytest.raises(InvalidManualVersion) as excinfo: - cli.main() + util.run_cli("bump", "--yes", manual_version) expected_error_message = ( f"[INVALID_MANUAL_VERSION]\nInvalid manual version: '{manual_version}'" @@ -939,26 +818,22 @@ def test_bump_invalid_manual_version_raises_exception(mocker, manual_version): "1.0.0", ], ) -def test_bump_manual_version(mocker, manual_version): - create_file_and_commit("feat: new file") +def test_bump_manual_version(util: UtilFixture, manual_version): + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes", manual_version] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", manual_version) tag_exists = git.tag_exist(manual_version) assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_manual_version_disallows_major_version_zero(mocker): - create_file_and_commit("feat: new file") +def test_bump_manual_version_disallows_major_version_zero(util: UtilFixture): + util.create_file_and_commit("feat: new file") manual_version = "0.2.0" - testargs = ["cz", "bump", "--yes", "--major-version-zero", manual_version] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(NotAllowed) as excinfo: - cli.main() + util.run_cli("bump", "--yes", "--major-version-zero", manual_version) expected_error_message = ( "--major-version-zero cannot be combined with MANUAL_VERSION" @@ -968,7 +843,7 @@ def test_bump_manual_version_disallows_major_version_zero(mocker): @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) def test_bump_with_pre_bump_hooks( - commit_msg, mocker: MockFixture, tmp_commitizen_project + commit_msg, mocker: MockFixture, tmp_commitizen_project, util: UtilFixture ): pre_bump_hook = "scripts/pre_bump_hook.sh" post_bump_hook = "scripts/post_bump_hook.sh" @@ -983,10 +858,8 @@ def test_bump_with_pre_bump_hooks( run_mock = mocker.Mock() mocker.patch.object(hooks, "run", run_mock) - create_file_and_commit(commit_msg) - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit(commit_msg) + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @@ -1021,7 +894,9 @@ def test_bump_with_pre_bump_hooks( ) -def test_bump_with_hooks_and_increment(mocker: MockFixture, tmp_commitizen_project): +def test_bump_with_hooks_and_increment( + mocker: MockFixture, tmp_commitizen_project, util: UtilFixture +): pre_bump_hook = "scripts/pre_bump_hook.sh" post_bump_hook = "scripts/post_bump_hook.sh" @@ -1035,28 +910,23 @@ def test_bump_with_hooks_and_increment(mocker: MockFixture, tmp_commitizen_proje run_mock = mocker.Mock() mocker.patch.object(hooks, "run", run_mock) - create_file_and_commit("test: some test") - testargs = ["cz", "bump", "--yes", "--increment", "MINOR"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("test: some test") + util.run_cli("bump", "--yes", "--increment", "MINOR") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @pytest.mark.usefixtures("tmp_git_project") -def test_bump_use_version_provider(mocker: MockFixture): +def test_bump_use_version_provider(mocker: MockFixture, util: UtilFixture): mock = mocker.MagicMock(name="provider") mock.get_version.return_value = "0.0.0" get_provider = mocker.patch( "commitizen.commands.bump.get_provider", return_value=mock ) - create_file_and_commit("fix: fake commit") - testargs = ["cz", "bump", "--yes", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - - cli.main() + util.create_file_and_commit("fix: fake commit") + util.run_cli("bump", "--yes", "--changelog") assert git.tag_exist("0.0.1") get_provider.assert_called_once() @@ -1065,23 +935,20 @@ def test_bump_use_version_provider(mocker: MockFixture): def test_bump_command_prerelease_scheme_via_cli( - tmp_commitizen_project_initial, mocker: MockFixture + tmp_commitizen_project_initial, util: UtilFixture ): tmp_commitizen_project = tmp_commitizen_project_initial() tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") - testargs = [ - "cz", + util.run_cli( "bump", "--prerelease", "alpha", "--yes", "--version-scheme", "semver", - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + ) tag_exists = git.tag_exist("0.2.0-a0") assert tag_exists is True @@ -1091,9 +958,7 @@ def test_bump_command_prerelease_scheme_via_cli( assert "0.2.0-a0" in f.read() # PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @@ -1104,7 +969,7 @@ def test_bump_command_prerelease_scheme_via_cli( def test_bump_command_prerelease_scheme_via_config( - tmp_commitizen_project_initial, mocker: MockFixture + tmp_commitizen_project_initial, util: UtilFixture ): tmp_commitizen_project = tmp_commitizen_project_initial( config_extra='version_scheme = "semver"\n', @@ -1112,9 +977,7 @@ def test_bump_command_prerelease_scheme_via_config( tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("0.2.0-a0") assert tag_exists is True @@ -1123,9 +986,7 @@ def test_bump_command_prerelease_scheme_via_config( with open(version_file) as f: assert "0.2.0-a0" in f.read() - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("0.2.0-a1") assert tag_exists is True @@ -1135,9 +996,7 @@ def test_bump_command_prerelease_scheme_via_config( assert "0.2.0-a1" in f.read() # PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") tag_exists = git.tag_exist("0.2.0") assert tag_exists is True @@ -1148,7 +1007,7 @@ def test_bump_command_prerelease_scheme_via_config( def test_bump_command_prerelease_scheme_check_old_tags( - tmp_commitizen_project_initial, mocker: MockFixture + tmp_commitizen_project_initial, util: UtilFixture ): tmp_commitizen_project = tmp_commitizen_project_initial( config_extra=('tag_format = "v$version"\nversion_scheme = "semver"\n'), @@ -1156,9 +1015,7 @@ def test_bump_command_prerelease_scheme_check_old_tags( tmp_version_file = tmp_commitizen_project.join("__version__.py") tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") - testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha", "--yes") tag_exists = git.tag_exist("v0.2.0-a0") assert tag_exists is True @@ -1167,9 +1024,7 @@ def test_bump_command_prerelease_scheme_check_old_tags( with open(version_file) as f: assert "0.2.0-a0" in f.read() - testargs = ["cz", "bump", "--prerelease", "alpha"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--prerelease", "alpha") tag_exists = git.tag_exist("v0.2.0-a1") assert tag_exists is True @@ -1179,9 +1034,7 @@ def test_bump_command_prerelease_scheme_check_old_tags( assert "0.2.0-a1" in f.read() # PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE - testargs = ["cz", "bump"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump") tag_exists = git.tag_exist("v0.2.0") assert tag_exists is True @@ -1201,12 +1054,10 @@ def test_bump_command_prerelease_scheme_check_old_tags( ("major: bug affecting users", "1.0.0"), ], ) -def test_bump_with_plugin(mocker: MockFixture, message: str, expected_tag: str): - create_file_and_commit(message) +def test_bump_with_plugin(util: UtilFixture, message: str, expected_tag: str): + util.create_file_and_commit(message) - testargs = ["cz", "--name", "cz_semver", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("--name", "cz_semver", "bump", "--yes") tag_exists = git.tag_exist(expected_tag) assert tag_exists is True @@ -1223,56 +1074,48 @@ def test_bump_with_plugin(mocker: MockFixture, message: str, expected_tag: str): ], ) def test_bump_with_major_version_zero_with_plugin( - mocker: MockFixture, message: str, expected_tag: str + util: UtilFixture, message: str, expected_tag: str ): - create_file_and_commit(message) + util.create_file_and_commit(message) - testargs = ["cz", "--name", "cz_semver", "bump", "--yes", "--major-version-zero"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("--name", "cz_semver", "bump", "--yes", "--major-version-zero") tag_exists = git.tag_exist(expected_tag) assert tag_exists is True @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_command_version_type_deprecation(mocker: MockFixture): - create_file_and_commit("feat: check deprecation on --version-type") +def test_bump_command_version_type_deprecation(util: UtilFixture): + util.create_file_and_commit("feat: check deprecation on --version-type") - testargs = [ - "cz", - "bump", - "--prerelease", - "alpha", - "--yes", - "--version-type", - "semver", - ] - mocker.patch.object(sys, "argv", testargs) with pytest.warns(DeprecationWarning): - cli.main() + util.run_cli( + "bump", + "--prerelease", + "alpha", + "--yes", + "--version-type", + "semver", + ) assert git.tag_exist("0.2.0-a0") @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_command_version_scheme_priority_over_version_type(mocker: MockFixture): - create_file_and_commit("feat: check deprecation on --version-type") +def test_bump_command_version_scheme_priority_over_version_type(util: UtilFixture): + util.create_file_and_commit("feat: check deprecation on --version-type") - testargs = [ - "cz", - "bump", - "--prerelease", - "alpha", - "--yes", - "--version-type", - "semver", - "--version-scheme", - "pep440", - ] - mocker.patch.object(sys, "argv", testargs) with pytest.warns(DeprecationWarning): - cli.main() + util.run_cli( + "bump", + "--prerelease", + "alpha", + "--yes", + "--version-type", + "semver", + "--version-scheme", + "pep440", + ) assert git.tag_exist("0.2.0a0") @@ -1288,8 +1131,8 @@ def test_bump_command_version_scheme_priority_over_version_type(mocker: MockFixt ), ) def test_bump_template_option_precedence( - mocker: MockFixture, tmp_commitizen_project: Path, + util: UtilFixture, any_changelog_format: ChangelogFormat, arg: str, cfg: str, @@ -1305,7 +1148,7 @@ def test_bump_template_option_precedence( cmd_template.write_text("from cmd") default_template.write_text("default") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") if cfg: pyproject = project_root / "pyproject.toml" @@ -1319,19 +1162,19 @@ def test_bump_template_option_precedence( ) ) - testargs = ["cz", "bump", "--yes", "--changelog"] + args = ["bump", "--yes", "--changelog"] if arg: - testargs.append(arg) - mocker.patch.object(sys, "argv", testargs + ["0.1.1"]) - cli.main() + args.append(arg) + args.append("0.1.1") + util.run_cli(*args) out = changelog.read_text() assert out == expected def test_bump_template_extras_precedence( - mocker: MockFixture, tmp_commitizen_project: Path, + util: UtilFixture, any_changelog_format: ChangelogFormat, mock_plugin: BaseCommitizen, ): @@ -1356,37 +1199,33 @@ def test_bump_template_extras_precedence( ) ) - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = [ - "cz", + util.run_cli( "bump", "--yes", "--changelog", "--extra", "first=from-command", "0.1.1", - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + ) changelog = project_root / any_changelog_format.default_changelog_file assert changelog.read_text() == "from-command - from-config - from-plugin" def test_bump_template_extra_quotes( - mocker: MockFixture, tmp_commitizen_project: Path, + util: UtilFixture, any_changelog_format: ChangelogFormat, ): project_root = Path(tmp_commitizen_project) changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("{{first}} - {{second}} - {{third}}") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") - testargs = [ - "cz", + util.run_cli( "bump", "--changelog", "--yes", @@ -1397,15 +1236,15 @@ def test_bump_template_extra_quotes( "-e", 'third="double quotes"', "0.1.1", - ] - mocker.patch.object(sys, "argv", testargs) - cli.main() + ) changelog = project_root / any_changelog_format.default_changelog_file assert changelog.read_text() == "no-quote - single quotes - double quotes" -def test_bump_changelog_contains_increment_only(mocker, tmp_commitizen_project, capsys): +def test_bump_changelog_contains_increment_only( + tmp_commitizen_project, util: UtilFixture, capsys +): """Issue 1024""" # Initialize commitizen up to v1.0.0 project_root = Path(tmp_commitizen_project) @@ -1415,23 +1254,19 @@ def test_bump_changelog_contains_increment_only(mocker, tmp_commitizen_project, ) tmp_changelog_file = project_root / "CHANGELOG.md" tmp_changelog_file.write_text("## v1.0.0") - create_file_and_commit("feat(user): new file") - create_tag("v1.0.0") + util.create_file_and_commit("feat(user): new file") + util.create_tag("v1.0.0") # Add a commit and bump to v2.0.0 - create_file_and_commit("feat(user)!: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat(user)!: new file") + util.run_cli("bump", "--yes") _ = capsys.readouterr() # Add a commit and create the incremental changelog to v3.0.0 # it should only include v3 changes - create_file_and_commit("feat(next)!: next version") - testargs = ["cz", "bump", "--yes", "--files-only", "--changelog-to-stdout"] - mocker.patch.object(sys, "argv", testargs) + util.create_file_and_commit("feat(next)!: next version") with pytest.raises(ExpectedExit): - cli.main() + util.run_cli("bump", "--yes", "--files-only", "--changelog-to-stdout") out, _ = capsys.readouterr() assert "3.0.0" in out @@ -1439,13 +1274,11 @@ def test_bump_changelog_contains_increment_only(mocker, tmp_commitizen_project, @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next(mocker: MockFixture, capsys): - create_file_and_commit("feat: new file") +def test_bump_get_next(util: UtilFixture, capsys): + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--yes", "--get-next"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("bump", "--yes", "--get-next") out, _ = capsys.readouterr() assert "0.2.0" in out @@ -1455,17 +1288,13 @@ def test_bump_get_next(mocker: MockFixture, capsys): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next_update_changelog_on_bump( - mocker: MockFixture, capsys, config_path -): - create_file_and_commit("feat: new file") +def test_bump_get_next_update_changelog_on_bump(util: UtilFixture, capsys, config_path): + util.create_file_and_commit("feat: new file") with open(config_path, "a", encoding="utf-8") as fp: fp.write("update_changelog_on_bump = true\n") - testargs = ["cz", "bump", "--yes", "--get-next"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(DryRunExit): - cli.main() + util.run_cli("bump", "--yes", "--get-next") out, _ = capsys.readouterr() assert "0.2.0" in out @@ -1475,119 +1304,96 @@ def test_bump_get_next_update_changelog_on_bump( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next__no_eligible_commits_raises(mocker: MockFixture): - create_file_and_commit("chore: new commit") - - testargs = ["cz", "bump", "--yes", "--get-next"] - mocker.patch.object(sys, "argv", testargs) +def test_bump_get_next__no_eligible_commits_raises(util: UtilFixture): + util.create_file_and_commit("chore: new commit") with pytest.raises(NoneIncrementExit): - cli.main() + util.run_cli("bump", "--yes", "--get-next") -def test_bump_allow_no_commit_with_no_commit(mocker, tmp_commitizen_project, capsys): +def test_bump_allow_no_commit_with_no_commit( + tmp_commitizen_project, util: UtilFixture, capsys +): with tmp_commitizen_project.as_cwd(): # Create the first commit and bump to 1.0.0 - create_file_and_commit("feat(user)!: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat(user)!: new file") + util.run_cli("bump", "--yes") # Verify NoCommitsFoundError should be raised # when there's no new commit and "--allow-no-commit" is not set with pytest.raises(NoCommitsFoundError): - testargs = ["cz", "bump"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump") # bump to 1.0.1 with new commit when "--allow-no-commit" is set - testargs = ["cz", "bump", "--allow-no-commit"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--allow-no-commit") out, _ = capsys.readouterr() assert "bump: version 1.0.0 → 1.0.1" in out def test_bump_allow_no_commit_with_no_eligible_commit( - mocker, tmp_commitizen_project, capsys + tmp_commitizen_project, util: UtilFixture, capsys ): with tmp_commitizen_project.as_cwd(): # Create the first commit and bump to 1.0.0 - create_file_and_commit("feat(user)!: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat(user)!: new file") + util.run_cli("bump", "--yes") # Create a commit that is ineligible to bump - create_file_and_commit("docs(bump): add description for allow no commit") + util.create_file_and_commit("docs(bump): add description for allow no commit") # Verify NoneIncrementExit should be raised # when there's no eligible bumping commit and "--allow-no-commit" is not set with pytest.raises(NoneIncrementExit): - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") # bump to 1.0.1 with ineligible commit when "--allow-no-commit" is set - testargs = ["cz", "bump", "--allow-no-commit"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--allow-no-commit") out, _ = capsys.readouterr() assert "bump: version 1.0.0 → 1.0.1" in out -def test_bump_allow_no_commit_with_increment(mocker, tmp_commitizen_project, capsys): +def test_bump_allow_no_commit_with_increment( + tmp_commitizen_project, util: UtilFixture, capsys +): with tmp_commitizen_project.as_cwd(): # # Create the first commit and bump to 1.0.0 - create_file_and_commit("feat(user)!: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat(user)!: new file") + util.run_cli("bump", "--yes") # Verify NoCommitsFoundError should be raised # when there's no new commit and "--allow-no-commit" is not set with pytest.raises(NoCommitsFoundError): - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") # bump to 1.1.0 with no new commit when "--allow-no-commit" is set # and increment is specified - testargs = ["cz", "bump", "--yes", "--allow-no-commit", "--increment", "MINOR"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--allow-no-commit", "--increment", "MINOR") out, _ = capsys.readouterr() assert "bump: version 1.0.0 → 1.1.0" in out def test_bump_allow_no_commit_with_manual_version( - mocker, tmp_commitizen_project, capsys + tmp_commitizen_project, util: UtilFixture, capsys ): with tmp_commitizen_project.as_cwd(): # # Create the first commit and bump to 1.0.0 - create_file_and_commit("feat(user)!: new file") - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.create_file_and_commit("feat(user)!: new file") + util.run_cli("bump", "--yes") # Verify NoCommitsFoundError should be raised # when there's no new commit and "--allow-no-commit" is not set with pytest.raises(NoCommitsFoundError): - testargs = ["cz", "bump", "--yes"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes") # bump to 1.1.0 with no new commit when "--allow-no-commit" is set # and increment is specified - testargs = ["cz", "bump", "--yes", "--allow-no-commit", "2.0.0"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--yes", "--allow-no-commit", "2.0.0") out, _ = capsys.readouterr() assert "bump: version 1.0.0 → 2.0.0" in out def test_bump_detect_legacy_tags_from_scm( - tmp_commitizen_project: py.path.local, mocker: MockFixture + tmp_commitizen_project: py.path.local, util: UtilFixture ): project_root = Path(tmp_commitizen_project) tmp_commitizen_cfg_file = project_root / "pyproject.toml" @@ -1603,20 +1409,18 @@ def test_bump_detect_legacy_tags_from_scm( ] ), ) - create_file_and_commit("feat: new file") - create_tag("legacy-0.4.2") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") + util.create_tag("legacy-0.4.2") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--increment", "patch", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--increment", "patch", "--changelog") assert git.tag_exist("v0.4.3") def test_bump_warn_but_dont_fail_on_invalid_tags( tmp_commitizen_project: py.path.local, - mocker: MockFixture, + util: UtilFixture, capsys: pytest.CaptureFixture, ): project_root = Path(tmp_commitizen_project) @@ -1630,15 +1434,13 @@ def test_bump_warn_but_dont_fail_on_invalid_tags( ] ), ) - create_file_and_commit("feat: new file") - create_tag("0.4.2") - create_file_and_commit("feat: new file") - create_tag("0.4.3.deadbeaf") - create_file_and_commit("feat: new file") + util.create_file_and_commit("feat: new file") + util.create_tag("0.4.2") + util.create_file_and_commit("feat: new file") + util.create_tag("0.4.3.deadbeaf") + util.create_file_and_commit("feat: new file") - testargs = ["cz", "bump", "--increment", "patch", "--changelog"] - mocker.patch.object(sys, "argv", testargs) - cli.main() + util.run_cli("bump", "--increment", "patch", "--changelog") _, err = capsys.readouterr() @@ -1646,10 +1448,10 @@ def test_bump_warn_but_dont_fail_on_invalid_tags( assert git.tag_exist("0.4.3") -def test_is_initial_tag(mocker: MockFixture, tmp_commitizen_project): +def test_is_initial_tag(mocker: MockFixture, tmp_commitizen_project, util: UtilFixture): """Test the _is_initial_tag method behavior.""" # Create a commit but no tags - create_file_and_commit("feat: initial commit") + util.create_file_and_commit("feat: initial commit") # Initialize Bump with minimal config config = BaseConfig() diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index 1094e62766..08a2b6cf78 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -1,7 +1,6 @@ from __future__ import annotations import itertools -import sys from pathlib import Path from textwrap import dedent from typing import TYPE_CHECKING @@ -9,7 +8,7 @@ import pytest from jinja2 import FileSystemLoader -from commitizen import cli, git +from commitizen import git from commitizen.commands.changelog import Changelog from commitizen.exceptions import ( DryRunExit, @@ -1692,6 +1691,7 @@ def test_export_changelog_template_from_plugin( mock_plugin: BaseCommitizen, changelog_format: ChangelogFormat, tmp_path: Path, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) target = project_root / "changelog.jinja" @@ -1700,10 +1700,7 @@ def test_export_changelog_template_from_plugin( src.write_text(tpl) mock_plugin.template_loader = FileSystemLoader(tmp_path) - args = ["cz", "changelog", "--export-template", str(target)] - - mocker.patch.object(sys, "argv", args) - cli.main() + util.run_cli("changelog", "--export-template", str(target)) assert target.exists() assert target.read_text() == tpl @@ -1712,6 +1709,7 @@ def test_export_changelog_template_from_plugin( def test_export_changelog_template_fails_when_template_has_no_filename( mocker: MockFixture, tmp_commitizen_project: Path, + util: UtilFixture, ): project_root = Path(tmp_commitizen_project) target = project_root / "changelog.jinja" @@ -1725,11 +1723,8 @@ class FakeTemplate: "commitizen.changelog.get_changelog_template", return_value=FakeTemplate() ) - args = ["cz", "changelog", "--export-template", str(target)] - mocker.patch.object(sys, "argv", args) - with pytest.raises(NotAllowed) as exc_info: - cli.main() + util.run_cli("changelog", "--export-template", str(target)) assert not target.exists() assert "Template filename is not set" in str(exc_info.value) diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index 47dd3fe12c..382814892b 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -1,12 +1,11 @@ from __future__ import annotations -import sys from io import StringIO from typing import TYPE_CHECKING, Any import pytest -from commitizen import cli, commands, git +from commitizen import commands, git from commitizen.cz import registry from commitizen.cz.base import BaseCommitizen, ValidationResult from commitizen.exceptions import ( @@ -15,7 +14,6 @@ InvalidCommitMessageError, NoCommitsFoundError, ) -from tests.utils import create_file_and_commit if TYPE_CHECKING: import re @@ -23,7 +21,10 @@ from pytest_mock import MockFixture + from commitizen.config.base_config import BaseConfig from commitizen.question import CzQuestion + from tests.utils import UtilFixture + COMMIT_LOG = [ "refactor: A code change that neither fixes a bug nor adds a feature", @@ -68,74 +69,70 @@ def _build_fake_git_commits(commit_msgs: list[str]) -> list[git.GitCommit]: return [git.GitCommit("test_rev", commit_msg) for commit_msg in commit_msgs] -def test_check_jira_fails(mocker: MockFixture): - testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_jira_fails(mocker: MockFixture, util: UtilFixture): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="random message for J-2 #fake_command blah"), ) with pytest.raises(InvalidCommitMessageError) as excinfo: - cli.main() + util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") assert "commit validation: failed!" in str(excinfo.value) -def test_check_jira_command_after_issue_one_space(mocker: MockFixture, capsys): - testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_jira_command_after_issue_one_space( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="JR-23 #command some arguments etc"), ) - cli.main() + util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out -def test_check_jira_command_after_issue_two_spaces(mocker: MockFixture, capsys): - testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_jira_command_after_issue_two_spaces( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="JR-2 #command some arguments etc"), ) - cli.main() + util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out -def test_check_jira_text_between_issue_and_command(mocker: MockFixture, capsys): - testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_jira_text_between_issue_and_command( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="JR-234 some text #command some arguments etc"), ) - cli.main() + util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out -def test_check_jira_multiple_commands(mocker: MockFixture, capsys): - testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_jira_multiple_commands(mocker: MockFixture, capsys, util: UtilFixture): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="JRA-23 some text #command1 args #command2 args"), ) - cli.main() + util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out -def test_check_conventional_commit_succeeds(mocker: MockFixture, capsys): - testargs = ["cz", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_conventional_commit_succeeds( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="fix(scope): some commit message"), ) - cli.main() + util.run_cli("check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out @@ -234,9 +231,9 @@ def test_check_command_with_invalid_argument(config): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_check_command_with_empty_range(config, mocker: MockFixture): +def test_check_command_with_empty_range(config: BaseConfig, util: UtilFixture): # must initialize git with a commit - create_file_and_commit("feat: initial") + util.create_file_and_commit("feat: initial") check_cmd = commands.Check(config=config, arguments={"rev_range": "master..master"}) with pytest.raises(NoCommitsFoundError) as excinfo: @@ -356,29 +353,29 @@ def test_check_command_override_allowed_prefixes_config(config, mocker: MockFixt error_mock.assert_called_once() -def test_check_command_with_pipe_message(mocker: MockFixture, capsys): - testargs = ["cz", "check"] - mocker.patch.object(sys, "argv", testargs) +def test_check_command_with_pipe_message( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch("sys.stdin", StringIO("fix(scope): some commit message")) - cli.main() + util.run_cli("check") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out -def test_check_command_with_pipe_message_and_failed(mocker: MockFixture): - testargs = ["cz", "check"] - mocker.patch.object(sys, "argv", testargs) +def test_check_command_with_pipe_message_and_failed( + mocker: MockFixture, util: UtilFixture +): mocker.patch("sys.stdin", StringIO("bad commit message")) with pytest.raises(InvalidCommitMessageError) as excinfo: - cli.main() + util.run_cli("check") assert "commit validation: failed!" in str(excinfo.value) -def test_check_command_with_comment_in_message_file(mocker: MockFixture, capsys): - testargs = ["cz", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) +def test_check_command_with_comment_in_message_file( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open( @@ -391,12 +388,14 @@ def test_check_command_with_comment_in_message_file(mocker: MockFixture, capsys) "This pre-commit hook will check our commits automatically." ), ) - cli.main() + util.run_cli("check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out -def test_check_conventional_commit_succeed_with_git_diff(mocker, capsys): +def test_check_conventional_commit_succeed_with_git_diff( + mocker, capsys, util: UtilFixture +): commit_msg = ( "feat: This is a test commit\n" "# Please enter the commit message for your changes. Lines starting\n" @@ -416,13 +415,11 @@ def test_check_conventional_commit_succeed_with_git_diff(mocker, capsys): "@@ -92,3 +92,4 @@ class Command(BaseCommand):\n" '+ "this is a test"\n' ) - testargs = ["cz", "check", "--commit-msg-file", "some_file"] - mocker.patch.object(sys, "argv", testargs) mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data=commit_msg), ) - cli.main() + util.run_cli("check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() assert "Commit validation: successful!" in out @@ -600,36 +597,24 @@ def use_cz_custom_validator(mocker): @pytest.mark.usefixtures("use_cz_custom_validator") -def test_check_command_with_custom_validator_succeed(mocker: MockFixture, capsys): - testargs = [ - "cz", - "--name", - "cz_custom_validator", - "check", - "--commit-msg-file", - "some_file", - ] - mocker.patch.object(sys, "argv", testargs) +def test_check_command_with_custom_validator_succeed( + mocker: MockFixture, capsys, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open(read_data="ABC-123: add commitizen pre-commit hook"), ) - cli.main() + util.run_cli( + "--name", "cz_custom_validator", "check", "--commit-msg-file", "some_file" + ) out, _ = capsys.readouterr() assert "Commit validation: successful!" in out @pytest.mark.usefixtures("use_cz_custom_validator") -def test_check_command_with_custom_validator_failed(mocker: MockFixture): - testargs = [ - "cz", - "--name", - "cz_custom_validator", - "check", - "--commit-msg-file", - "some_file", - ] - mocker.patch.object(sys, "argv", testargs) +def test_check_command_with_custom_validator_failed( + mocker: MockFixture, util: UtilFixture +): mocker.patch( "commitizen.commands.check.open", mocker.mock_open( @@ -637,7 +622,9 @@ def test_check_command_with_custom_validator_failed(mocker: MockFixture): ), ) with pytest.raises(InvalidCommitMessageError) as excinfo: - cli.main() + util.run_cli( + "--name", "cz_custom_validator", "check", "--commit-msg-file", "some_file" + ) assert "commit validation: failed!" in str(excinfo.value), ( "Pattern validation unexpectedly passed" ) diff --git a/tests/commands/test_common_command.py b/tests/commands/test_common_command.py index bb9de90bbe..7a5a26b6b2 100644 --- a/tests/commands/test_common_command.py +++ b/tests/commands/test_common_command.py @@ -1,10 +1,8 @@ -import sys - import pytest from pytest_mock import MockFixture -from commitizen import cli from commitizen.commands import Example, Info, ListCz, Schema +from tests.utils import UtilFixture @pytest.mark.parametrize( @@ -24,11 +22,11 @@ ) @pytest.mark.usefixtures("python_version") def test_command_shows_description_when_use_help_option( - mocker: MockFixture, capsys, file_regression, monkeypatch: pytest.MonkeyPatch, command: str, + util: UtilFixture, ): """Test that the command shows the description when the help option is used. @@ -42,10 +40,8 @@ def test_command_shows_description_when_use_help_option( monkeypatch.setenv("NO_COLOR", "1") monkeypatch.setenv("PAGER", "cat") - testargs = ["cz", command, "--help"] - mocker.patch.object(sys, "argv", testargs) with pytest.raises(SystemExit): - cli.main() + util.run_cli(command, "--help") out, _ = capsys.readouterr() file_regression.check(out, extension=".txt") diff --git a/tests/providers/test_scm_provider.py b/tests/providers/test_scm_provider.py index e28a6782ab..1de4bf8fb9 100644 --- a/tests/providers/test_scm_provider.py +++ b/tests/providers/test_scm_provider.py @@ -6,16 +6,10 @@ from commitizen.providers import get_provider from commitizen.providers.scm_provider import ScmProvider -from tests.utils import ( - create_branch, - create_file_and_commit, - create_tag, - merge_branch, - switch_branch, -) if TYPE_CHECKING: from commitizen.config.base_config import BaseConfig + from tests.utils import UtilFixture @pytest.mark.parametrize( @@ -46,12 +40,16 @@ ) @pytest.mark.usefixtures("tmp_git_project") def test_scm_provider( - config: BaseConfig, tag_format: str, tag: str, expected_version: str + config: BaseConfig, + tag_format: str, + tag: str, + expected_version: str, + util: UtilFixture, ): - create_file_and_commit("test: fake commit") - create_tag(tag) - create_file_and_commit("test: fake commit") - create_tag("should-not-match") + util.create_file_and_commit("test: fake commit") + util.create_tag(tag) + util.create_file_and_commit("test: fake commit") + util.create_tag("should-not-match") config.settings["version_provider"] = "scm" config.settings["tag_format"] = tag_format @@ -75,52 +73,54 @@ def test_scm_provider_default_without_commits_and_tags(config: BaseConfig): @pytest.mark.usefixtures("tmp_git_project") -def test_scm_provider_default_with_commits_and_tags(config: BaseConfig): +def test_scm_provider_default_with_commits_and_tags( + config: BaseConfig, util: UtilFixture +): config.settings["version_provider"] = "scm" provider = get_provider(config) assert isinstance(provider, ScmProvider) assert provider.get_version() == "0.0.0" - create_file_and_commit("Initial state") - create_tag("1.0.0") + util.create_file_and_commit("Initial state") + util.create_tag("1.0.0") # create develop - create_branch("develop") - switch_branch("develop") + util.create_branch("develop") + util.switch_branch("develop") # add a feature to develop - create_file_and_commit("develop: add beta feature1") + util.create_file_and_commit("develop: add beta feature1") assert provider.get_version() == "1.0.0" - create_tag("1.1.0b0") + util.create_tag("1.1.0b0") # create staging - create_branch("staging") - switch_branch("staging") - create_file_and_commit("staging: Starting release candidate") + util.create_branch("staging") + util.switch_branch("staging") + util.create_file_and_commit("staging: Starting release candidate") assert provider.get_version() == "1.1.0b0" - create_tag("1.1.0rc0") + util.create_tag("1.1.0rc0") # add another feature to develop - switch_branch("develop") - create_file_and_commit("develop: add beta feature2") + util.switch_branch("develop") + util.create_file_and_commit("develop: add beta feature2") assert provider.get_version() == "1.1.0b0" - create_tag("1.2.0b0") + util.create_tag("1.2.0b0") # add a hotfix to master - switch_branch("master") - create_file_and_commit("master: add hotfix") + util.switch_branch("master") + util.create_file_and_commit("master: add hotfix") assert provider.get_version() == "1.0.0" - create_tag("1.0.1") + util.create_tag("1.0.1") # merge the hotfix to staging - switch_branch("staging") - merge_branch("master") + util.switch_branch("staging") + util.merge_branch("master") assert provider.get_version() == "1.1.0rc0" @pytest.mark.usefixtures("tmp_git_project") -def test_scm_provider_detect_legacy_tags(config: BaseConfig): +def test_scm_provider_detect_legacy_tags(config: BaseConfig, util: UtilFixture): config.settings["version_provider"] = "scm" config.settings["tag_format"] = "v${version}" config.settings["legacy_tag_formats"] = [ @@ -129,14 +129,14 @@ def test_scm_provider_detect_legacy_tags(config: BaseConfig): ] provider = get_provider(config) - create_file_and_commit("test: fake commit") - create_tag("old-0.4.1") + util.create_file_and_commit("test: fake commit") + util.create_tag("old-0.4.1") assert provider.get_version() == "0.4.1" - create_file_and_commit("test: fake commit") - create_tag("legacy-0.4.2") + util.create_file_and_commit("test: fake commit") + util.create_tag("legacy-0.4.2") assert provider.get_version() == "0.4.2" - create_file_and_commit("test: fake commit") - create_tag("v0.5.0") + util.create_file_and_commit("test: fake commit") + util.create_tag("v0.5.0") assert provider.get_version() == "0.5.0" diff --git a/tests/test_bump_create_commit_message.py b/tests/test_bump_create_commit_message.py index 0002659396..0477b5eeb9 100644 --- a/tests/test_bump_create_commit_message.py +++ b/tests/test_bump_create_commit_message.py @@ -3,9 +3,9 @@ from textwrap import dedent import pytest -from pytest_mock import MockFixture -from commitizen import bump, cli, cmd, exceptions +from commitizen import bump, cmd, exceptions +from tests.utils import UtilFixture conversion = [ ( @@ -38,14 +38,13 @@ def test_create_tag(test_input, expected): ), ) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_pre_commit_changelog(mocker: MockFixture, freezer, retry): - freezer.move_to("2022-04-01") - testargs = ["cz", "bump", "--changelog", "--yes"] +def test_bump_pre_commit_changelog(util: UtilFixture, retry): + util.freezer.move_to("2022-04-01") + bump_args = ["bump", "--changelog", "--yes"] if retry: - testargs.append("--retry") + bump_args.append("--retry") else: pytest.xfail("it will fail because pre-commit will reformat CHANGELOG.md") - mocker.patch.object(sys, "argv", testargs) # Configure prettier as a pre-commit hook Path(".pre-commit-config.yaml").write_text( dedent( @@ -71,7 +70,7 @@ def test_bump_pre_commit_changelog(mocker: MockFixture, freezer, retry): cmd.run("git add -A") cmd.run('git commit -m "fix: _test"') cmd.run("pre-commit install") - cli.main() + util.run_cli(*bump_args) # Pre-commit fixed last line adding extra indent and "\" char assert Path("CHANGELOG.md").read_text() == dedent( """\ @@ -86,12 +85,11 @@ def test_bump_pre_commit_changelog(mocker: MockFixture, freezer, retry): @pytest.mark.parametrize("retry", (True, False)) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_pre_commit_changelog_fails_always(mocker: MockFixture, freezer, retry): - freezer.move_to("2022-04-01") - testargs = ["cz", "bump", "--changelog", "--yes"] +def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry): + util.freezer.move_to("2022-04-01") + bump_args = ["bump", "--changelog", "--yes"] if retry: - testargs.append("--retry") - mocker.patch.object(sys, "argv", testargs) + bump_args.append("--retry") Path(".pre-commit-config.yaml").write_text( dedent( """\ @@ -110,20 +108,19 @@ def test_bump_pre_commit_changelog_fails_always(mocker: MockFixture, freezer, re cmd.run('git commit -m "feat: forbid changelogs"') cmd.run("pre-commit install") with pytest.raises(exceptions.BumpCommitFailedError): - cli.main() + util.run_cli(*bump_args) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_build_metadata(mocker: MockFixture, freezer): +def test_bump_with_build_metadata(util: UtilFixture): def _add_entry(test_str: str, args: list): Path(test_str).write_text("") cmd.run("git add -A") cmd.run(f'git commit -m "fix: test-{test_str}"') - cz_args = ["cz", "bump", "--changelog", "--yes"] + args - mocker.patch.object(sys, "argv", cz_args) - cli.main() + cz_args = ["bump", "--changelog", "--yes"] + args + util.run_cli(*cz_args) - freezer.move_to("2024-01-01") + util.freezer.move_to("2024-01-01") _add_entry("a", ["--build-metadata", "a.b.c"]) _add_entry("b", []) diff --git a/tests/test_cli.py b/tests/test_cli.py index f91a27373a..9a362e81e0 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -15,69 +15,51 @@ NoCommandFoundError, NotAGitProjectError, ) +from tests.utils import UtilFixture -def test_sysexit_no_argv(mocker: MockFixture, capsys): - testargs = ["cz"] - mocker.patch.object(sys, "argv", testargs) - +def test_sysexit_no_argv(util: UtilFixture, capsys): with pytest.raises(ExpectedExit): - cli.main() + util.run_cli() out, _ = capsys.readouterr() assert out.startswith("usage") -def test_cz_config_file_without_correct_file_path(mocker: MockFixture, capsys): - testargs = ["cz", "--config", "./config/pyproject.toml", "example"] - mocker.patch.object(sys, "argv", testargs) - +def test_cz_config_file_without_correct_file_path(util: UtilFixture, capsys): with pytest.raises(ConfigFileNotFound) as excinfo: - cli.main() + util.run_cli("--config", "./config/pyproject.toml", "example") assert "Cannot found the config file" in str(excinfo.value) -def test_cz_with_arg_but_without_command(mocker: MockFixture): - testargs = ["cz", "--name", "cz_jira"] - mocker.patch.object(sys, "argv", testargs) - +def test_cz_with_arg_but_without_command(util: UtilFixture): with pytest.raises(NoCommandFoundError) as excinfo: - cli.main() + util.run_cli("--name", "cz_jira") assert "Command is required" in str(excinfo.value) -def test_name(mocker: MockFixture, capsys): - testargs = ["cz", "-n", "cz_jira", "example"] - mocker.patch.object(sys, "argv", testargs) - - cli.main() +def test_name(util: UtilFixture, capsys): + util.run_cli("-n", "cz_jira", "example") out, _ = capsys.readouterr() assert out.startswith("JRA") @pytest.mark.usefixtures("tmp_git_project") -def test_name_default_value(mocker: MockFixture, capsys): - testargs = ["cz", "example"] - mocker.patch.object(sys, "argv", testargs) - - cli.main() +def test_name_default_value(util: UtilFixture, capsys): + util.run_cli("example") out, _ = capsys.readouterr() assert out.startswith("fix: correct minor typos in code") -def test_ls(mocker: MockFixture, capsys): - testargs = ["cz", "-n", "cz_jira", "ls"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_ls(util: UtilFixture, capsys): + util.run_cli("-n", "cz_jira", "ls") out, err = capsys.readouterr() assert "cz_conventional_commits" in out assert isinstance(out, str) -def test_arg_debug(mocker: MockFixture): - testargs = ["cz", "--debug", "info"] - mocker.patch.object(sys, "argv", testargs) - cli.main() +def test_arg_debug(util: UtilFixture): + util.run_cli("--debug", "info") excepthook = sys.excepthook # `sys.excepthook` is replaced by a `partial` in `cli.main` # it's not a normal function @@ -167,19 +149,15 @@ def test_parse_no_raise_mix_invalid_arg_is_skipped(): assert result == [1, 2, 4] -def test_unknown_args_raises(mocker: MockFixture): - testargs = ["cz", "c", "-this_arg_is_not_supported"] - mocker.patch.object(sys, "argv", testargs) +def test_unknown_args_raises(util: UtilFixture): with pytest.raises(InvalidCommandArgumentError) as excinfo: - cli.main() + util.run_cli("c", "-this_arg_is_not_supported") assert "Invalid commitizen arguments were found" in str(excinfo.value) -def test_unknown_args_before_double_dash_raises(mocker: MockFixture): - testargs = ["cz", "c", "-this_arg_is_not_supported", "--"] - mocker.patch.object(sys, "argv", testargs) +def test_unknown_args_before_double_dash_raises(util: UtilFixture): with pytest.raises(InvalidCommandArgumentError) as excinfo: - cli.main() + util.run_cli("c", "-this_arg_is_not_supported", "--") assert "Invalid commitizen arguments were found before -- separator" in str( excinfo.value ) diff --git a/tests/test_git.py b/tests/test_git.py index 12c0e2ad82..3fb25a8e65 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -9,18 +9,13 @@ from commitizen import cmd, git from commitizen.exceptions import GitCommandError -from tests.utils import ( - FakeCommand, - create_branch, - create_file_and_commit, - create_tag, - switch_branch, -) if TYPE_CHECKING: from pytest_gitconfig import GitConfig from pytest_mock import MockFixture + from tests.utils import UtilFixture + @pytest.mark.parametrize("date", ["2020-01-21", "1970-01-01"]) def test_git_tag_date(date: str): @@ -39,13 +34,13 @@ def test_git_object_eq(): assert git_commit != "sha1-code" -def test_get_tags(mocker: MockFixture): +def test_get_tags(util: UtilFixture): tag_str = ( "v1.0.0---inner_delimiter---333---inner_delimiter---2020-01-20---inner_delimiter---\n" "v0.5.0---inner_delimiter---222---inner_delimiter---2020-01-17---inner_delimiter---\n" "v0.0.1---inner_delimiter---111---inner_delimiter---2020-01-17---inner_delimiter---\n" ) - mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=tag_str)) + util.mock_cmd(out=tag_str) git_tags = git.get_tags() latest_git_tag = git_tags[0] @@ -53,55 +48,49 @@ def test_get_tags(mocker: MockFixture): assert latest_git_tag.name == "v1.0.0" assert latest_git_tag.date == "2020-01-20" - mocker.patch( - "commitizen.cmd.run", return_value=FakeCommand(out="", err="No tag available") - ) + util.mock_cmd(out="", err="No tag available") assert git.get_tags() == [] -def test_get_reachable_tags(tmp_commitizen_project): - with tmp_commitizen_project.as_cwd(): - create_file_and_commit("Initial state") - create_tag("1.0.0") - # create develop - create_branch("develop") - switch_branch("develop") +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_get_reachable_tags(util: UtilFixture): + util.create_file_and_commit("Initial state") + util.create_tag("1.0.0") + # create develop + util.create_branch("develop") + util.switch_branch("develop") - # add a feature to develop - create_file_and_commit("develop") - create_tag("1.1.0b0") + # add a feature to develop + util.create_file_and_commit("develop") + util.create_tag("1.1.0b0") - # create staging - switch_branch("master") - create_file_and_commit("master") - create_tag("1.0.1") + # create staging + util.switch_branch("master") + util.create_file_and_commit("master") + util.create_tag("1.0.1") - tags = git.get_tags(reachable_only=True) - tag_names = set([t.name for t in tags]) - # 1.1.0b0 is not present - assert tag_names == {"1.0.0", "1.0.1"} + tags = git.get_tags(reachable_only=True) + tag_names = set([t.name for t in tags]) + # 1.1.0b0 is not present + assert tag_names == {"1.0.0", "1.0.1"} +@pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.parametrize("locale", ["en_US", "fr_FR"]) -def test_get_reachable_tags_with_commits( - tmp_commitizen_project, locale: str, monkeypatch: pytest.MonkeyPatch -): +def test_get_reachable_tags_with_commits(locale: str, monkeypatch: pytest.MonkeyPatch): monkeypatch.setenv("LANG", f"{locale}.UTF-8") monkeypatch.setenv("LANGUAGE", f"{locale}.UTF-8") monkeypatch.setenv("LC_ALL", f"{locale}.UTF-8") - with tmp_commitizen_project.as_cwd(): - assert git.get_tags(reachable_only=True) == [] + assert git.get_tags(reachable_only=True) == [] -def test_get_tag_names(mocker: MockFixture): +def test_get_tag_names(util: UtilFixture): tag_str = "v1.0.0\nv0.5.0\nv0.0.1\n" - mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=tag_str)) + util.mock_cmd(out=tag_str) assert git.get_tag_names() == ["v1.0.0", "v0.5.0", "v0.0.1"] - mocker.patch( - "commitizen.cmd.run", return_value=FakeCommand(out="", err="No tag available") - ) + util.mock_cmd(out="", err="No tag available") assert git.get_tag_names() == [] @@ -126,23 +115,23 @@ def test_get_log_as_str_list_empty(): @pytest.mark.usefixtures("tmp_commitizen_project") -def test_get_commits(): - create_file_and_commit("feat(users): add username") - create_file_and_commit("fix: username exception") +def test_get_commits(util: UtilFixture): + util.create_file_and_commit("feat(users): add username") + util.create_file_and_commit("fix: username exception") commits = git.get_commits() assert len(commits) == 2 @pytest.mark.usefixtures("tmp_commitizen_project") -def test_get_commits_author_and_email(): - create_file_and_commit("fix: username exception") +def test_get_commits_author_and_email(util: UtilFixture): + util.create_file_and_commit("fix: username exception") commit = git.get_commits()[0] assert commit.author != "" assert "@" in commit.author_email -def test_get_commits_without_email(mocker: MockFixture): +def test_get_commits_without_email(util: UtilFixture): raw_commit = ( "a515bb8f71c403f6f7d1c17b9d8ebf2ce3959395\n" "95bbfc703eb99cb49ba0d6ffd8469911303dbe63 12d3b4bdaa996ea7067a07660bb5df4772297bdd\n" @@ -157,7 +146,7 @@ def test_get_commits_without_email(mocker: MockFixture): "\n" "----------commit-delimiter----------\n" ) - mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=raw_commit)) + util.mock_cmd(out=raw_commit) commits = git.get_commits() @@ -171,7 +160,7 @@ def test_get_commits_without_email(mocker: MockFixture): assert commits[1].title == "feat(users): add username" -def test_get_commits_without_breakline_in_each_commit(mocker: MockFixture): +def test_get_commits_without_breakline_in_each_commit(util: UtilFixture): raw_commit = ( "ae9ba6fc5526cf478f52ef901418d85505109744\n" "ff2f56ca844de72a9d59590831087bf5a97bac84\n" @@ -192,7 +181,7 @@ def test_get_commits_without_breakline_in_each_commit(mocker: MockFixture): "user@email.edu\n" "----------commit-delimiter----------\n" ) - mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=raw_commit)) + util.mock_cmd(out=raw_commit) commits = git.get_commits() @@ -211,7 +200,7 @@ def test_get_commits_without_breakline_in_each_commit(mocker: MockFixture): ) -def test_get_commits_with_and_without_parents(mocker: MockFixture): +def test_get_commits_with_and_without_parents(util: UtilFixture): raw_commit = ( "4206e661bacf9643373255965f34bbdb382cb2b9\n" "ae9ba6fc5526cf478f52ef901418d85505109744 bf8479e7aa1a5b9d2f491b79e3a4d4015519903e\n" @@ -232,7 +221,7 @@ def test_get_commits_with_and_without_parents(mocker: MockFixture): "user@email.com\n" "----------commit-delimiter----------\n" ) - mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=raw_commit)) + util.mock_cmd(out=raw_commit) commits = git.get_commits() @@ -280,93 +269,86 @@ def test_get_tag_names_has_correct_arrow_annotation(): assert arrow_annotation == "list[str]" -def test_get_latest_tag_name(tmp_commitizen_project): - with tmp_commitizen_project.as_cwd(): - tag_name = git.get_latest_tag_name() - assert tag_name is None +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_get_latest_tag_name(util: UtilFixture): + tag_name = git.get_latest_tag_name() + assert tag_name is None - create_file_and_commit("feat(test): test") - cmd.run("git tag 1.0") - tag_name = git.get_latest_tag_name() - assert tag_name == "1.0" + util.create_file_and_commit("feat(test): test") + util.create_tag("1.0") + tag_name = git.get_latest_tag_name() + assert tag_name == "1.0" -def test_is_staging_clean_when_adding_file(tmp_commitizen_project): - with tmp_commitizen_project.as_cwd(): - assert git.is_staging_clean() is True +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_is_staging_clean_when_adding_file(): + assert git.is_staging_clean() is True - cmd.run("touch test_file") + cmd.run("touch test_file") - assert git.is_staging_clean() is True + assert git.is_staging_clean() is True - cmd.run("git add test_file") + cmd.run("git add test_file") - assert git.is_staging_clean() is False + assert git.is_staging_clean() is False -def test_is_staging_clean_when_updating_file(tmp_commitizen_project): - with tmp_commitizen_project.as_cwd(): - assert git.is_staging_clean() is True +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_is_staging_clean_when_updating_file(): + assert git.is_staging_clean() is True - cmd.run("touch test_file") - cmd.run("git add test_file") - if os.name == "nt": - cmd.run('git commit -m "add test_file"') - else: - cmd.run("git commit -m 'add test_file'") - cmd.run("echo 'test' > test_file") + cmd.run("touch test_file") + cmd.run("git add test_file") + if os.name == "nt": + cmd.run('git commit -m "add test_file"') + else: + cmd.run("git commit -m 'add test_file'") + cmd.run("echo 'test' > test_file") - assert git.is_staging_clean() is True + assert git.is_staging_clean() is True - cmd.run("git add test_file") + cmd.run("git add test_file") - assert git.is_staging_clean() is False + assert git.is_staging_clean() is False -def test_get_eol_for_open(tmp_commitizen_project): - with tmp_commitizen_project.as_cwd(): - assert git.EOLType.for_open() == os.linesep +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_get_eol_for_open(): + assert git.EOLType.for_open() == os.linesep - cmd.run("git config core.eol lf") - assert git.EOLType.for_open() == "\n" + cmd.run("git config core.eol lf") + assert git.EOLType.for_open() == "\n" - cmd.run("git config core.eol crlf") - assert git.EOLType.for_open() == "\r\n" + cmd.run("git config core.eol crlf") + assert git.EOLType.for_open() == "\r\n" - cmd.run("git config core.eol native") - assert git.EOLType.for_open() == os.linesep + cmd.run("git config core.eol native") + assert git.EOLType.for_open() == os.linesep -def test_get_core_editor(mocker): - mocker.patch.dict(os.environ, {"GIT_EDITOR": "nano"}) +def test_get_core_editor(monkeypatch: pytest.MonkeyPatch, util: UtilFixture): + monkeypatch.setenv("GIT_EDITOR", "nano") assert git.get_core_editor() == "nano" - mocker.patch.dict(os.environ, clear=True) - mocker.patch( - "commitizen.cmd.run", - return_value=cmd.Command( - out="vim", err="", stdout=b"", stderr=b"", return_code=0 - ), - ) + monkeypatch.delenv("GIT_EDITOR") + + util.mock_cmd(out="vim") assert git.get_core_editor() == "vim" - mocker.patch( - "commitizen.cmd.run", - return_value=cmd.Command(out="", err="", stdout=b"", stderr=b"", return_code=1), - ) + util.mock_cmd() assert git.get_core_editor() is None -def test_create_tag_with_message(tmp_commitizen_project): - with tmp_commitizen_project.as_cwd(): - create_file_and_commit("feat(test): test") - tag_name = "1.0" - tag_message = "test message" - create_tag(tag_name, tag_message) - assert git.get_latest_tag_name() == tag_name - assert git.get_tag_message(tag_name) == ( - tag_message if platform.system() != "Windows" else f"'{tag_message}'" - ) +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_create_tag_with_message(util: UtilFixture): + util.create_file_and_commit("feat(test): test") + tag_name = "1.0" + tag_message = "test message" + util.create_tag(tag_name, tag_message) + assert git.get_latest_tag_name() == tag_name + assert git.get_tag_message(tag_name) == ( + tag_message if platform.system() != "Windows" else f"'{tag_message}'" + ) @pytest.mark.parametrize( @@ -391,8 +373,10 @@ def test_create_tag_with_message(tmp_commitizen_project): "Path does not contain spaces", ], ) -def test_commit_with_spaces_in_path(mocker, file_path, expected_cmd): - mock_run = mocker.patch("commitizen.cmd.run", return_value=FakeCommand()) +def test_commit_with_spaces_in_path( + mocker: MockFixture, file_path: str, expected_cmd: str, util: UtilFixture +): + mock_run = util.mock_cmd() mock_unlink = mocker.patch("os.unlink") mock_temp_file = mocker.patch("commitizen.git.NamedTemporaryFile") mock_temp_file.return_value.name = file_path @@ -403,12 +387,9 @@ def test_commit_with_spaces_in_path(mocker, file_path, expected_cmd): mock_unlink.assert_called_once_with(file_path) -def test_get_filenames_in_commit_error(mocker: MockFixture): +def test_get_filenames_in_commit_error(util: UtilFixture): """Test that GitCommandError is raised when git command fails.""" - mocker.patch( - "commitizen.cmd.run", - return_value=FakeCommand(out="", err="fatal: bad object HEAD", return_code=1), - ) + util.mock_cmd(err="fatal: bad object HEAD", return_code=1) with pytest.raises(GitCommandError) as excinfo: git.get_filenames_in_commit() assert str(excinfo.value) == "fatal: bad object HEAD" @@ -475,27 +456,23 @@ def test_git_commit_from_rev_and_commit(): ("posix", None, 'git commit -F "temp.txt"'), ], ) -def test_create_commit_cmd_string(mocker, os_name, committer_date, expected_cmd): +def test_create_commit_cmd_string( + mocker: MockFixture, os_name: str, committer_date: str, expected_cmd: str +): """Test the OS-specific behavior of _create_commit_cmd_string""" mocker.patch("os.name", os_name) result = git._create_commit_cmd_string("", committer_date, "temp.txt") assert result == expected_cmd -def test_get_default_branch_success(mocker: MockFixture): - mocker.patch( - "commitizen.cmd.run", return_value=FakeCommand(out="refs/remotes/origin/main\n") - ) +def test_get_default_branch_success(util: UtilFixture): + util.mock_cmd(out="refs/remotes/origin/main\n") assert git.get_default_branch() == "refs/remotes/origin/main" -def test_get_default_branch_error(mocker: MockFixture): - mocker.patch( - "commitizen.cmd.run", - return_value=FakeCommand( - err="fatal: ref refs/remotes/origin/HEAD is not a symbolic ref", - return_code=1, - ), +def test_get_default_branch_error(util: UtilFixture): + util.mock_cmd( + err="fatal: ref refs/remotes/origin/HEAD is not a symbolic ref", return_code=1 ) with pytest.raises(GitCommandError): git.get_default_branch() diff --git a/tests/utils.py b/tests/utils.py index 57161d83b1..bca565f78c 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -10,8 +10,11 @@ import pytest from commitizen import cli, cmd, exceptions, git +from commitizen.cmd import Command if TYPE_CHECKING: + from unittest.mock import Mock + from freezegun.api import FrozenDateTimeFactory from pytest_mock import MockerFixture @@ -26,52 +29,6 @@ class VersionSchemeTestArgs(NamedTuple): devrelease: int | None -class FakeCommand: - def __init__(self, out=None, err=None, return_code=0): - self.out = out - self.err = err - self.return_code = return_code - - -def create_file_and_commit( - message: str, filename: str | None = None, committer_date: str | None = None -): - if not filename: - filename = str(uuid.uuid4()) - - Path(filename).touch() - c = cmd.run("git add .") - if c.return_code != 0: - raise exceptions.CommitError(c.err) - c = git.commit(message, committer_date=committer_date) - if c.return_code != 0: - raise exceptions.CommitError(c.err) - - -def create_branch(name: str): - c = cmd.run(f"git branch {name}") - if c.return_code != 0: - raise exceptions.GitCommandError(c.err) - - -def switch_branch(branch: str): - c = cmd.run(f"git switch {branch}") - if c.return_code != 0: - raise exceptions.GitCommandError(c.err) - - -def merge_branch(branch: str): - c = cmd.run(f"git merge {branch}") - if c.return_code != 0: - raise exceptions.GitCommandError(c.err) - - -def create_tag(tag: str, message: str | None = None) -> None: - c = git.tag(tag, annotated=(message is not None), msg=message) - if c.return_code != 0: - raise exceptions.CommitError(c.err) - - @dataclass class UtilFixture: """ @@ -160,6 +117,11 @@ def tick(self) -> None: self.freezer.tick() self.patch_env() + def mock_cmd(self, out: str = "", err: str = "", return_code: int = 0) -> Mock: + """Mock cmd.run command.""" + return_value = Command(out, err, b"", b"", return_code) + return self.mocker.patch("commitizen.cmd.run", return_value=return_value) + @pytest.fixture def util( From b4bb2dcfbd4c23c77df5a2616f0d00ce121cebb8 Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:26:09 +0100 Subject: [PATCH 167/221] style(ruff): add `UP` and `TC` fixes to the safe fixes list (#1767) --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index e27f97fcb0..e46372abc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -229,6 +229,10 @@ select = [ "TC006", ] ignore = ["E501", "D1", "D415"] +extend-safe-fixes = [ + "TC", # Move imports inside/outside TYPE_CHECKING blocks + "UP", # Update syntaxes for current Python version recommendations +] [tool.ruff.lint.per-file-ignores] "tests/*" = ["ANN", "S101"] From 7327ae19030aba2c63427d12e35af56d3d919adf Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:29:50 +0100 Subject: [PATCH 168/221] ci(bump): fix the missing permissions for trusted publishing (fix #1759) (#1761) --- .github/workflows/pythonpublish.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index bddf13a5d8..3230cb814d 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -8,6 +8,9 @@ on: jobs: deploy: runs-on: ubuntu-latest + permissions: + id-token: write + contents: read steps: - uses: actions/checkout@v6 with: From de5c7a94d7d67491130dda3945efe331ed695c1e Mon Sep 17 00:00:00 2001 From: "Axel H." <noirbizarre@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:03:04 +0100 Subject: [PATCH 169/221] ci(release): uses `pypa/gh-action-pypi-publish@release/v1` to release with attestations (#1768) --- .github/workflows/pythonpublish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 3230cb814d..d7bce79c4e 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -20,5 +20,5 @@ jobs: uses: astral-sh/setup-uv@v7 - name: Build run: uv build - - name: Publish - run: uv publish + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 From 1d891958fdefd1e403743b82cd7a0ccafc56774b Mon Sep 17 00:00:00 2001 From: Wei Lee <weilee.rx@gmail.com> Date: Mon, 5 Jan 2026 23:22:30 +0800 Subject: [PATCH 170/221] test: upgrade min pytest to 9 and use native toml configuration --- pyproject.toml | 6 +++--- uv.lock | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e46372abc5..55b4fb0318 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -100,7 +100,7 @@ dev = [ base = ["poethepoet>=0.34.0"] test = [ - "pytest>=7.2", + "pytest>=9", "pytest-cov>=4", "pytest-mock>=3.10", "pytest-regressions>=2.4.0", @@ -177,8 +177,8 @@ omit = [ ] -[tool.pytest.ini_options] -addopts = "--strict-markers" +[tool.pytest] +addopts = ["--strict-markers"] testpaths = ["tests/"] filterwarnings = [ # get_smart_tag_range is deprecated and will be removed in v5 diff --git a/uv.lock b/uv.lock index d23b812146..b2189224e3 100644 --- a/uv.lock +++ b/uv.lock @@ -296,7 +296,7 @@ dev = [ { name = "mypy", specifier = ">=1.16.0" }, { name = "poethepoet", specifier = ">=0.34.0" }, { name = "pre-commit", specifier = ">=3.2.0" }, - { name = "pytest", specifier = ">=7.2" }, + { name = "pytest", specifier = ">=9" }, { name = "pytest-cov", specifier = ">=4" }, { name = "pytest-freezer", specifier = ">=0.4.6" }, { name = "pytest-gitconfig", specifier = ">=0.9.0" }, @@ -329,7 +329,7 @@ linters = [ ] script = [{ name = "rich", specifier = ">=13.7.1" }] test = [ - { name = "pytest", specifier = ">=7.2" }, + { name = "pytest", specifier = ">=9" }, { name = "pytest-cov", specifier = ">=4" }, { name = "pytest-freezer", specifier = ">=0.4.6" }, { name = "pytest-gitconfig", specifier = ">=0.9.0" }, From 63c529d6f413ebfa470013b61895f3652cd76fd1 Mon Sep 17 00:00:00 2001 From: BelpHegoR17 <bel02082024@gmail.com> Date: Tue, 6 Jan 2026 20:03:59 +0530 Subject: [PATCH 171/221] docs(config/configuration_file.md): document --config option (#1770) * docs(config/configuration_file.md): document the --config CLI option * docs(config/configuration_file.md): specify the error * docs(config/configuration_file.md): fix indent --- docs/config/configuration_file.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/config/configuration_file.md b/docs/config/configuration_file.md index 8469102550..71944cb713 100644 --- a/docs/config/configuration_file.md +++ b/docs/config/configuration_file.md @@ -20,6 +20,14 @@ Configuration files are typically located in the root of your project directory. The first valid configuration file found will be used. If no configuration file is found, Commitizen will use its default settings. +!!! note + Commitizen supports explicitly specifying a configuration file using the `--config` option, which is useful when the configuration file is not located in the project root directory. + When `--config` is provided, Commitizen will only load configuration from the specified file and will not search for configuration files using the default search order described above. If the specified configuration file does not exist, Commitizen raises the `ConfigFileNotFound` error. If the specified configuration file exists but is empty, Commitizen raises the `ConfigFileIsEmpty` error. + + ```bash + cz --config <PATH> <command> + ``` + !!! tip For Python projects, it's recommended to add your Commitizen configuration to `pyproject.toml` to keep all project configuration in one place. From d1f8bf06256a4a1388506fa21d8712506146e4e8 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Tue, 6 Jan 2026 23:31:44 +0800 Subject: [PATCH 172/221] docs: update incorrect comment (#1775) --- .github/workflows/links.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index ac8336a86b..8bd275ffab 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -11,7 +11,7 @@ jobs: check-links: runs-on: ubuntu-latest permissions: - issues: write # required for peter-evans/create-issue-from-file + issues: write # required for Broken Links Report steps: - uses: actions/checkout@v6 From b7cc22014630b957ff60231db5529bbddacefc64 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Wed, 7 Jan 2026 18:36:36 +0800 Subject: [PATCH 173/221] docs(faq): categorize faq into "how to", "feature request graveyard", and "history" (#1722) --- docs/faq.md | 82 +++------------------------------------ docs/features_wont_add.md | 72 ++++++++++++++++++++++++++++++++-- docs/history.md | 23 +++++++++++ mkdocs.yml | 3 +- 4 files changed, 98 insertions(+), 82 deletions(-) create mode 100644 docs/history.md diff --git a/docs/faq.md b/docs/faq.md index fba72325b8..568ec2fbe8 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,4 +1,6 @@ -This page contains frequently asked questions about Commitizen. +# FAQ + +This page contains frequently asked how to questions. ## Support for [`PEP621`](https://peps.python.org/pep-0621/) @@ -23,15 +25,6 @@ version = "2.5.1" version_provider = "pep621" ``` -## Why are `revert` and `chore` valid types in the check pattern of `cz_conventional_commits` but not types we can select? - -`revert` and `chore` are added to the `pattern` in `cz check` in order to prevent backward errors, but officially they are not part of conventional commits, we are using the latest [types from Angular](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type) (they used to but were removed). -However, you can create a customized `cz` with those extra types. (See [Customization](customization/config_file.md)). - -See more discussion in -- [issue #142](https://github.com/commitizen-tools/commitizen/issues/142) -- [issue #36](https://github.com/commitizen-tools/commitizen/issues/36) - ## How to revert a bump? If for any reason, the created tag and changelog were to be undone, this is the snippet: @@ -50,28 +43,6 @@ In case the commit was pushed to the server, you can remove it by running: git push --delete origin <created_tag> ``` -## Is this project affiliated with the [Commitizen JS][cz-js] project? - -**It is not affiliated.** - -Both are used for similar purposes, parsing commits, generating changelog and version we presume. -This one is written in python to make integration easier for python projects and the other serves the JS packages. - -<!-- TODO: Add more details about the differences between Commitizen and Commitizen JS --> - -They differ a bit in design, not sure if cz-js does any of this, but these are some things you can do with our Commitizen: - -- create custom rules, version bumps and changelog generation. By default, we use the popular conventional commits (I think cz-js allows this). -- single package, install one thing and it will work. cz-js is a monorepo, but you have to install different dependencies as far as I know. -- pre-commit integration -- works on any language project, as long as you create the `.cz.toml` or `cz.toml` file. - -Where do they cross paths? - -If you are using conventional commits in your git history, then you could swap one with the other in theory. - -Regarding the name, [cz-js][cz-js] came first, they used the word Commitizen first. When this project was created originally, the creator read "be a good commitizen", and thought it was just a cool word that made sense, and this would be a package that helps you be a good "commit citizen". - ## How to handle revert commits? ```sh @@ -79,58 +50,17 @@ git revert --no-commit <SHA> git commit -m "revert: foo bar" ``` -## Why don't we use [Pydantic](https://docs.pydantic.dev/)? - -While Pydantic is a powerful and popular library for data validation, we intentionally avoid using it in this project to keep our dependency tree minimal and maintainable. - -Including Pydantic would increase the chances of version conflicts for users - especially with major changes introduced in Pydantic v3. Because we pin dependencies tightly, adding Pydantic could unintentionally restrict what other tools or libraries users can install alongside `commitizen`. - -Moreover we don't rely on the full feature set of Pydantic. Simpler alternatives like Python's built-in `TypedDict` offer sufficient type safety for our use cases, without the runtime overhead or dependency burden. - -In short, avoiding Pydantic helps us: -- Keep dependencies lightweight -- Reduce compatibility issues for users -- Maintain clarity about what contributors should and shouldn't use - - ## I got `Exception [WinError 995] The I/O operation ...` error This error was caused by a Python bug on Windows. It's been fixed by [cpython #22017](https://github.com/python/cpython/pull/22017), and according to Python's changelog, [3.8.6rc1](https://docs.python.org/3.8/whatsnew/changelog.html#python-3-8-6-release-candidate-1) and [3.9.0rc2](https://docs.python.org/3.9/whatsnew/changelog.html#python-3-9-0-release-candidate-2) should be the accurate versions first contain this fix. In conclusion, upgrade your Python version might solve this issue. More discussion can be found in issue [#318](https://github.com/commitizen-tools/commitizen/issues/318). -## Why does Commitizen not support CalVer? - -`commitizen` could support CalVer alongside SemVer, but in practice implementing CalVer -creates numerous edge cases that are difficult to maintain ([#385]) and more generally, -mixing the two version schemes may not be a good idea. If CalVer or other custom -versioning scheme is needed, `commitizen` could still be used to standardize commits -and create changelogs, but a separate package should be used for version increments. - -Mixing CalVer and SemVer is generally not recommended because each versioning scheme -serves a different purpose. Diverging from either specification can be confusing to -users and cause errors with third-party tools that don't expect the non-standard format. - -In the future, `commitizen` may support some implementation of CalVer, but at the time -of writing, there are no plans to implement the feature ([#173]). - -If you would like to learn more about both schemes, there are plenty of good resources: - -- [Announcing CalVer](https://sedimental.org/calver.html) -- [API Versioning from Stripe](https://stripe.com/blog/api-versioning) -- [Discussion about pip's use of CalVer](https://github.com/pypa/pip/issues/5645#issuecomment-407192448) -- [Git Version Numbering](https://code.erpenbeck.io/git/2021/12/16/git-version-numbering/) -- [SemVer vs. CalVer and Why I Use Both](https://mikestaszel.com/post/semver-vs-calver-and-why-i-use-both/) (but not at the same time) -- [Semver Will Not Save You](https://hynek.me/articles/semver-will-not-save-you/) -- [Why I Don't Like SemVer](https://snarky.ca/why-i-dont-like-semver/) - -[#173]: https://github.com/commitizen-tools/commitizen/issues/173 -[#385]: https://github.com/commitizen-tools/commitizen/pull/385 - ## How to change the tag format ? You can use the [`legacy_tag_formats`](config/bump.md#legacy_tag_formats) to list old tag formats. New bumped tags will be in the new format but old ones will still work for: + - changelog generation (full, incremental and version range) - bump new version computation (automatically guessed or increment given) @@ -146,7 +76,7 @@ legacy_tag_formats = [ ] ``` -## How to avoid warnings for expected non-version tags +## How to avoid warnings for expected non-version tags? You can explicitly ignore them with [`ignored_tag_formats`](config/bump.md#ignored_tag_formats). @@ -159,5 +89,3 @@ ignored_tag_formats = [ "v${major}.${minor}", ] ``` - -[cz-js]: https://github.com/commitizen/cz-cli diff --git a/docs/features_wont_add.md b/docs/features_wont_add.md index 9fbd6d5b5c..01b5da1ff7 100644 --- a/docs/features_wont_add.md +++ b/docs/features_wont_add.md @@ -1,7 +1,71 @@ -This page contains features that have been proposed or considered but won't be implemented in Commitizen. +# Feature request graveyard + +This page contains features and designs that have been proposed or considered but won't be implemented in Commitizen. For a comprehensive list, please refer to our [issue tracker](https://github.com/commitizen-tools/commitizen/issues?q=is:issue%20state:closed%20label:%22issue-status:%20wont-fix%22%20OR%20label:%22issue-status:%20wont-implement%22). -- Enable multiple locations of config file `.cz.*` [#955](https://github.com/commitizen-tools/commitizen/issues/955) -- Create a flag to build the changelog from commits in multiple git repositories [#790](https://github.com/commitizen-tools/commitizen/issues/790) -- Global Configuration [#597](https://github.com/commitizen-tools/commitizen/issues/597) +## Enable multiple locations of config file `.cz.*` [#955](https://github.com/commitizen-tools/commitizen/issues/955) + +<!-- TODO: Add more details about why we won't add this feature --> + +## Create a flag to build the changelog from commits in multiple git repositories [#790](https://github.com/commitizen-tools/commitizen/issues/790) + +<!-- TODO: Add more details about why we won't add this feature --> + +## Global Configuration [#597](https://github.com/commitizen-tools/commitizen/issues/597) + +<!-- TODO: Add more details about why we won't add this feature --> + +## Why are `revert` and `chore` valid types in the check pattern of `cz_conventional_commits` but not types we can select? + +`revert` and `chore` are added to the `pattern` in `cz check` in order to prevent backward errors, but officially they are not part of conventional commits, we are using the latest [types from Angular](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type) (they used to but were removed). +However, you can create a customized `cz` with those extra types. (See [Customization](customization/config_file.md)). + +See more discussion in + +- [issue #142](https://github.com/commitizen-tools/commitizen/issues/142) +- [issue #36](https://github.com/commitizen-tools/commitizen/issues/36) + + +## Why does Commitizen not support CalVer? + +`commitizen` could support CalVer alongside SemVer, but in practice implementing CalVer +creates numerous edge cases that are difficult to maintain ([#385]) and more generally, +mixing the two version schemes may not be a good idea. If CalVer or other custom +versioning scheme is needed, `commitizen` could still be used to standardize commits +and create changelogs, but a separate package should be used for version increments. + +Mixing CalVer and SemVer is generally not recommended because each versioning scheme +serves a different purpose. Diverging from either specification can be confusing to +users and cause errors with third-party tools that don't expect the non-standard format. + +In the future, `commitizen` may support some implementation of CalVer, but at the time +of writing, there are no plans to implement the feature ([#173]). + +If you would like to learn more about both schemes, there are plenty of good resources: + +- [Announcing CalVer](https://sedimental.org/calver.html) +- [API Versioning from Stripe](https://stripe.com/blog/api-versioning) +- [Discussion about pip's use of CalVer](https://github.com/pypa/pip/issues/5645#issuecomment-407192448) +- [Git Version Numbering](https://code.erpenbeck.io/git/2021/12/16/git-version-numbering/) +- [SemVer vs. CalVer and Why I Use Both](https://mikestaszel.com/post/semver-vs-calver-and-why-i-use-both/) (but not at the same time) +- [Semver Will Not Save You](https://hynek.me/articles/semver-will-not-save-you/) +- [Why I Don't Like SemVer](https://snarky.ca/why-i-dont-like-semver/) + +[#173]: https://github.com/commitizen-tools/commitizen/issues/173 +[#385]: https://github.com/commitizen-tools/commitizen/pull/385 + + +## Why don't we use [Pydantic](https://docs.pydantic.dev/)? + +While Pydantic is a powerful and popular library for data validation, we intentionally avoid using it in this project to keep our dependency tree minimal and maintainable. + +Including Pydantic would increase the chances of version conflicts for users - especially with major changes introduced in Pydantic v3. Because we pin dependencies tightly, adding Pydantic could unintentionally restrict what other tools or libraries users can install alongside `commitizen`. + +Moreover we don't rely on the full feature set of Pydantic. Simpler alternatives like Python's built-in `TypedDict` offer sufficient type safety for our use cases, without the runtime overhead or dependency burden. + +In short, avoiding Pydantic helps us: + +- Keep dependencies lightweight +- Reduce compatibility issues for users +- Maintain clarity about what contributors should and shouldn't use diff --git a/docs/history.md b/docs/history.md new file mode 100644 index 0000000000..47a726e100 --- /dev/null +++ b/docs/history.md @@ -0,0 +1,23 @@ +## Is this project affiliated with the [cz-cli][cz-cli] project? + +**It is not affiliated.** + +Both are used for similar purposes, parsing commits, generating changelog and version we presume. +Our Commitizen project is written in python to make integration easier for python projects, whereas [cz-cli][cz-cli] is written in JavaScript and serves the JS packages. + +<!-- TODO: Add more details about the differences between Commitizen and cz-cli --> + +They differ a bit in design, not sure if cz-cli does any of this, but these are some things you can do with our Commitizen: + +- create custom rules, version bumps and changelog generation. By default, we use the popular conventional commits (I think cz-cli allows this). +- single package, install one thing and it will work. cz-cli is a monorepo, but you have to install different dependencies as far as I know. +- pre-commit integration +- works on any language project, as long as you create the `.cz.toml` or `cz.toml` file. + +Where do they cross paths? + +If you are using conventional commits in your git history, then you could swap one with the other in theory. + +Regarding the name, [cz-cli][cz-cli] came first, they used the word Commitizen first. When this project was created originally, the creator read "be a good commitizen", and thought it was just a cool word that made sense, and this would be a package that helps you be a good "commit citizen". + +[cz-cli]: https://github.com/commitizen/cz-cli diff --git a/mkdocs.yml b/mkdocs.yml index 28c5b9e382..2ad1a7d718 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -67,7 +67,7 @@ nav: - Developmental releases: "tutorials/dev_releases.md" - Monorepo support: "tutorials/monorepo_guidance.md" - FAQ: "faq.md" - - Features we won't add: "features_wont_add.md" + - "features_wont_add.md" - Exit Codes: "exit_codes.md" - Third-Party Commitizen Plugins: - About: "third-party-plugins/about.md" @@ -83,6 +83,7 @@ nav: - "third-party-plugins/github-jira-conventional.md" - Contributing: "contributing.md" - Contributing TL;DR: "contributing_tldr.md" + - "history.md" - Resources: "external_links.md" markdown_extensions: From eeead21fa2d4317ffbd5986383530a3203c3ef32 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Thu, 8 Jan 2026 17:21:29 +0800 Subject: [PATCH 174/221] docs: add AGENTS.md (#1781) --- AGENTS.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..c2d0e98ae7 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,54 @@ +# AGENTS instructions + +## Purpose + +This file provides **project-specific guidance for AI agents** (and other automated tools) working on the `commitizen` repository. +Follow these instructions in addition to any higher-level system or tool rules. + +## Project Overview + +- **Project**: `commitizen` - a tool to help enforce and automate conventional commits, version bumps, and changelog generation. +- **Primary language**: Python (library + CLI). +- **Key entrypoints**: + - `commitizen/cli.py` - main CLI implementation. + - `commitizen/commands/` - subcommands such as `bump`, `commit`, `changelog`, `check`, etc. + - `commitizen/config/` - configuration discovery and loading. + - `commitizen/providers/` - version providers (e.g., `pep621`, `poetry`, `npm`, `uv`). + +## General Expectations + +- **Preserve public behavior and CLI UX.** +- **Avoid breaking changes** (APIs, CLI flags, exit codes) unless explicitly requested. +- **Keep changes small and focused.** +- **Update or add tests/docs** when you change user-facing behavior. + +## How to Explore and Validate Changes + +- **Code entrypoints**: + - CLI behavior: `commitizen/cli.py` and `commitizen/commands/`. + - Config resolution: `commitizen/config/factory.py` and config modules. + - Bump/changelog/versioning: `commitizen/bump.py`, `commitizen/changelog.py`, `commitizen/version_schemes.py`, `commitizen/providers/`. +- **Docs to consult** (before larger changes): + - `docs/README.md` + - `docs/contributing.md` + - `docs/commands/` and `docs/config/` +- **Tests**: + - Prefer targeted runs, e.g. `uv run pytest tests/test_cli.py` or a specific `tests/commands/` file. + +## Coding Guidelines (for AI tools) + +- **Style**: Follow patterns in nearby code; keep functions focused. +- **Types**: Preserve or improve existing type hints. +- **Errors**: Prefer `commitizen/exceptions.py` error types; keep messages clear for CLI users. +- **Output**: Use `commitizen/out.py`; do not add noisy logging. + +## Common Task Pointers + +- **CLI commands**: edit `commitizen/commands/<name>.py`, wire via `commitizen/cli.py`, and adjust `tests/commands/` + `docs/commands/`. +- **Version bumps / changelog**: use `commitizen/bump.py`, `commitizen/changelog.py`, `commitizen/version_schemes.py`, and `commitizen/providers/` (+ matching tests). +- **Config resolution**: use `commitizen/config/factory.py` and config modules; update `tests/test_conf.py` and related tests. + +## When Unsure + +- Prefer **reading tests and documentation first** to understand the expected behavior. +- When behavior is ambiguous, **assume backward compatibility** with current tests and docs is required. From b86b172b8de4e0174f06660b202dba1a89871187 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Mon, 12 Jan 2026 16:17:35 +0800 Subject: [PATCH 175/221] ci: run unittests only on python and dependency change (#1738) Co-authored-by: Wei Lee <weilee.rx@gmail.com> --- .github/workflows/pythonpackage.yml | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index cdf0d1d17d..45e91e428e 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -8,25 +8,50 @@ on: workflow_dispatch: jobs: + detect_changes: + runs-on: ubuntu-latest + outputs: + relevant: ${{ steps.filter.outputs.relevant }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - id: filter + uses: dorny/paths-filter@v3 + with: + filters: | + relevant: + - "commitizen/**" + - "tests/**" + - ".github/workflows/**" python-check: + needs: detect_changes strategy: matrix: python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] platform: [ubuntu-22.04, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: + - name: No relevant changes, fast-path success + if: ${{ needs.detect_changes.outputs.relevant != 'true' }} + run: | + echo "No relevant file changes; skipping tests and linters." - uses: actions/checkout@v6 + if: ${{ needs.detect_changes.outputs.relevant == 'true' }} with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: astral-sh/setup-uv@v7 + if: ${{ needs.detect_changes.outputs.relevant == 'true' }} with: python-version: ${{ matrix.python-version }} - name: Install dependencies + if: ${{ needs.detect_changes.outputs.relevant == 'true' }} run: | uv --version uv sync --frozen --group base --group test --group linters - name: Run tests and linters + if: ${{ needs.detect_changes.outputs.relevant == 'true' }} run: | git config --global user.email "action@github.com" git config --global user.name "GitHub Action" @@ -34,11 +59,12 @@ jobs: shell: bash - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 + if: ${{ needs.detect_changes.outputs.relevant == 'true' }} with: token: ${{ secrets.CODECOV_TOKEN }} - name: Upload test results to Codecov uses: codecov/codecov-action@v5 - if: ${{ !cancelled() }} + if: ${{ needs.detect_changes.outputs.relevant == 'true' && !cancelled() }} with: token: ${{ secrets.CODECOV_TOKEN }} report_type: test_results From 2b81c8ca48f38e9bd6621d17432bb72992873583 Mon Sep 17 00:00:00 2001 From: Nick Coleman <nicholashadleycoleman@gmail.com> Date: Mon, 12 Jan 2026 08:29:57 +0000 Subject: [PATCH 176/221] fix(config): add warning for multiple configuration files and update documentation (#1773) * feat(config): add warning for multiple configuration files Detects when multiple configuration files exist (excluding pyproject.toml) and displays a warning message identifying which file is being used. Closes #1771 * refactor: simplify multiple config files warning Remove extra steps to check if config files are empty. Just warn about multiple files and show first file from the list. * refactor(config): use walrus operator for git_project_root assignment Co-authored-by: Wei Lee <weilee.rx@gmail.com> * fix(config): only check for multiple configs when filepath is None Co-authored-by: Tim Hsiung <bear890707@gmail.com> * fix(config): improve warning message clarity for multiple config files Co-authored-by: Tim Hsiung <bear890707@gmail.com> * refactor(config): remove _check_and_warn_multiple_configs function; refactor read_cfg function * fix(config): streamline multiple config files warning logic --------- Co-authored-by: Wei Lee <weilee.rx@gmail.com> Co-authored-by: Tim Hsiung <bear890707@gmail.com> --- commitizen/config/__init__.py | 17 ++++++- docs/config/configuration_file.md | 3 ++ tests/test_conf.py | 84 +++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index e30f9f789c..2fb84a1238 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import TYPE_CHECKING -from commitizen import defaults, git +from commitizen import defaults, git, out from commitizen.config.factory import create_config from commitizen.exceptions import ConfigFileIsEmpty, ConfigFileNotFound @@ -35,7 +35,20 @@ def _resolve_config_paths(filepath: str | None = None) -> Generator[Path, None, def read_cfg(filepath: str | None = None) -> BaseConfig: - for filename in _resolve_config_paths(filepath): + config_candidates = list(_resolve_config_paths(filepath)) + + # Check for multiple config files and warn the user + config_candidates_exclude_pyproject = [ + path for path in config_candidates if path.name != "pyproject.toml" + ] + if len(config_candidates_exclude_pyproject) > 1: + filenames = [path.name for path in config_candidates_exclude_pyproject] + out.warn( + f"Multiple config files detected: {', '.join(filenames)}. " + f"Using config file: '{filenames[0]}'." + ) + + for filename in config_candidates: with open(filename, "rb") as f: data: bytes = f.read() diff --git a/docs/config/configuration_file.md b/docs/config/configuration_file.md index 71944cb713..8e4c1f2146 100644 --- a/docs/config/configuration_file.md +++ b/docs/config/configuration_file.md @@ -31,6 +31,9 @@ The first valid configuration file found will be used. If no configuration file !!! tip For Python projects, it's recommended to add your Commitizen configuration to `pyproject.toml` to keep all project configuration in one place. +!!! warning "Multiple Configuration Files" + If Commitizen detects more than one configuration file in your project directory (excluding `pyproject.toml`), it will display a warning message and identify which file is being used. To avoid confusion, ensure you have only one Commitizen configuration file in your project. + ## Supported Formats Commitizen supports three configuration file formats: diff --git a/tests/test_conf.py b/tests/test_conf.py index 0df0d18647..1ef30d5152 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -239,6 +239,90 @@ def test_load_empty_pyproject_toml_from_config_argument(_, tmpdir): with pytest.raises(ConfigFileIsEmpty): config.read_cfg(filepath="./not_in_root/pyproject.toml") + def test_warn_multiple_config_files(_, tmpdir, capsys): + """Test that a warning is issued when multiple config files exist.""" + with tmpdir.as_cwd(): + # Create multiple config files + tmpdir.join(".cz.toml").write(PYPROJECT) + tmpdir.join(".cz.json").write(JSON_STR) + + # Read config + cfg = config.read_cfg() + + # Check that the warning was issued + captured = capsys.readouterr() + assert "Multiple config files detected" in captured.err + assert ".cz.toml" in captured.err + assert ".cz.json" in captured.err + assert "Using" in captured.err + + # Verify the correct config is loaded (first in priority order) + assert cfg.settings == _settings + + def test_warn_multiple_config_files_with_pyproject(_, tmpdir, capsys): + """Test warning excludes pyproject.toml from the warning message.""" + with tmpdir.as_cwd(): + # Create multiple config files including pyproject.toml + tmpdir.join("pyproject.toml").write(PYPROJECT) + tmpdir.join(".cz.json").write(JSON_STR) + + # Read config - should use pyproject.toml (first in priority) + cfg = config.read_cfg() + + # No warning should be issued as only one non-pyproject config exists + captured = capsys.readouterr() + assert "Multiple config files detected" not in captured.err + + # Verify the correct config is loaded + assert cfg.settings == _settings + + def test_warn_multiple_config_files_uses_correct_one(_, tmpdir, capsys): + """Test that the correct config file is used when multiple exist.""" + with tmpdir.as_cwd(): + # Create .cz.json with different settings + json_different = """ + { + "commitizen": { + "name": "cz_conventional_commits", + "version": "2.0.0" + } + } + """ + tmpdir.join(".cz.json").write(json_different) + tmpdir.join(".cz.toml").write(PYPROJECT) + + # Read config - should use pyproject.toml (first in defaults.CONFIG_FILES) + # But since pyproject.toml doesn't exist, .cz.toml is second in priority + cfg = config.read_cfg() + + # Check that warning mentions both files + captured = capsys.readouterr() + assert "Multiple config files detected" in captured.err + assert ".cz.toml" in captured.err + assert ".cz.json" in captured.err + + # Verify .cz.toml was used (second in priority after pyproject.toml) + assert cfg.settings["name"] == "cz_jira" # from PYPROJECT + assert cfg.settings["version"] == "1.0.0" + + def test_no_warn_with_explicit_config_path(_, tmpdir, capsys): + """Test that no warning is issued when user explicitly specifies config.""" + with tmpdir.as_cwd(): + # Create multiple config files + tmpdir.join(".cz.toml").write(PYPROJECT) + tmpdir.join(".cz.json").write(JSON_STR) + + # Read config with explicit path + cfg = config.read_cfg(filepath=".cz.json") + + # No warning should be issued + captured = capsys.readouterr() + assert "Multiple config files detected" not in captured.err + + # Verify the explicitly specified config is loaded (compare to expected JSON config) + json_cfg_expected = JsonConfig(data=JSON_STR, path=Path(".cz.json")) + assert cfg.settings == json_cfg_expected.settings + @pytest.mark.parametrize( "config_file, exception_string", From 193859bee654804538880f21522988cf7de38d5f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Jan 2026 08:30:30 +0000 Subject: [PATCH 177/221] =?UTF-8?q?bump:=20version=204.11.1=20=E2=86=92=20?= =?UTF-8?q?4.11.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f8d29aed7c..522278ad84 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.1 # automatically updated by Commitizen + rev: v4.11.2 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 88ac00b6f7..298bddfdca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.11.2 (2026-01-12) + +### Fix + +- **config**: add warning for multiple configuration files and update documentation (#1773) + ## v4.11.1 (2026-01-03) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 601b9bb2b3..77df5910b1 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.1" +__version__ = "4.11.2" diff --git a/pyproject.toml b/pyproject.toml index 55b4fb0318..66299ab2ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.1" +version = "4.11.2" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index b2189224e3..ddd0ae8e52 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.1" +version = "4.11.2" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 6dd2eaee93c3245162dfd5d88e960ab4bbac6883 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Tue, 13 Jan 2026 01:09:47 +0800 Subject: [PATCH 178/221] docs: add commitizen-tools logo to our docs site (#1786) --- docs/images/cz_logo.png | Bin 0 -> 4092 bytes mkdocs.yml | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 docs/images/cz_logo.png diff --git a/docs/images/cz_logo.png b/docs/images/cz_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f5f0244ec22735a7475e8267f840d8190d68d40 GIT binary patch literal 4092 zcmXw+dpuL||Hm_9a~m5f8HSZh7v;L#FVi-O<Py2&nvgA*Tx&9gGWYwfB*`V0D3rS> zxnFY0ZIio(#Aq(x`F?-DKh8Pt_jy0xuk-%n^Z1<4E9$xthKKVM=dokQcyL(s4d(Of z(FJB_-b*dt<s3W4+loW$m<435PI^2yAD-;kn9lN<zd!HKeo`M864Hl3b7v4$kS18s z%{%DazJjW8OQm?lt%%p@AMR$zFLGT=R}SqTKjAfa($v)Y6}Y1MM-h+|@YZXvNU-EF zm|Na0jZ4ADb>1dJsgioTXN+F`!_MRPp^CT{>GFHGwaxTUE05f4fW8SC$`^e<ig-Qg zDv*?CBY_Z@yK#obhP}VyqhX!$p`;;apYTsb?a9BO2N1fK`6p+AGI3_vk-Po8twz00 z!;=?n{46Fmy?btUgr80U)uoSGw-{1%8tju<lBq8wue=atIjy;nepBwQU1)aA>%0jG zL^Lcc9D^Ow*A_s+K(TR!QADf}J494GUW_F^%@D4xE1?3AkP$=$kkEEOw5}{+9UPSf zj+~)3HA^C?k_f;ver8)_3=wPqI-)NCBoNtnCX@!ow)wU(p?*mObU=s+p`Q^+T|g!T z(*(dI5}6RL28?YoJc61f5iIgY5bzmsr;D8lQMCY6$;>0AMsOrXnK}c7t$`!2D$g<l zIyh1fcQil`G*0z22eWM`me?g5#hfx<8F0fqfjQ;3bZFcll-w(c%*AMfF_YkLZl^`T z6g)W&2?tZwFDzkUTqOLC+&3(YgM<gly~V;nBs@tj3JYT+;n8yLSQsk_A9)ssg>8V9 z$55v#wdun`T~=8-D-(*hdOWm?YFSJ>I;FD;9d<0C9n)FuLlp)uM!agvS>9d=%q(0d z2+dWj+vk!xnyq-zXUGvMN{&ljR_AVwJufI>^wih@$YN=22h#%UYj3!ubN@WtkMZu- z!+iV<f@&RZ>A-_;s}6XKlG~Q`&RL=A%D&B{q|VQ@cg#C}%P5h8Sjh66tEmwh*_vOU z8>u5Sk7Ve}S)3btSmSb@PX=|0D9HQ4ai4z^za4SyrG0@?YWsMpZH=>!#Uk}fayPaF zD8bcHtwn1}&Qy&%?mOf&TrcvqwA_h*G`fvkYMNZqT69*-y|vQXI-<c<b&z;frJ5tO z8}%L<Wv=Z^vD}L|Q!+Yw;h&3}>S5hZkG^d4g`(X~W#kW=F9{Kn3MWQ)3{)y>t5zB_ z;c`xgWR8$ZH&{61S(>_?j=u>fSD9x^k@tt*tOuyAPjWd;>(+A_hY!1Z$K$&r7$P6m zD_s>oUVij@hT`sd*w~Cs4V<i;TTT(wcDC!R-)pug86Tqj^VS^K2pge^=~J-#_TRF< z4~&*OiONHqPRZTVjEc?8hE;wp*<F#Z*-hQ-n<@AE?&7c@5|}k=DzL4w;=&4><*jh0 zVyjtFr{*7$*AF&lcQ!>N$tX+7wPfasVC!h?^^g9^?U_EJKCu)TzC{~!8Xz<!w4Q$z z_El6|Ypvb2s!FXaFD%@2bWnkF2bCfg(7nr(ejIhH!O`dJ{5enGJw|^RY$|A|L;Cd# zLyY69cuI7w`AW`eTf%UUlb{-{XLc}k?(odE^}=Zx&(WzE!^BP3{nq+$)Sr;5{>_W& zK{YPFMA5@-t!&@3L97hAv3o>#^}l$dn{b9bJeCc_J(YM8gcc-EbSAAN7xU(1#MOht z>ek=6o~!HHP1tC|a+J}F)T)Y7qp;5bdG|a2Wu2zA&S4H^X+@?(87CBHio9#>-G6@c z5=g|H<_-aNDI(jCnS^R#7&Z&_9lrvEB)vz-)@{Rr(;k=)t$~5O^(IYEjSXdO&wMo0 zbp*zt?)l&S)U?Z^qHKAiR{CAHeQNVSX4ab~!)r+u^iQu0Qok7&Ao@kIHV**G-F}*5 z=btZD(AO2_H|CvQon&BR=d!aouvP4^1+U5&ub#C!s`FmQpY==g{fAS?DaPB)W3M4g zWVAJcFs+wkpvD@1>6_f0?9_bxu1F8R^s_<1)q@`C7YjYJ&wa1tosO#^lpC1#aLRXY z#Fhoc1n&LbFg<zjRCB?=ZYdhAhESbxxE6bv)qN@QMC3>s=3v%+Z~y76K`IWdD$&mw zc>!fPD~1xwtm;mt>u}ly#snr^ZK5$S*ZV!-gAeM&``IInP?r4RJ=(X%P4Co8=hQP* zI<y`IbFv0+WdQgUpCD;2Gwv*C6?jSfL%Pb?V{?jDmAI#!lc;3w@r`X><Rr`Ma<6^i zszA9m2pR(~*;CUWabLZ9(5OF04TudiBTi0>>1^Z=e1YZMd;idhE$=MEg5toY*OBek zaKUcuF?nv;BA5A1hTL<^0bfncAP<NN%u|3&Nqx$eLKX}(DOpcQfulP;x||$qNGhVy z4+`!LG56m4he!Y}ofxiUF6;F6J7)jaao6kL%=;Rz(!6QajbC4SyxdHFZ_CRg+1Q(P zDRyirnw7AsW7ypM@9!M7EA6rM*|p`SWwB~W4XK@#+|5QI#qI}<r{<OB33zW7Q0|c1 za%i7#JIin|A9F9~eA8)pKb*m_YxO;2UCX``P%4<!nR-cM5$`_@?y}Ep9{Bm*@_i}) z*@gjf7^~^Ypf?BJhx2SaHI#}AipnF08p=v`?P6=9Eq~+Kee8Af)gXnRr6$qv&%(JY z8M|3B_U6R?5UAw->-37GKfY|&Y6Zr74PJTZ6u1U`{nQ(Cdo6UUSM0}LKI@6;)sRRP zTWKdp#XaZZS;m|4mF<9n7EE(92xdNWLmufV5BWjsmaOq(*f^_&uHuC+Zhi$c#-6tf zsNM{S{yAN7%KC=FqZa?Wh@8!oLe!3SUbIHsUmw0fLb*|>W&5+~lNq(USl`;+m^;?T z4}W3Iqgq(>2XEv9Dp){kZ8;JTA1&aXXA2x!(<jXR)z7w_jYkDk#$#C>`5{wHEBfle zKBAxlMe)BmaXurLd5?`JaKqKpvH8a;prA5*{$pGEa|g!FP1O1TFglR}`DE~gliZ*d zrNPVVG|lSD`zP=;Kgjqvi~?#@o-Mpt$7Nadj$`t>Fk#y~M&V|0W%k?jSpI8ogk3eI zgMup6H*3u#I}A`8LD1bt*Jc-K?gE>%PcP>(EAQM(ejuP8lt*H1ObNdFjuW2OU|&xH z;7&n0HHJ~>km)fF#uge?xJ+$fX?|+0OXPzT)u9OMXz?g+68`$|5;0r~fI}ik;YCJL z@Xv)<T~=|pnV%|kMqdZEESn;Onvz=$O+I`(72xSoF}LuDYHOguRY~)0H?d8d<K}Jy z!vFsuv&C2&SqS<tF)%!M_QBgO>BYKd2?p@bFR%cXei6)2OfjQZO5wwsMYV?8rA2Ee zKoC1VWJB2E!8}w6mDE-rwJe-UZEN0SC@=sC0&sN^<rhT>k>LvqZuHNr((WkB-2sZ; z>Lb5{TKyzvc!|ePm8ox#^Sj&cQdeB;CJE&}5G&!d?C<5tQnS^5ceaOR#+IIhFZiK; z*MM$!Pz}?PUc-`B6FbAGl<>N;@Ny0OujoUIt$N=t&C5OKG{r8^KdRAme6>tmf_cZL z!%G!~=@PO(M2y|w>L2MrlZn3k?|x1AEN1<h`09n%IxKrAshRlIJ@N%j6uqzs$<lmC z4i=LBbU&z<pU>c~Ebl^|063Bc<ufq90_fkLm6ZvWhk^CqMjsstnQxY43X>*<IMDQB z&!oW1wqC_tX!=zjU|W{27=He;txzd5|6T}edv17Hz(2FbiY|UU1d`C>-L_Smb6)ly zkIOV>n|?jL)9Q1<s>TF4&1OMiNi+7!cE~yYGvjQyIj`!161B3QRkp?hAGf^w{COV_ z(u==_gz_twPn%8q+-sQ%FXb<L#W$kHx%s;F>FBe?AY;;q&4Ki#kiD&I#!8S$?<zf_ zA9aOKpFa6|(He7YwCSNFyqe8Qsv(x*hmly0acE)R7N!)QUsT=L&+_Gmd>m~Tk`~om z^yhCdT|LqC>e-Y!_NjTZg3Dxtl~h<6V5vc>c}b8$XB8RkZ8ehiJM2DzG)EcUdT@IL zSNJ{u41#jmcJ{-TPv9$R;nat{_knJQ!h=6-ll)*o@Ma_uheJZFqw9=xjV+v?%GJdt zB4t`kG9&f6vF`&pqC}zOadh@m{T!MRmKuW}I`c;&B95U0#;G3_?3?-hTLr{TnB!h+ zpYwY8KmZ0)ViufZ_Q8#FDREzqI(!_=IyII^Xd}`q<+1nd`Js1M#i2(XUy@EO<;LBc zeFC-J@=XgGM1e70Me~_5fh1y#u(Ux4IdNptbMN7fG=1u44b8mA%wqdFkFbha-{UU% z<MA;oHd`7O48(MuX4yA0J3)V22mDG;fy`LLUJLgW=WAWFKoe%P;bIyYRmIjM$shtn z+a|X=QvfO3tD=p{7g!0u=r!>|eOUNMyPuE>q-}qRro4t*H2K~?zyhMO1Fpsw?(JE( zh<_XnYtlu^YKcte^BS)w8lhfr@mW4W&jmcC#TJ1R?x9}rALZsB)HiNo;C(#cbJ}@~ z!CGI#oA5p;Gtu2;F7-Y^Fc>E>AOiAb2k6C*`kUh{ⅆL+71X9fSN6Xascq1j6}N> zsN+)HV30Hb@QJv|uCq<zwq*f@h|_l9gC%?4;ulTf&?7V{A}#_sSo5fT9Z7CAnaqEZ z@q^d|j>NytS{=6Zh0#_#{33z3Md7xw#O7sMWiC`sVvx|}jJS9#szmR+aPFC6kA~d) z#U6E9p{a7Ig}4Zko>zNLc$X2~2L|;%)$&sF6>mk60tNpp+w5uWpSFf4q30>rbCrVm za%jP@De}t(yN}jBW4+DVeJIRlD-e)fyyCPqp{YQxWZ741qEaT4&}4x?APp)-K%VRX zU5RSs4Dq+NHa0&=0FDLl@xfj)9Z3QJNJ3+Atzk$O7V#)E7y;qVM0AtQ;8+Phz69;l zLZAdrAgS#pt|JV|$|6pP!G~Dng%RV1n1LOY8Dv2zC<VZMRb5@wvc7hafjq3mL<=Ba zjFb?E|IhYtQ1G!tR1y$LYE=VJ6S}eBr~kD|OyEEgp;^hnK>;6U*+}QXf-&o0EYa|a zE~-Ue8{jGdYk~gPg2nNX??B_?(uqvN6H7#6-H;?bLm<*ol_^1$KmZ1q5`4le&?E>` zdj}lZL`CbOexbF2CqS?kaXEm5crvpv0glW!Lx{uwNFrc~Q6&8TJS42;<pn?<BAyA1 zgCq0Mh_OpUBUe#FDdb?51hWR;oxUDQL+R?FoR`&aVXmJZdv|9V)aWr9TQx&$`FAV- zTwW@u(j0jop+jhC**?h)`pGD?SB=h-j$MTRpEriFyp&D_gY|3w<}!`^;bD5P{jDaH R>pC+zhSN7fzteSi{2#wRr(ysA literal 0 HcmV?d00001 diff --git a/mkdocs.yml b/mkdocs.yml index 2ad1a7d718..328a601962 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,6 +4,8 @@ site_description: commit rules, semantic version, conventional commits theme: name: material + logo: images/cz_logo.png + favicon: images/cz_logo.png palette: # Palette toggle for automatic mode - media: "(prefers-color-scheme)" From 370ac9d3e1bf03692fce3f8900f9404aab4b3842 Mon Sep 17 00:00:00 2001 From: Jakob Zimmermann <105009705+zimmermannJakob@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:34:46 +0100 Subject: [PATCH 179/221] fix(bump): fix the issue that changelog_merge_prerelease not working on cz bump --- commitizen/changelog.py | 20 +++++- commitizen/changelog_formats/__init__.py | 8 ++- commitizen/changelog_formats/base.py | 37 +++++++++-- commitizen/commands/bump.py | 2 + commitizen/commands/changelog.py | 19 ++++++ tests/commands/test_bump_command.py | 63 +++++++++++++++++++ ...log_config_flag_merge_prerelease_alpha_.md | 11 ++++ ...elog_config_flag_merge_prerelease_beta_.md | 11 ++++ ...erelease_only_prerelease_present_alpha_.md | 10 +++ ...rerelease_only_prerelease_present_beta_.md | 10 +++ ..._prerelease_only_prerelease_present_rc_.md | 10 +++ ...ngelog_config_flag_merge_prerelease_rc_.md | 11 ++++ tests/test_changelog_format_asciidoc.py | 6 +- 13 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_alpha_.md create mode 100644 tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_beta_.md create mode 100644 tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_alpha_.md create mode 100644 tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_beta_.md create mode 100644 tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_rc_.md create mode 100644 tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_rc_.md diff --git a/commitizen/changelog.py b/commitizen/changelog.py index dfc4157725..8d01bebc17 100644 --- a/commitizen/changelog.py +++ b/commitizen/changelog.py @@ -72,6 +72,19 @@ def __post_init__(self) -> None: self.latest_version_tag = self.latest_version +@dataclass +class IncrementalMergeInfo: + """ + Information regarding the last non-pre-release, parsed from the changelog. + + Required to merge pre-releases on bump. + Separate from Metadata to not mess with the interface. + """ + + name: str | None = None + index: int | None = None + + def get_commit_tag(commit: GitCommit, tags: list[GitTag]) -> GitTag | None: return next((tag for tag in tags if tag.rev == commit.rev), None) @@ -86,6 +99,7 @@ def generate_tree_from_commits( changelog_message_builder_hook: MessageBuilderHook | None = None, changelog_release_hook: ChangelogReleaseHook | None = None, rules: TagRules | None = None, + during_version_bump: bool = False, ) -> Generator[dict[str, Any], None, None]: pat = re.compile(changelog_pattern) map_pat = re.compile(commit_parser, re.MULTILINE) @@ -93,8 +107,10 @@ def generate_tree_from_commits( rules = rules or TagRules() # Check if the latest commit is not tagged - - current_tag = get_commit_tag(commits[0], tags) if commits else None + if during_version_bump and rules.merge_prereleases: + current_tag = None + else: + current_tag = get_commit_tag(commits[0], tags) if commits else None current_tag_name = unreleased_version or "Unreleased" current_tag_date = ( date.today().isoformat() if unreleased_version is not None else "" diff --git a/commitizen/changelog_formats/__init__.py b/commitizen/changelog_formats/__init__.py index 018aa3b329..c92a43087c 100644 --- a/commitizen/changelog_formats/__init__.py +++ b/commitizen/changelog_formats/__init__.py @@ -8,7 +8,7 @@ if TYPE_CHECKING: from collections.abc import Callable - from commitizen.changelog import Metadata + from commitizen.changelog import IncrementalMergeInfo, Metadata from commitizen.config.base_config import BaseConfig CHANGELOG_FORMAT_ENTRYPOINT = "commitizen.changelog_format" @@ -47,6 +47,12 @@ def get_metadata(self, filepath: str) -> Metadata: """ raise NotImplementedError + def get_latest_full_release(self, filepath: str) -> IncrementalMergeInfo: + """ + Extract metadata for the last non-pre-release. + """ + raise NotImplementedError + KNOWN_CHANGELOG_FORMATS: dict[str, type[ChangelogFormat]] = { ep.name: ep.load() diff --git a/commitizen/changelog_formats/base.py b/commitizen/changelog_formats/base.py index eef6a23689..da6f63bd1f 100644 --- a/commitizen/changelog_formats/base.py +++ b/commitizen/changelog_formats/base.py @@ -4,7 +4,9 @@ from abc import ABCMeta from typing import IO, TYPE_CHECKING, Any, ClassVar -from commitizen.changelog import Metadata +from commitizen.changelog import IncrementalMergeInfo, Metadata +from commitizen.config.base_config import BaseConfig +from commitizen.git import GitTag from commitizen.tags import TagRules, VersionTag from commitizen.version_schemes import get_version_scheme @@ -60,10 +62,10 @@ def get_metadata_from_file(self, file: IO[Any]) -> Metadata: meta.unreleased_end = index # Try to find the latest release done - parsed = self.parse_version_from_title(line) - if parsed: - meta.latest_version = parsed.version - meta.latest_version_tag = parsed.tag + parsed_version = self.parse_version_from_title(line) + if parsed_version: + meta.latest_version = parsed_version.version + meta.latest_version_tag = parsed_version.tag meta.latest_version_position = index break # there's no need for more info if meta.unreleased_start is not None and meta.unreleased_end is None: @@ -71,6 +73,31 @@ def get_metadata_from_file(self, file: IO[Any]) -> Metadata: return meta + def get_latest_full_release(self, filepath: str) -> IncrementalMergeInfo: + if not os.path.isfile(filepath): + return IncrementalMergeInfo() + + with open( + filepath, encoding=self.config.settings["encoding"] + ) as changelog_file: + return self.get_latest_full_release_from_file(changelog_file) + + def get_latest_full_release_from_file(self, file: IO[Any]) -> IncrementalMergeInfo: + latest_version_index: int | None = None + for index, line in enumerate(file): + latest_version_index = index + line = line.strip().lower() + + parsed_version = self.parse_version_from_title(line) + if ( + parsed_version + and not self.tag_rules.extract_version( + GitTag(parsed_version.tag, "", "") + ).is_prerelease + ): + return IncrementalMergeInfo(name=parsed_version.tag, index=index) + return IncrementalMergeInfo(index=latest_version_index) + def parse_version_from_title(self, line: str) -> VersionTag | None: """ Extract the version from a title line if any diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index 0ed5ffd5b8..f6637b5c74 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -314,6 +314,8 @@ def __call__(self) -> None: "extras": self.extras, "incremental": True, "dry_run": dry_run, + # governs logic for merge_prerelease + "during_version_bump": self.arguments["prerelease"] is None, } if self.changelog_to_stdout: changelog_cmd = Changelog( diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index 215e03206a..33dca6b6c1 100644 --- a/commitizen/commands/changelog.py +++ b/commitizen/commands/changelog.py @@ -44,6 +44,7 @@ class ChangelogArgs(TypedDict, total=False): template: str extras: dict[str, Any] export_template: str + during_version_bump: bool | None class Changelog: @@ -124,6 +125,8 @@ def __init__(self, config: BaseConfig, arguments: ChangelogArgs) -> None: self.extras = arguments.get("extras") or {} self.export_template_to = arguments.get("export_template") + self.during_version_bump: bool = arguments.get("during_version_bump") or False + def _find_incremental_rev(self, latest_version: str, tags: Iterable[GitTag]) -> str: """Try to find the 'start_rev'. @@ -222,6 +225,21 @@ def __call__(self) -> None: self.tag_rules, ) + if self.during_version_bump and self.tag_rules.merge_prereleases: + latest_full_release_info = self.changelog_format.get_latest_full_release( + self.file_name + ) + if latest_full_release_info.index: + changelog_meta.unreleased_start = 0 + changelog_meta.latest_version_position = latest_full_release_info.index + changelog_meta.unreleased_end = latest_full_release_info.index - 1 + + start_rev = latest_full_release_info.name or "" + if not start_rev and latest_full_release_info.index: + # Only pre-releases in changelog + changelog_meta.latest_version_position = None + changelog_meta.unreleased_end = latest_full_release_info.index + 1 + commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order") if not commits and ( self.current_version is None or not self.current_version.is_prerelease @@ -238,6 +256,7 @@ def __call__(self) -> None: changelog_message_builder_hook=self.cz.changelog_message_builder_hook, changelog_release_hook=self.cz.changelog_release_hook, rules=self.tag_rules, + during_version_bump=self.during_version_bump, ) if self.change_type_order: tree = changelog.generate_ordered_changelog_tree( diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index c781e25263..d79a76b5ae 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -31,6 +31,7 @@ if TYPE_CHECKING: import py from pytest_mock import MockFixture + from pytest_regressions.file_regression import FileRegressionFixture from commitizen.changelog_formats import ChangelogFormat from commitizen.cz.base import BaseCommitizen @@ -1494,3 +1495,65 @@ def test_is_initial_tag(mocker: MockFixture, tmp_commitizen_project, util: UtilF # Test case 4: No current tag, user denies mocker.patch("questionary.confirm", return_value=mocker.Mock(ask=lambda: False)) assert bump_cmd._is_initial_tag(None, is_yes=False) is False + + +@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"]) +@pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2025-01-01") +def test_changelog_config_flag_merge_prerelease( + mocker: MockFixture, + util: UtilFixture, + changelog_path: str, + config_path: str, + file_regression: FileRegressionFixture, + test_input: str, +): + with open(config_path, "a") as f: + f.write("changelog_merge_prerelease = true\n") + f.write("update_changelog_on_bump = true\n") + f.write("annotated_tag = true\n") + + util.create_file_and_commit("irrelevant commit") + mocker.patch("commitizen.git.GitTag.date", "1970-01-01") + git.tag("0.1.0") + + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.run_cli("bump", "--prerelease", test_input, "--yes") + + util.run_cli("bump", "--changelog") + + with open(changelog_path) as f: + out = f.read() + + file_regression.check(out, extension=".md") + + +@pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"]) +@pytest.mark.usefixtures("tmp_commitizen_project") +@pytest.mark.freeze_time("2025-01-01") +def test_changelog_config_flag_merge_prerelease_only_prerelease_present( + util: UtilFixture, + changelog_path: str, + config_path: str, + file_regression: FileRegressionFixture, + test_input: str, +): + with open(config_path, "a") as f: + f.write("changelog_merge_prerelease = true\n") + f.write("update_changelog_on_bump = true\n") + f.write("annotated_tag = true\n") + + util.create_file_and_commit("feat: more relevant commit") + util.run_cli("bump", "--prerelease", test_input, "--yes") + + util.create_file_and_commit("feat: add new output") + util.create_file_and_commit("fix: output glitch") + util.run_cli("bump", "--prerelease", test_input, "--yes") + + util.run_cli("bump", "--changelog") + + with open(changelog_path) as f: + out = f.read() + + file_regression.check(out, extension=".md") diff --git a/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_alpha_.md b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_alpha_.md new file mode 100644 index 0000000000..6061938125 --- /dev/null +++ b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_alpha_.md @@ -0,0 +1,11 @@ +## 0.2.0 (2025-01-01) + +### Feat + +- add new output + +### Fix + +- output glitch + +## 0.1.0 (1970-01-01) diff --git a/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_beta_.md b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_beta_.md new file mode 100644 index 0000000000..6061938125 --- /dev/null +++ b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_beta_.md @@ -0,0 +1,11 @@ +## 0.2.0 (2025-01-01) + +### Feat + +- add new output + +### Fix + +- output glitch + +## 0.1.0 (1970-01-01) diff --git a/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_alpha_.md b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_alpha_.md new file mode 100644 index 0000000000..1f04057964 --- /dev/null +++ b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_alpha_.md @@ -0,0 +1,10 @@ +## 0.2.0 (2025-01-01) + +### Feat + +- add new output +- more relevant commit + +### Fix + +- output glitch diff --git a/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_beta_.md b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_beta_.md new file mode 100644 index 0000000000..1f04057964 --- /dev/null +++ b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_beta_.md @@ -0,0 +1,10 @@ +## 0.2.0 (2025-01-01) + +### Feat + +- add new output +- more relevant commit + +### Fix + +- output glitch diff --git a/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_rc_.md b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_rc_.md new file mode 100644 index 0000000000..1f04057964 --- /dev/null +++ b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_only_prerelease_present_rc_.md @@ -0,0 +1,10 @@ +## 0.2.0 (2025-01-01) + +### Feat + +- add new output +- more relevant commit + +### Fix + +- output glitch diff --git a/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_rc_.md b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_rc_.md new file mode 100644 index 0000000000..6061938125 --- /dev/null +++ b/tests/commands/test_bump_command/test_changelog_config_flag_merge_prerelease_rc_.md @@ -0,0 +1,11 @@ +## 0.2.0 (2025-01-01) + +### Feat + +- add new output + +### Fix + +- output glitch + +## 0.1.0 (1970-01-01) diff --git a/tests/test_changelog_format_asciidoc.py b/tests/test_changelog_format_asciidoc.py index 199c4b9729..c64979ee16 100644 --- a/tests/test_changelog_format_asciidoc.py +++ b/tests/test_changelog_format_asciidoc.py @@ -4,7 +4,7 @@ import pytest -from commitizen.changelog import Metadata +from commitizen.changelog import IncrementalMergeInfo, Metadata from commitizen.changelog_formats.asciidoc import AsciiDoc if TYPE_CHECKING: @@ -173,6 +173,10 @@ def test_get_metadata( assert format.get_metadata(str(changelog)) == expected +def test_get_latest_full_release_no_file(format: AsciiDoc): + assert format.get_latest_full_release("/nonexistent") == IncrementalMergeInfo() + + @pytest.mark.parametrize( "format_with_tags, tag_string, expected, ", ( From aa82b98206c0b97edf95749b561a2734e2e4761e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 09:35:14 +0000 Subject: [PATCH 180/221] =?UTF-8?q?bump:=20version=204.11.2=20=E2=86=92=20?= =?UTF-8?q?4.11.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 522278ad84..53b04ef72d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.2 # automatically updated by Commitizen + rev: v4.11.3 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 298bddfdca..1553b9957c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.11.3 (2026-01-13) + +### Fix + +- **bump**: fix the issue that changelog_merge_prerelease not working on cz bump + ## v4.11.2 (2026-01-12) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 77df5910b1..f2c314c153 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.2" +__version__ = "4.11.3" diff --git a/pyproject.toml b/pyproject.toml index 66299ab2ac..7262a5dd11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.2" +version = "4.11.3" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index ddd0ae8e52..924995d6d7 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.2" +version = "4.11.3" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 21c8043db0942307f52a04f59b50885d11b55735 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Wed, 14 Jan 2026 12:33:41 +0800 Subject: [PATCH 181/221] docs(README): remove steps about manually setup a configuration file (#1793) --- docs/README.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/README.md b/docs/README.md index d61ec18085..ad0911e3a3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -125,19 +125,7 @@ pdm add -d commitizen #### Initialize Commitizen -To get started, you'll need to set up your configuration. You have two options: - -1. Use the interactive setup: -```sh -cz init -``` - -2. Manually create a configuration file (`.cz.toml` or `cz.toml`): -```toml -[tool.commitizen] -version = "0.1.0" -update_changelog_on_bump = true -``` +To get started, run the `cz init` command. This will guide you through the process of creating a configuration file with your preferred settings. #### Create Commits From 52d84c1d8eb6e4a8604034e962191fcc4fb06eab Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Wed, 14 Jan 2026 13:59:29 +0800 Subject: [PATCH 182/221] test(cli): shorten no_raise tests (#1796) --- tests/test_cli.py | 51 ++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 9a362e81e0..6112d29bf7 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -119,34 +119,31 @@ def test_commitizen_excepthook_no_raises(capsys): assert excinfo.value.code == 0 -def test_parse_no_raise_single_integer(): - input_str = "1" - result = cli.parse_no_raise(input_str) - assert result == [1] - - -def test_parse_no_raise_integers(): - input_str = "1,2,3" - result = cli.parse_no_raise(input_str) - assert result == [1, 2, 3] - - -def test_parse_no_raise_error_code(): - input_str = "NO_COMMITIZEN_FOUND,NO_COMMITS_FOUND,NO_PATTERN_MAP" - result = cli.parse_no_raise(input_str) - assert result == [1, 3, 5] - - -def test_parse_no_raise_mix_integer_error_code(): - input_str = "NO_COMMITIZEN_FOUND,2,NO_COMMITS_FOUND,4" - result = cli.parse_no_raise(input_str) - assert result == [1, 2, 3, 4] - - -def test_parse_no_raise_mix_invalid_arg_is_skipped(): - input_str = "NO_COMMITIZEN_FOUND,2,nothing,4" +@pytest.mark.parametrize( + "input_str, expected_result", + [ + pytest.param("1", [1], id="single_code"), + pytest.param("1,2,3", [1, 2, 3], id="multiple_number_codes"), + pytest.param( + "NO_COMMITIZEN_FOUND,NO_COMMITS_FOUND,NO_PATTERN_MAP", + [1, 3, 5], + id="string_codes", + ), + pytest.param( + "NO_COMMITIZEN_FOUND,2,NO_COMMITS_FOUND,4", + [1, 2, 3, 4], + id="number_and_string_codes", + ), + pytest.param( + "NO_COMMITIZEN_FOUND,2,nothing,4", + [1, 2, 4], + id="number_and_string_codes_and_invalid_code", + ), + ], +) +def test_parse_no_raise(input_str, expected_result): result = cli.parse_no_raise(input_str) - assert result == [1, 2, 4] + assert result == expected_result def test_unknown_args_raises(util: UtilFixture): From c3065ab14e69b6522e91240aeddb4360b571e7c8 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Wed, 14 Jan 2026 16:36:00 +0800 Subject: [PATCH 183/221] build: fix mkdocs dev server hot reload failure issue --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7262a5dd11..09a6118a46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -300,7 +300,7 @@ all.sequence = ["format", "lint", "check-commit", "cover"] "doc:build".cmd = "mkdocs build" doc.help = "Live documentation server" -doc.cmd = "mkdocs serve" +doc.cmd = "mkdocs serve --livereload" # mkdocs hot reload failure workaround. Ref: https://github.com/mkdocs/mkdocs/issues/4032#issuecomment-3591002290 ci.help = "Run all tasks in CI" ci.sequence = ["check-commit", { cmd = "pre-commit run --all-files" }, "cover"] From 4af719baeb875838ec0217ce0493b2a05b31421f Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Thu, 15 Jan 2026 20:39:36 +0800 Subject: [PATCH 184/221] fix(cli): move sys.excepthook override to correct line, rename 'type' parameter, fix no argv test (#1791) --- commitizen/cli.py | 9 ++--- tests/commands/test_common_command.py | 10 +----- tests/conftest.py | 11 ++++++ tests/test_cli.py | 24 +++++++++++-- ...invalid_command_py_3_10___invalid_arg_.txt | 4 +++ ...nvalid_command_py_3_10_invalidCommand_.txt | 4 +++ ...invalid_command_py_3_11___invalid_arg_.txt | 4 +++ ...nvalid_command_py_3_11_invalidCommand_.txt | 4 +++ ...invalid_command_py_3_12___invalid_arg_.txt | 4 +++ ...nvalid_command_py_3_12_invalidCommand_.txt | 4 +++ ...invalid_command_py_3_13___invalid_arg_.txt | 3 ++ ...nvalid_command_py_3_13_invalidCommand_.txt | 3 ++ ...invalid_command_py_3_14___invalid_arg_.txt | 3 ++ ...nvalid_command_py_3_14_invalidCommand_.txt | 3 ++ tests/test_cli/test_no_argv_py_3_10_.txt | 34 +++++++++++++++++++ tests/test_cli/test_no_argv_py_3_11_.txt | 34 +++++++++++++++++++ tests/test_cli/test_no_argv_py_3_12_.txt | 34 +++++++++++++++++++ tests/test_cli/test_no_argv_py_3_13_.txt | 33 ++++++++++++++++++ tests/test_cli/test_no_argv_py_3_14_.txt | 33 ++++++++++++++++++ 19 files changed, 242 insertions(+), 16 deletions(-) create mode 100644 tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt create mode 100644 tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt create mode 100644 tests/test_cli/test_no_argv_py_3_10_.txt create mode 100644 tests/test_cli/test_no_argv_py_3_11_.txt create mode 100644 tests/test_cli/test_no_argv_py_3_12_.txt create mode 100644 tests/test_cli/test_no_argv_py_3_13_.txt create mode 100644 tests/test_cli/test_no_argv_py_3_14_.txt diff --git a/commitizen/cli.py b/commitizen/cli.py index e5538aeb49..364bc93f85 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -561,7 +561,7 @@ def __call__( def commitizen_excepthook( - type: type[BaseException], + exctype: type[BaseException], value: BaseException, traceback: TracebackType | None, debug: bool = False, @@ -569,13 +569,13 @@ def commitizen_excepthook( ) -> None: traceback = traceback if isinstance(traceback, TracebackType) else None if not isinstance(value, CommitizenException): - sys.__excepthook__(type, value, traceback) + sys.__excepthook__(exctype, value, traceback) return if value.message: value.output_method(value.message) if debug: - sys.__excepthook__(type, value, traceback) + sys.__excepthook__(exctype, value, traceback) exit_code = value.exit_code if no_raise is not None and exit_code in no_raise: sys.exit(ExitCode.EXPECTED_EXIT) @@ -629,6 +629,8 @@ class Args(argparse.Namespace): def main() -> None: + sys.excepthook = commitizen_excepthook + parser: argparse.ArgumentParser = cli(data) argcomplete.autocomplete(parser) # Show help if no arg provided @@ -673,7 +675,6 @@ def main() -> None: elif not conf.path: conf.update({"name": "cz_conventional_commits"}) - sys.excepthook = commitizen_excepthook if args.debug: logging.getLogger("commitizen").setLevel(logging.DEBUG) sys.excepthook = partial(sys.excepthook, debug=True) diff --git a/tests/commands/test_common_command.py b/tests/commands/test_common_command.py index 7a5a26b6b2..c70bc96e94 100644 --- a/tests/commands/test_common_command.py +++ b/tests/commands/test_common_command.py @@ -20,11 +20,10 @@ "version", ], ) -@pytest.mark.usefixtures("python_version") +@pytest.mark.usefixtures("python_version", "consistent_terminal_output") def test_command_shows_description_when_use_help_option( capsys, file_regression, - monkeypatch: pytest.MonkeyPatch, command: str, util: UtilFixture, ): @@ -32,13 +31,6 @@ def test_command_shows_description_when_use_help_option( Note: If the command description changes, please run `poe test:regen` to regenerate the test files. """ - # Force consistent terminal output - monkeypatch.setenv("COLUMNS", "80") - monkeypatch.setenv("TERM", "dumb") - monkeypatch.setenv("LC_ALL", "C") - monkeypatch.setenv("LANG", "C") - monkeypatch.setenv("NO_COLOR", "1") - monkeypatch.setenv("PAGER", "cat") with pytest.raises(SystemExit): util.run_cli(command, "--help") diff --git a/tests/conftest.py b/tests/conftest.py index d7fb6a23de..9b4c033e5b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -302,3 +302,14 @@ def any_changelog_format(config: BaseConfig) -> ChangelogFormat: def python_version(request: pytest.FixtureRequest) -> str: """The current python version in '{major}.{minor}' format""" return cast("str", request.param) + + +@pytest.fixture +def consistent_terminal_output(monkeypatch: pytest.MonkeyPatch): + """Force consistent terminal output.""" + monkeypatch.setenv("COLUMNS", "80") + monkeypatch.setenv("TERM", "dumb") + monkeypatch.setenv("LC_ALL", "C") + monkeypatch.setenv("LANG", "C") + monkeypatch.setenv("NO_COLOR", "1") + monkeypatch.setenv("PAGER", "cat") diff --git a/tests/test_cli.py b/tests/test_cli.py index 6112d29bf7..f504a8cb6c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -18,11 +18,29 @@ from tests.utils import UtilFixture -def test_sysexit_no_argv(util: UtilFixture, capsys): +@pytest.mark.usefixtures("python_version", "consistent_terminal_output") +def test_no_argv(util: UtilFixture, capsys, file_regression): with pytest.raises(ExpectedExit): util.run_cli() - out, _ = capsys.readouterr() - assert out.startswith("usage") + out, err = capsys.readouterr() + assert out == "" + file_regression.check(err, extension=".txt") + + +@pytest.mark.parametrize( + "arg", + [ + "--invalid-arg", + "invalidCommand", + ], +) +@pytest.mark.usefixtures("python_version", "consistent_terminal_output") +def test_invalid_command(util: UtilFixture, capsys, file_regression, arg): + with pytest.raises(NoCommandFoundError): + util.run_cli(arg) + out, err = capsys.readouterr() + assert out == "" + file_regression.check(err, extension=".txt") def test_cz_config_file_without_correct_file_path(util: UtilFixture, capsys): diff --git a/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt new file mode 100644 index 0000000000..148b4eacdb --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt @@ -0,0 +1,4 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... +cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt new file mode 100644 index 0000000000..e2d4416b81 --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt @@ -0,0 +1,4 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... +cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from 'init', 'commit', 'c', 'ls', 'example', 'info', 'schema', 'bump', 'changelog', 'ch', 'check', 'version') diff --git a/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt new file mode 100644 index 0000000000..148b4eacdb --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt @@ -0,0 +1,4 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... +cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt new file mode 100644 index 0000000000..e2d4416b81 --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt @@ -0,0 +1,4 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... +cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from 'init', 'commit', 'c', 'ls', 'example', 'info', 'schema', 'bump', 'changelog', 'ch', 'check', 'version') diff --git a/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt new file mode 100644 index 0000000000..148b4eacdb --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt @@ -0,0 +1,4 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... +cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt new file mode 100644 index 0000000000..c92220c4dc --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt @@ -0,0 +1,4 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... +cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from init, commit, c, ls, example, info, schema, bump, changelog, ch, check, version) diff --git a/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt new file mode 100644 index 0000000000..4f0ba2b148 --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt @@ -0,0 +1,3 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... +cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt new file mode 100644 index 0000000000..749066c556 --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt @@ -0,0 +1,3 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... +cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from init, commit, c, ls, example, info, schema, bump, changelog, ch, check, version) diff --git a/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt new file mode 100644 index 0000000000..4f0ba2b148 --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt @@ -0,0 +1,3 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... +cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt new file mode 100644 index 0000000000..749066c556 --- /dev/null +++ b/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt @@ -0,0 +1,3 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... +cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from init, commit, c, ls, example, info, schema, bump, changelog, ch, check, version) diff --git a/tests/test_cli/test_no_argv_py_3_10_.txt b/tests/test_cli/test_no_argv_py_3_10_.txt new file mode 100644 index 0000000000..691c75a86f --- /dev/null +++ b/tests/test_cli/test_no_argv_py_3_10_.txt @@ -0,0 +1,34 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... + +Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. +For more information, please visit https://commitizen-tools.github.io/commitizen + +options: + -h, --help show this help message and exit + --config CONFIG the path of configuration file + --debug use debug mode + -n NAME, --name NAME use the given commitizen (default: + cz_conventional_commits) + -nr NO_RAISE, --no-raise NO_RAISE + comma separated error codes that won't raise error, + e.g: cz -nr 1,2,3 bump. See codes at + https://commitizen- + tools.github.io/commitizen/exit_codes/ + +commands: + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + init init commitizen configuration + commit (c) create new commit + ls show available commitizens + example show commit example + info show information about the cz + schema show commit schema + bump bump semantic version based on the git log + changelog (ch) generate changelog (note that it will overwrite + existing file) + check validates that a commit message matches the commitizen + schema + version get the version of the installed commitizen or the + current project (default: installed commitizen) diff --git a/tests/test_cli/test_no_argv_py_3_11_.txt b/tests/test_cli/test_no_argv_py_3_11_.txt new file mode 100644 index 0000000000..691c75a86f --- /dev/null +++ b/tests/test_cli/test_no_argv_py_3_11_.txt @@ -0,0 +1,34 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... + +Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. +For more information, please visit https://commitizen-tools.github.io/commitizen + +options: + -h, --help show this help message and exit + --config CONFIG the path of configuration file + --debug use debug mode + -n NAME, --name NAME use the given commitizen (default: + cz_conventional_commits) + -nr NO_RAISE, --no-raise NO_RAISE + comma separated error codes that won't raise error, + e.g: cz -nr 1,2,3 bump. See codes at + https://commitizen- + tools.github.io/commitizen/exit_codes/ + +commands: + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + init init commitizen configuration + commit (c) create new commit + ls show available commitizens + example show commit example + info show information about the cz + schema show commit schema + bump bump semantic version based on the git log + changelog (ch) generate changelog (note that it will overwrite + existing file) + check validates that a commit message matches the commitizen + schema + version get the version of the installed commitizen or the + current project (default: installed commitizen) diff --git a/tests/test_cli/test_no_argv_py_3_12_.txt b/tests/test_cli/test_no_argv_py_3_12_.txt new file mode 100644 index 0000000000..691c75a86f --- /dev/null +++ b/tests/test_cli/test_no_argv_py_3_12_.txt @@ -0,0 +1,34 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + ... + +Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. +For more information, please visit https://commitizen-tools.github.io/commitizen + +options: + -h, --help show this help message and exit + --config CONFIG the path of configuration file + --debug use debug mode + -n NAME, --name NAME use the given commitizen (default: + cz_conventional_commits) + -nr NO_RAISE, --no-raise NO_RAISE + comma separated error codes that won't raise error, + e.g: cz -nr 1,2,3 bump. See codes at + https://commitizen- + tools.github.io/commitizen/exit_codes/ + +commands: + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + init init commitizen configuration + commit (c) create new commit + ls show available commitizens + example show commit example + info show information about the cz + schema show commit schema + bump bump semantic version based on the git log + changelog (ch) generate changelog (note that it will overwrite + existing file) + check validates that a commit message matches the commitizen + schema + version get the version of the installed commitizen or the + current project (default: installed commitizen) diff --git a/tests/test_cli/test_no_argv_py_3_13_.txt b/tests/test_cli/test_no_argv_py_3_13_.txt new file mode 100644 index 0000000000..f880f99772 --- /dev/null +++ b/tests/test_cli/test_no_argv_py_3_13_.txt @@ -0,0 +1,33 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... + +Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. +For more information, please visit https://commitizen-tools.github.io/commitizen + +options: + -h, --help show this help message and exit + --config CONFIG the path of configuration file + --debug use debug mode + -n, --name NAME use the given commitizen (default: + cz_conventional_commits) + -nr, --no-raise NO_RAISE + comma separated error codes that won't raise error, + e.g: cz -nr 1,2,3 bump. See codes at + https://commitizen- + tools.github.io/commitizen/exit_codes/ + +commands: + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + init init commitizen configuration + commit (c) create new commit + ls show available commitizens + example show commit example + info show information about the cz + schema show commit schema + bump bump semantic version based on the git log + changelog (ch) generate changelog (note that it will overwrite + existing file) + check validates that a commit message matches the commitizen + schema + version get the version of the installed commitizen or the + current project (default: installed commitizen) diff --git a/tests/test_cli/test_no_argv_py_3_14_.txt b/tests/test_cli/test_no_argv_py_3_14_.txt new file mode 100644 index 0000000000..f880f99772 --- /dev/null +++ b/tests/test_cli/test_no_argv_py_3_14_.txt @@ -0,0 +1,33 @@ +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... + +Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. +For more information, please visit https://commitizen-tools.github.io/commitizen + +options: + -h, --help show this help message and exit + --config CONFIG the path of configuration file + --debug use debug mode + -n, --name NAME use the given commitizen (default: + cz_conventional_commits) + -nr, --no-raise NO_RAISE + comma separated error codes that won't raise error, + e.g: cz -nr 1,2,3 bump. See codes at + https://commitizen- + tools.github.io/commitizen/exit_codes/ + +commands: + {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} + init init commitizen configuration + commit (c) create new commit + ls show available commitizens + example show commit example + info show information about the cz + schema show commit schema + bump bump semantic version based on the git log + changelog (ch) generate changelog (note that it will overwrite + existing file) + check validates that a commit message matches the commitizen + schema + version get the version of the installed commitizen or the + current project (default: installed commitizen) From 7e59a059c30612fed8ee8931005104766c46e767 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 12:40:16 +0000 Subject: [PATCH 185/221] =?UTF-8?q?bump:=20version=204.11.3=20=E2=86=92=20?= =?UTF-8?q?4.11.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53b04ef72d..f8a8c0b7c1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.3 # automatically updated by Commitizen + rev: v4.11.4 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 1553b9957c..c83bcd8d4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.11.4 (2026-01-15) + +### Fix + +- **cli**: move sys.excepthook override to correct line, rename 'type' parameter, fix no argv test (#1791) + ## v4.11.3 (2026-01-13) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index f2c314c153..0f60e612e1 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.3" +__version__ = "4.11.4" diff --git a/pyproject.toml b/pyproject.toml index 09a6118a46..18e8122b25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.3" +version = "4.11.4" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index 924995d6d7..81ec24d284 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.3" +version = "4.11.4" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 1da871e4adebd331e586b131132bf5dbb73a1162 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Thu, 15 Jan 2026 20:48:44 +0800 Subject: [PATCH 186/221] fix(config): ensure the actually used config file is correct, better test coverage (#1784) --- commitizen/config/__init__.py | 72 ++++++------- commitizen/defaults.py | 8 +- docs/config/configuration_file.md | 10 +- tests/test_conf.py | 163 +++++++++++++++++++----------- 4 files changed, 151 insertions(+), 102 deletions(-) diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index 2fb84a1238..cce3a266cd 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -1,7 +1,6 @@ from __future__ import annotations from pathlib import Path -from typing import TYPE_CHECKING from commitizen import defaults, git, out from commitizen.config.factory import create_config @@ -9,54 +8,57 @@ from .base_config import BaseConfig -if TYPE_CHECKING: - from collections.abc import Generator - - -def _resolve_config_paths(filepath: str | None = None) -> Generator[Path, None, None]: - if filepath is not None: - out_path = Path(filepath) - if not out_path.exists(): - raise ConfigFileNotFound() - - yield out_path - return +def _resolve_config_paths() -> list[Path]: git_project_root = git.find_git_project_root() cfg_search_paths = [Path(".")] - if git_project_root: + + if git_project_root and not cfg_search_paths[0].samefile(git_project_root): cfg_search_paths.append(git_project_root) - for path in cfg_search_paths: + # The following algorithm is ugly, but we need to ensure that the order of the candidates are preserved before v5. + # Also, the number of possible config files is limited, so the complexity is not a problem. + candidates: list[Path] = [] + for dir in cfg_search_paths: for filename in defaults.CONFIG_FILES: - out_path = path / Path(filename) - if out_path.exists(): - yield out_path + out_path = dir / Path(filename) + if out_path.exists() and all(not out_path.samefile(p) for p in candidates): + candidates.append(out_path) + return candidates + + +def _create_config_from_path(path: Path) -> BaseConfig: + with open(path, "rb") as f: + data: bytes = f.read() + + return create_config(data=data, path=path) def read_cfg(filepath: str | None = None) -> BaseConfig: - config_candidates = list(_resolve_config_paths(filepath)) + if filepath is not None: + conf_path = Path(filepath) + if not conf_path.exists(): + raise ConfigFileNotFound() + conf = _create_config_from_path(conf_path) + if conf.is_empty_config: + raise ConfigFileIsEmpty() + return conf + + config_candidate_paths = _resolve_config_paths() # Check for multiple config files and warn the user config_candidates_exclude_pyproject = [ - path for path in config_candidates if path.name != "pyproject.toml" + path for path in config_candidate_paths if path.name != "pyproject.toml" ] - if len(config_candidates_exclude_pyproject) > 1: - filenames = [path.name for path in config_candidates_exclude_pyproject] - out.warn( - f"Multiple config files detected: {', '.join(filenames)}. " - f"Using config file: '{filenames[0]}'." - ) - - for filename in config_candidates: - with open(filename, "rb") as f: - data: bytes = f.read() - - conf = create_config(data=data, path=filename) + + for config_candidate_path in config_candidate_paths: + conf = _create_config_from_path(config_candidate_path) if not conf.is_empty_config: + if len(config_candidates_exclude_pyproject) > 1: + out.warn( + f"Multiple config files detected: {', '.join(map(str, config_candidates_exclude_pyproject))}. " + f"Using config file: '{config_candidate_path}'." + ) return conf - if filepath is not None: - raise ConfigFileIsEmpty() - return BaseConfig() diff --git a/commitizen/defaults.py b/commitizen/defaults.py index b91fe4879c..6de41f63d1 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -67,15 +67,15 @@ class Settings(TypedDict, total=False): breaking_change_exclamation_in_title: bool -CONFIG_FILES: list[str] = [ - "pyproject.toml", +CONFIG_FILES: tuple[str, ...] = ( ".cz.toml", + "cz.toml", ".cz.json", "cz.json", ".cz.yaml", "cz.yaml", - "cz.toml", -] + "pyproject.toml", +) ENCODING = "utf-8" DEFAULT_SETTINGS: Settings = { diff --git a/docs/config/configuration_file.md b/docs/config/configuration_file.md index 8e4c1f2146..c38b8b4c8b 100644 --- a/docs/config/configuration_file.md +++ b/docs/config/configuration_file.md @@ -10,13 +10,15 @@ It is recommended to create a configuration file via our [`cz init`](../commands Configuration files are typically located in the root of your project directory. Commitizen searches for configuration files in the following order: -1. `pyproject.toml` (in the `[tool.commitizen]` section) -2. `.cz.toml` +<!-- DEPENDENCY: commitizen/defaults.py CONFIG_FILES --> + +1. `.cz.toml` +2. `cz.toml` 3. `.cz.json` 4. `cz.json` 5. `.cz.yaml` 6. `cz.yaml` -7. `cz.toml` +7. `pyproject.toml` (in the `[tool.commitizen]` section) The first valid configuration file found will be used. If no configuration file is found, Commitizen will use its default settings. @@ -29,7 +31,7 @@ The first valid configuration file found will be used. If no configuration file ``` !!! tip - For Python projects, it's recommended to add your Commitizen configuration to `pyproject.toml` to keep all project configuration in one place. + For Python projects, you can add your Commitizen configuration to `pyproject.toml` to keep all project configuration in one place. !!! warning "Multiple Configuration Files" If Commitizen detects more than one configuration file in your project directory (excluding `pyproject.toml`), it will display a warning message and identify which file is being used. To avoid confusion, ensure you have only one Commitizen configuration file in your project. diff --git a/tests/test_conf.py b/tests/test_conf.py index 1ef30d5152..b41ead0691 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -8,7 +8,7 @@ import pytest import yaml -from commitizen import config, defaults, git +from commitizen import cmd, config, defaults, git from commitizen.config.json_config import JsonConfig from commitizen.config.toml_config import TomlConfig from commitizen.config.yaml_config import YAMLConfig @@ -172,9 +172,7 @@ def test_find_git_project_root(tmpdir): assert git.find_git_project_root() is None -@pytest.mark.parametrize( - "config_files_manager", defaults.CONFIG_FILES.copy(), indirect=True -) +@pytest.mark.parametrize("config_files_manager", defaults.CONFIG_FILES, indirect=True) def test_set_key(config_files_manager): _conf = config.read_cfg() _conf.set_key("version", "2.0.0") @@ -184,7 +182,7 @@ def test_set_key(config_files_manager): class TestReadCfg: @pytest.mark.parametrize( - "config_files_manager", defaults.CONFIG_FILES.copy(), indirect=True + "config_files_manager", defaults.CONFIG_FILES, indirect=True ) def test_load_conf(_, config_files_manager): cfg = config.read_cfg() @@ -239,71 +237,85 @@ def test_load_empty_pyproject_toml_from_config_argument(_, tmpdir): with pytest.raises(ConfigFileIsEmpty): config.read_cfg(filepath="./not_in_root/pyproject.toml") - def test_warn_multiple_config_files(_, tmpdir, capsys): - """Test that a warning is issued when multiple config files exist.""" - with tmpdir.as_cwd(): - # Create multiple config files - tmpdir.join(".cz.toml").write(PYPROJECT) - tmpdir.join(".cz.json").write(JSON_STR) - # Read config - cfg = config.read_cfg() - - # Check that the warning was issued - captured = capsys.readouterr() - assert "Multiple config files detected" in captured.err - assert ".cz.toml" in captured.err - assert ".cz.json" in captured.err - assert "Using" in captured.err - - # Verify the correct config is loaded (first in priority order) - assert cfg.settings == _settings - - def test_warn_multiple_config_files_with_pyproject(_, tmpdir, capsys): - """Test warning excludes pyproject.toml from the warning message.""" +class TestWarnMultipleConfigFiles: + @pytest.mark.parametrize( + "files,expected_path,should_warn", + [ + # Same directory, different file types + ([(".cz.toml", PYPROJECT), (".cz.json", JSON_STR)], ".cz.toml", True), + ([(".cz.json", JSON_STR), (".cz.yaml", YAML_STR)], ".cz.json", True), + ([(".cz.toml", PYPROJECT), (".cz.yaml", YAML_STR)], ".cz.toml", True), + # With pyproject.toml (excluded from warning) + ( + [("pyproject.toml", PYPROJECT), (".cz.json", JSON_STR)], + ".cz.json", + False, + ), + ( + [("pyproject.toml", PYPROJECT), (".cz.toml", PYPROJECT)], + ".cz.toml", + False, + ), + ], + ) + def test_warn_multiple_config_files_same_dir( + _, tmpdir, capsys, files, expected_path, should_warn + ): + """Test warning when multiple config files exist in same directory.""" with tmpdir.as_cwd(): - # Create multiple config files including pyproject.toml - tmpdir.join("pyproject.toml").write(PYPROJECT) - tmpdir.join(".cz.json").write(JSON_STR) + for filename, content in files: + tmpdir.join(filename).write(content) - # Read config - should use pyproject.toml (first in priority) cfg = config.read_cfg() - - # No warning should be issued as only one non-pyproject config exists captured = capsys.readouterr() - assert "Multiple config files detected" not in captured.err - # Verify the correct config is loaded - assert cfg.settings == _settings + if should_warn: + assert "Multiple config files detected" in captured.err + assert "Using" in captured.err + for filename, _ in files: + if filename != "pyproject.toml": + assert filename in captured.err + else: + assert "Multiple config files detected" not in captured.err + + assert cfg.path == Path(expected_path) + # Verify config loaded correctly (name and version match expected) + assert cfg.settings["name"] == "cz_jira" + assert cfg.settings["version"] == "1.0.0" - def test_warn_multiple_config_files_uses_correct_one(_, tmpdir, capsys): - """Test that the correct config file is used when multiple exist.""" + @pytest.mark.parametrize( + "config_file,content", + [ + (".cz.json", JSON_STR), + (".cz.toml", PYPROJECT), + (".cz.yaml", YAML_STR), + ("cz.toml", PYPROJECT), + ("cz.json", JSON_STR), + ("cz.yaml", YAML_STR), + ], + ) + def test_warn_same_filename_different_directories_with_git( + _, tmpdir, capsys, config_file, content + ): + """Test warning when same config filename exists in the current directory and in the git root.""" with tmpdir.as_cwd(): - # Create .cz.json with different settings - json_different = """ - { - "commitizen": { - "name": "cz_conventional_commits", - "version": "2.0.0" - } - } - """ - tmpdir.join(".cz.json").write(json_different) - tmpdir.join(".cz.toml").write(PYPROJECT) + cmd.run("git init") - # Read config - should use pyproject.toml (first in defaults.CONFIG_FILES) - # But since pyproject.toml doesn't exist, .cz.toml is second in priority - cfg = config.read_cfg() + # Create config in git root + tmpdir.join(config_file).write(content) - # Check that warning mentions both files - captured = capsys.readouterr() - assert "Multiple config files detected" in captured.err - assert ".cz.toml" in captured.err - assert ".cz.json" in captured.err + # Create same filename in subdirectory + subdir = tmpdir.mkdir("subdir") + subdir.join(config_file).write(content) - # Verify .cz.toml was used (second in priority after pyproject.toml) - assert cfg.settings["name"] == "cz_jira" # from PYPROJECT - assert cfg.settings["version"] == "1.0.0" + with subdir.as_cwd(): + cfg = config.read_cfg() + captured = capsys.readouterr() + + assert "Multiple config files detected" in captured.err + assert f"Using config file: '{config_file}'" in captured.err + assert cfg.path == Path(config_file) def test_no_warn_with_explicit_config_path(_, tmpdir, capsys): """Test that no warning is issued when user explicitly specifies config.""" @@ -323,6 +335,39 @@ def test_no_warn_with_explicit_config_path(_, tmpdir, capsys): json_cfg_expected = JsonConfig(data=JSON_STR, path=Path(".cz.json")) assert cfg.settings == json_cfg_expected.settings + @pytest.mark.parametrize( + "config_file, content, with_git", + [ + (file, content, with_git) + for file, content in [ + (".cz.toml", PYPROJECT), + (".cz.json", JSON_STR), + (".cz.yaml", YAML_STR), + ("pyproject.toml", PYPROJECT), + ("cz.toml", PYPROJECT), + ("cz.json", JSON_STR), + ("cz.yaml", YAML_STR), + ] + for with_git in [True, False] + ], + ) + def test_no_warn_with_single_config_file( + _, tmpdir, capsys, config_file, content, with_git + ): + """Test that no warning is issued when user explicitly specifies config.""" + with tmpdir.as_cwd(): + if with_git: + cmd.run("git init") + + tmpdir.join(config_file).write(content) + + cfg = config.read_cfg() + captured = capsys.readouterr() + + # No warning should be issued + assert "Multiple config files detected" not in captured.err + assert cfg.path == Path(config_file) + @pytest.mark.parametrize( "config_file, exception_string", From 8283081219ade41136a9fe185efc58c172bea47d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 12:49:10 +0000 Subject: [PATCH 187/221] =?UTF-8?q?bump:=20version=204.11.4=20=E2=86=92=20?= =?UTF-8?q?4.11.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f8a8c0b7c1..6d94b6ab9f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.4 # automatically updated by Commitizen + rev: v4.11.5 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index c83bcd8d4f..f50b59c841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.11.5 (2026-01-15) + +### Fix + +- **config**: ensure the actually used config file is correct, better test coverage (#1784) + ## v4.11.4 (2026-01-15) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 0f60e612e1..95491c1789 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.4" +__version__ = "4.11.5" diff --git a/pyproject.toml b/pyproject.toml index 18e8122b25..fa18701e5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.4" +version = "4.11.5" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index 81ec24d284..a8a07733b4 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.4" +version = "4.11.5" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 7bf4c316198164e659a64463bbd3c43d0049ef51 Mon Sep 17 00:00:00 2001 From: Matt Belle <github@sl.mattbelle.com> Date: Thu, 15 Jan 2026 11:59:04 -0500 Subject: [PATCH 188/221] =?UTF-8?q?fix(git):=20commit=20bodies=20with=20ca?= =?UTF-8?q?rriage=20returns=20are=20correctly=20split=20by=20=E2=80=A6=20(?= =?UTF-8?q?#1780)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(git): commit bodies with carriage returns are correctly split by line This should enable us to correctly parse squashed commits made on an SCM server residing on a Windows OS. * test(git): commit parsing logic matches implementation * style(git): undo accidental linebreak change --------- Co-authored-by: Matt Belle <matthew.belle@ibm.com> --- commitizen/git.py | 4 ++-- tests/test_git.py | 40 +++++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/commitizen/git.py b/commitizen/git.py index e598ff065c..dc26038986 100644 --- a/commitizen/git.py +++ b/commitizen/git.py @@ -118,8 +118,8 @@ def from_rev_and_commit(cls, rev_and_commit: str) -> GitCommit: >>> commit.parents ['def456', 'ghi789'] """ - rev, parents, title, author, author_email, *body_list = rev_and_commit.split( - "\n" + rev, parents, title, author, author_email, *body_list = ( + rev_and_commit.splitlines() ) return cls( rev=rev.strip(), diff --git a/tests/test_git.py b/tests/test_git.py index 3fb25a8e65..9333997813 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -395,17 +395,21 @@ def test_get_filenames_in_commit_error(util: UtilFixture): assert str(excinfo.value) == "fatal: bad object HEAD" -def test_git_commit_from_rev_and_commit(): - # Test data with all fields populated - rev_and_commit = ( - "abc123\n" # rev - "def456 ghi789\n" # parents - "feat: add new feature\n" # title - "John Doe\n" # author - "john@example.com\n" # author_email - "This is a detailed description\n" # body - "of the new feature\n" - "with multiple lines" +@pytest.mark.parametrize( + "linebreak", ["\n", "\r\n"], ids=["line_feed", "carriage_return"] +) +def test_git_commit_from_rev_and_commit(linebreak): + rev_and_commit = linebreak.join( + [ + "abc123", # rev + "def456 ghi789", # parents + "feat: add new feature", # title + "John Doe", # author + "john@example.com", # author_email + "This is a detailed description", # body + "of the new feature", + "with multiple lines", + ] ) commit = git.GitCommit.from_rev_and_commit(rev_and_commit) @@ -421,12 +425,14 @@ def test_git_commit_from_rev_and_commit(): assert commit.parents == ["def456", "ghi789"] # Test with minimal data - minimal_commit = ( - "abc123\n" # rev - "\n" # no parents - "feat: minimal commit\n" # title - "John Doe\n" # author - "john@example.com\n" # author_email + minimal_commit = linebreak.join( + [ + "abc123", # rev + "", # no parents + "feat: minimal commit", # title + "John Doe", # author + "john@example.com", # author_email + ] ) commit = git.GitCommit.from_rev_and_commit(minimal_commit) From cdaa9412d4f599d2d269ce53c84c96d68c11764f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:59:34 +0000 Subject: [PATCH 189/221] =?UTF-8?q?bump:=20version=204.11.5=20=E2=86=92=20?= =?UTF-8?q?4.11.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d94b6ab9f..602683fa50 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.5 # automatically updated by Commitizen + rev: v4.11.6 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index f50b59c841..7ce1bd2a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.11.6 (2026-01-15) + +### Fix + +- **git**: commit bodies with carriage returns are correctly split by … (#1780) + ## v4.11.5 (2026-01-15) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 95491c1789..54bf8651d7 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.5" +__version__ = "4.11.6" diff --git a/pyproject.toml b/pyproject.toml index fa18701e5e..fdad366543 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.5" +version = "4.11.6" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index a8a07733b4..33c98d0344 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.5" +version = "4.11.6" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From a010a8df0fb7aecb1139a8683380667d72102810 Mon Sep 17 00:00:00 2001 From: BelpHegoR17 <bel02082024@gmail.com> Date: Thu, 15 Jan 2026 22:33:32 +0530 Subject: [PATCH 190/221] docs: update version provider install instructions (#1757) * docs(docs/config/version_provider.md): update version provider docs to use published package install * docs(config/version_provider.md): added editable install instructions for provider * docs(config/version_provider.md): refine provider installation wording * docs(config/version_provider.md): correct indent --- docs/config/version_provider.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/config/version_provider.md b/docs/config/version_provider.md index 859f84f781..48a49049df 100644 --- a/docs/config/version_provider.md +++ b/docs/config/version_provider.md @@ -264,9 +264,18 @@ setup( ### Step 3: Install and Use 1. Install your provider package: - ```bash - pip install -e . - ``` + + - Once your custom Commitizen provider is packaged and published (for example, to PyPI), install it like any standard Python package: + + ```bash + pip install my-commitizen-provider + ``` + + - If you want to use the provider directly from the current project source (during development), install it in editable mode ([See pip documentation](https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-e)): + + ```bash + pip install -e . + ``` 2. Configure Commitizen to use your provider: ```toml From b6d9c59a1401d655b1419d1b11ee3cadd582ee9a Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 17 Jan 2026 15:00:19 +0800 Subject: [PATCH 191/221] test(config): shorten config file factory tests (#1804) --- tests/test_conf.py | 52 ++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/tests/test_conf.py b/tests/test_conf.py index b41ead0691..6e4256f162 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -370,16 +370,15 @@ def test_no_warn_with_single_config_file( @pytest.mark.parametrize( - "config_file, exception_string", + "config_file", [ - (".cz.toml", r"\.cz\.toml"), - ("cz.toml", r"cz\.toml"), - ("pyproject.toml", r"pyproject\.toml"), + ".cz.toml", + "cz.toml", + "pyproject.toml", ], - ids=[".cz.toml", "cz.toml", "pyproject.toml"], ) class TestTomlConfig: - def test_init_empty_config_content(self, tmpdir, config_file, exception_string): + def test_init_empty_config_content(self, tmpdir, config_file): path = tmpdir.mkdir("commitizen").join(config_file) toml_config = TomlConfig(data="", path=path) toml_config.init_empty_config_content() @@ -387,9 +386,7 @@ def test_init_empty_config_content(self, tmpdir, config_file, exception_string): with open(path, encoding="utf-8") as toml_file: assert toml_file.read() == "[tool.commitizen]\n" - def test_init_empty_config_content_with_existing_content( - self, tmpdir, config_file, exception_string - ): + def test_init_empty_config_content_with_existing_content(self, tmpdir, config_file): existing_content = "[tool.black]\nline-length = 88\n" path = tmpdir.mkdir("commitizen").join(config_file) @@ -400,26 +397,24 @@ def test_init_empty_config_content_with_existing_content( with open(path, encoding="utf-8") as toml_file: assert toml_file.read() == existing_content + "\n[tool.commitizen]\n" - def test_init_with_invalid_config_content( - self, tmpdir, config_file, exception_string - ): + def test_init_with_invalid_config_content(self, tmpdir, config_file): existing_content = "invalid toml content" path = tmpdir.mkdir("commitizen").join(config_file) - with pytest.raises(InvalidConfigurationError, match=exception_string): + with pytest.raises(InvalidConfigurationError) as excinfo: TomlConfig(data=existing_content, path=path) + assert config_file in str(excinfo.value) @pytest.mark.parametrize( - "config_file, exception_string", + "config_file", [ - (".cz.json", r"\.cz\.json"), - ("cz.json", r"cz\.json"), + ".cz.json", + "cz.json", ], - ids=[".cz.json", "cz.json"], ) class TestJsonConfig: - def test_init_empty_config_content(self, tmpdir, config_file, exception_string): + def test_init_empty_config_content(self, tmpdir, config_file): path = tmpdir.mkdir("commitizen").join(config_file) json_config = JsonConfig(data="{}", path=path) json_config.init_empty_config_content() @@ -427,26 +422,24 @@ def test_init_empty_config_content(self, tmpdir, config_file, exception_string): with open(path, encoding="utf-8") as json_file: assert json.load(json_file) == {"commitizen": {}} - def test_init_with_invalid_config_content( - self, tmpdir, config_file, exception_string - ): + def test_init_with_invalid_config_content(self, tmpdir, config_file): existing_content = "invalid json content" path = tmpdir.mkdir("commitizen").join(config_file) - with pytest.raises(InvalidConfigurationError, match=exception_string): + with pytest.raises(InvalidConfigurationError) as excinfo: JsonConfig(data=existing_content, path=path) + assert config_file in str(excinfo.value) @pytest.mark.parametrize( - "config_file, exception_string", + "config_file", [ - (".cz.yaml", r"\.cz\.yaml"), - ("cz.yaml", r"cz\.yaml"), + ".cz.yaml", + "cz.yaml", ], - ids=[".cz.yaml", "cz.yaml"], ) class TestYamlConfig: - def test_init_empty_config_content(self, tmpdir, config_file, exception_string): + def test_init_empty_config_content(self, tmpdir, config_file): path = tmpdir.mkdir("commitizen").join(config_file) yaml_config = YAMLConfig(data="{}", path=path) yaml_config.init_empty_config_content() @@ -454,9 +447,10 @@ def test_init_empty_config_content(self, tmpdir, config_file, exception_string): with open(path) as yaml_file: assert yaml.safe_load(yaml_file) == {"commitizen": {}} - def test_init_with_invalid_content(self, tmpdir, config_file, exception_string): + def test_init_with_invalid_content(self, tmpdir, config_file): existing_content = "invalid: .cz.yaml: content: maybe?" path = tmpdir.mkdir("commitizen").join(config_file) - with pytest.raises(InvalidConfigurationError, match=exception_string): + with pytest.raises(InvalidConfigurationError) as excinfo: YAMLConfig(data=existing_content, path=path) + assert config_file in str(excinfo.value) From 7d0367deca288d2f6cf05b92f3158486648193c4 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 17 Jan 2026 15:04:50 +0800 Subject: [PATCH 192/221] test: remove unreachable code in pytest.raises block, fix some malformed tests and extract fixtures (#1800) --- tests/commands/conftest.py | 6 + tests/commands/test_check_command.py | 236 ++++++++------------------ tests/commands/test_commit_command.py | 173 +++++++------------ tests/test_cz_customize.py | 4 +- 4 files changed, 147 insertions(+), 272 deletions(-) diff --git a/tests/commands/conftest.py b/tests/commands/conftest.py index 4f9b5de3c6..88fc89b7cb 100644 --- a/tests/commands/conftest.py +++ b/tests/commands/conftest.py @@ -1,6 +1,7 @@ import os import pytest +from pytest_mock import MockerFixture from commitizen import defaults from commitizen.config import BaseConfig @@ -52,3 +53,8 @@ def changelog_path() -> str: @pytest.fixture() def config_path() -> str: return os.path.join(os.getcwd(), "pyproject.toml") + + +@pytest.fixture() +def success_mock(mocker: MockerFixture): + return mocker.patch("commitizen.out.success") diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index 382814892b..4b15da6eb1 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -19,7 +19,7 @@ import re from collections.abc import Mapping - from pytest_mock import MockFixture + from pytest_mock import MockFixture, MockType from commitizen.config.base_config import BaseConfig from commitizen.question import CzQuestion @@ -149,18 +149,12 @@ def test_check_conventional_commit_succeeds( ), ), ) -def test_check_no_conventional_commit(commit_msg, config, mocker: MockFixture, tmpdir): - with pytest.raises(InvalidCommitMessageError): - error_mock = mocker.patch("commitizen.out.error") - - tempfile = tmpdir.join("temp_commit_file") - tempfile.write(commit_msg) +def test_check_no_conventional_commit(commit_msg, config, tmpdir): + tempfile = tmpdir.join("temp_commit_file") + tempfile.write(commit_msg) - check_cmd = commands.Check( - config=config, arguments={"commit_msg_file": tempfile} - ) - check_cmd() - error_mock.assert_called_once() + with pytest.raises(InvalidCommitMessageError): + commands.Check(config=config, arguments={"commit_msg_file": tempfile})() @pytest.mark.parametrize( @@ -172,15 +166,10 @@ def test_check_no_conventional_commit(commit_msg, config, mocker: MockFixture, t "bump: 0.0.1 -> 1.0.0", ), ) -def test_check_conventional_commit(commit_msg, config, mocker: MockFixture, tmpdir): - success_mock = mocker.patch("commitizen.out.success") - +def test_check_conventional_commit(commit_msg, config, success_mock: MockType, tmpdir): tempfile = tmpdir.join("temp_commit_file") tempfile.write(commit_msg) - - check_cmd = commands.Check(config=config, arguments={"commit_msg_file": tempfile}) - - check_cmd() + commands.Check(config=config, arguments={"commit_msg_file": tempfile})() success_mock.assert_called_once() @@ -189,33 +178,26 @@ def test_check_command_when_commit_file_not_found(config): commands.Check(config=config, arguments={"commit_msg_file": "no_such_file"})() -def test_check_a_range_of_git_commits(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") +def test_check_a_range_of_git_commits( + config, success_mock: MockType, mocker: MockFixture +): mocker.patch( "commitizen.git.get_commits", return_value=_build_fake_git_commits(COMMIT_LOG) ) - check_cmd = commands.Check( - config=config, arguments={"rev_range": "HEAD~10..master"} - ) - - check_cmd() + commands.Check(config=config, arguments={"rev_range": "HEAD~10..master"})() success_mock.assert_called_once() def test_check_a_range_of_git_commits_and_failed(config, mocker: MockFixture): - error_mock = mocker.patch("commitizen.out.error") mocker.patch( "commitizen.git.get_commits", return_value=_build_fake_git_commits(["This commit does not follow rule"]), ) - check_cmd = commands.Check( - config=config, arguments={"rev_range": "HEAD~10..master"} - ) - with pytest.raises(InvalidCommitMessageError): - check_cmd() - error_mock.assert_called_once() + with pytest.raises(InvalidCommitMessageError) as excinfo: + commands.Check(config=config, arguments={"rev_range": "HEAD~10..master"})() + assert "This commit does not follow rule" in str(excinfo.value) def test_check_command_with_invalid_argument(config): @@ -234,123 +216,80 @@ def test_check_command_with_invalid_argument(config): def test_check_command_with_empty_range(config: BaseConfig, util: UtilFixture): # must initialize git with a commit util.create_file_and_commit("feat: initial") - - check_cmd = commands.Check(config=config, arguments={"rev_range": "master..master"}) with pytest.raises(NoCommitsFoundError) as excinfo: - check_cmd() - + commands.Check(config=config, arguments={"rev_range": "master..master"})() assert "No commit found with range: 'master..master'" in str(excinfo) def test_check_a_range_of_failed_git_commits(config, mocker: MockFixture): - ill_formated_commits_msgs = [ + ill_formatted_commits_msgs = [ "First commit does not follow rule", "Second commit does not follow rule", ("Third commit does not follow rule\nIll-formatted commit with body"), ] mocker.patch( "commitizen.git.get_commits", - return_value=_build_fake_git_commits(ill_formated_commits_msgs), - ) - check_cmd = commands.Check( - config=config, arguments={"rev_range": "HEAD~10..master"} + return_value=_build_fake_git_commits(ill_formatted_commits_msgs), ) with pytest.raises(InvalidCommitMessageError) as excinfo: - check_cmd() - assert all([msg in str(excinfo.value) for msg in ill_formated_commits_msgs]) + commands.Check(config=config, arguments={"rev_range": "HEAD~10..master"})() + assert all([msg in str(excinfo.value) for msg in ill_formatted_commits_msgs]) -def test_check_command_with_valid_message(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") - check_cmd = commands.Check( +def test_check_command_with_valid_message( + config, success_mock: MockType, mocker: MockFixture +): + commands.Check( config=config, arguments={"message": "fix(scope): some commit message"} - ) - - check_cmd() + )() success_mock.assert_called_once() -def test_check_command_with_invalid_message(config, mocker: MockFixture): - error_mock = mocker.patch("commitizen.out.error") - check_cmd = commands.Check(config=config, arguments={"message": "bad commit"}) - +@pytest.mark.parametrize("message", ["bad commit", ""]) +def test_check_command_with_invalid_message(config, message): with pytest.raises(InvalidCommitMessageError): - check_cmd() - error_mock.assert_called_once() - - -def test_check_command_with_empty_message(config, mocker: MockFixture): - error_mock = mocker.patch("commitizen.out.error") - check_cmd = commands.Check(config=config, arguments={"message": ""}) - - with pytest.raises(InvalidCommitMessageError): - check_cmd() - error_mock.assert_called_once() - + commands.Check(config=config, arguments={"message": message})() -def test_check_command_with_allow_abort_arg(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") - check_cmd = commands.Check( - config=config, arguments={"message": "", "allow_abort": True} - ) - check_cmd() +def test_check_command_with_allow_abort_arg(config, success_mock): + commands.Check(config=config, arguments={"message": "", "allow_abort": True})() success_mock.assert_called_once() -def test_check_command_with_allow_abort_config(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") +def test_check_command_with_allow_abort_config(config, success_mock): config.settings["allow_abort"] = True - check_cmd = commands.Check(config=config, arguments={"message": ""}) - - check_cmd() + commands.Check(config=config, arguments={"message": ""})() success_mock.assert_called_once() -def test_check_command_override_allow_abort_config(config, mocker: MockFixture): - error_mock = mocker.patch("commitizen.out.error") +def test_check_command_override_allow_abort_config(config): config.settings["allow_abort"] = True - check_cmd = commands.Check( - config=config, arguments={"message": "", "allow_abort": False} - ) - with pytest.raises(InvalidCommitMessageError): - check_cmd() - error_mock.assert_called_once() + commands.Check(config=config, arguments={"message": "", "allow_abort": False})() -def test_check_command_with_allowed_prefixes_arg(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") - check_cmd = commands.Check( +def test_check_command_with_allowed_prefixes_arg(config, success_mock): + commands.Check( config=config, arguments={"message": "custom! test", "allowed_prefixes": ["custom!"]}, - ) - - check_cmd() + )() success_mock.assert_called_once() -def test_check_command_with_allowed_prefixes_config(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") +def test_check_command_with_allowed_prefixes_config(config, success_mock): config.settings["allowed_prefixes"] = ["custom!"] - check_cmd = commands.Check(config=config, arguments={"message": "custom! test"}) - - check_cmd() + commands.Check(config=config, arguments={"message": "custom! test"})() success_mock.assert_called_once() -def test_check_command_override_allowed_prefixes_config(config, mocker: MockFixture): - error_mock = mocker.patch("commitizen.out.error") +def test_check_command_override_allowed_prefixes_config(config): config.settings["allow_abort"] = ["fixup!"] - check_cmd = commands.Check( - config=config, - arguments={"message": "fixup! test", "allowed_prefixes": ["custom!"]}, - ) - with pytest.raises(InvalidCommitMessageError): - check_cmd() - error_mock.assert_called_once() + commands.Check( + config=config, + arguments={"message": "fixup! test", "allowed_prefixes": ["custom!"]}, + )() def test_check_command_with_pipe_message( @@ -424,93 +363,64 @@ def test_check_conventional_commit_succeed_with_git_diff( assert "Commit validation: successful!" in out -def test_check_command_with_message_length_limit(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") +def test_check_command_with_message_length_limit(config, success_mock): message = "fix(scope): some commit message" - check_cmd = commands.Check( + commands.Check( config=config, arguments={"message": message, "message_length_limit": len(message) + 1}, - ) - - check_cmd() + )() success_mock.assert_called_once() -def test_check_command_with_message_length_limit_exceeded(config, mocker: MockFixture): - error_mock = mocker.patch("commitizen.out.error") +def test_check_command_with_message_length_limit_exceeded(config): message = "fix(scope): some commit message" - check_cmd = commands.Check( - config=config, - arguments={"message": message, "message_length_limit": len(message) - 1}, - ) - with pytest.raises(CommitMessageLengthExceededError): - check_cmd() - error_mock.assert_called_once() - + commands.Check( + config=config, + arguments={"message": message, "message_length_limit": len(message) - 1}, + )() -def test_check_command_with_amend_prefix_default(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") - check_cmd = commands.Check(config=config, arguments={"message": "amend! test"}) - check_cmd() +def test_check_command_with_amend_prefix_default(config, success_mock): + commands.Check(config=config, arguments={"message": "amend! test"})() success_mock.assert_called_once() -def test_check_command_with_config_message_length_limit(config, mocker: MockFixture): - success_mock = mocker.patch("commitizen.out.success") +def test_check_command_with_config_message_length_limit(config, success_mock): message = "fix(scope): some commit message" - config.settings["message_length_limit"] = len(message) + 1 - - check_cmd = commands.Check( + commands.Check( config=config, arguments={"message": message}, - ) - - check_cmd() + )() success_mock.assert_called_once() -def test_check_command_with_config_message_length_limit_exceeded( - config, mocker: MockFixture -): - error_mock = mocker.patch("commitizen.out.error") +def test_check_command_with_config_message_length_limit_exceeded(config): message = "fix(scope): some commit message" - config.settings["message_length_limit"] = len(message) - 1 - - check_cmd = commands.Check( - config=config, - arguments={"message": message}, - ) - with pytest.raises(CommitMessageLengthExceededError): - check_cmd() - error_mock.assert_called_once() + commands.Check( + config=config, + arguments={"message": message}, + )() def test_check_command_cli_overrides_config_message_length_limit( - config, mocker: MockFixture + config, success_mock: MockType, mocker: MockFixture ): - success_mock = mocker.patch("commitizen.out.success") message = "fix(scope): some commit message" - config.settings["message_length_limit"] = len(message) - 1 - - check_cmd = commands.Check( - config=config, - arguments={"message": message, "message_length_limit": len(message) + 1}, - ) - - check_cmd() - success_mock.assert_called_once() - - success_mock.reset_mock() - check_cmd = commands.Check( - config=config, - arguments={"message": message, "message_length_limit": None}, - ) + for message_length_limit in [len(message) + 1, None]: + success_mock.reset_mock() + commands.Check( + config=config, + arguments={ + "message": message, + "message_length_limit": message_length_limit, + }, + )() + success_mock.assert_called_once() class ValidationCz(BaseCommitizen): diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index c987f4b3f3..c17001292e 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -2,7 +2,7 @@ from unittest.mock import ANY import pytest -from pytest_mock import MockFixture +from pytest_mock import MockFixture, MockType from commitizen import cmd, commands from commitizen.cz.exceptions import CzException @@ -20,6 +20,13 @@ ) +@pytest.fixture +def commit_mock(mocker: MockFixture): + commit_mock = mocker.patch("commitizen.git.commit") + commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) + return commit_mock + + @pytest.fixture def staging_is_clean(mocker: MockFixture, tmp_git_project): is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean") @@ -33,8 +40,8 @@ def backup_file(tmp_git_project): backup_file.write("backup commit") -@pytest.mark.usefixtures("staging_is_clean") -def test_commit(config, mocker: MockFixture): +@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +def test_commit(config, success_mock: MockType, mocker: MockFixture): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -45,10 +52,6 @@ def test_commit(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - commands.Commit(config, {})() success_mock.assert_called_once() @@ -65,13 +68,14 @@ def test_commit_backup_on_failure(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("", "error", b"", b"", 9) + mocker.patch("commitizen.git.commit").return_value = cmd.Command( + "", "error", b"", b"", 9 + ) error_mock = mocker.patch("commitizen.out.error") + commit_cmd = commands.Commit(config, {}) + temp_file = commit_cmd.backup_file_path with pytest.raises(CommitError): - commit_cmd = commands.Commit(config, {}) - temp_file = commit_cmd.backup_file_path commit_cmd() prompt_mock.assert_called_once() @@ -79,11 +83,8 @@ def test_commit_backup_on_failure(config, mocker: MockFixture): assert os.path.isfile(temp_file) -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_retry_fails_no_backup(config, mocker: MockFixture): - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - +@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +def test_commit_retry_fails_no_backup(config): with pytest.raises(NoCommitBackupError) as excinfo: commands.Commit(config, {"retry": True})() @@ -91,13 +92,11 @@ def test_commit_retry_fails_no_backup(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean", "backup_file") -def test_commit_retry_works(config, mocker: MockFixture): +def test_commit_retry_works( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - commit_cmd = commands.Commit(config, {"retry": True}) temp_file = commit_cmd.backup_file_path commit_cmd() @@ -109,7 +108,9 @@ def test_commit_retry_works(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_retry_after_failure_no_backup(config, mocker: MockFixture): +def test_commit_retry_after_failure_no_backup( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -120,10 +121,6 @@ def test_commit_retry_after_failure_no_backup(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["retry_after_failure"] = True commands.Commit(config, {})() @@ -133,13 +130,11 @@ def test_commit_retry_after_failure_no_backup(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean", "backup_file") -def test_commit_retry_after_failure_works(config, mocker: MockFixture): +def test_commit_retry_after_failure_works( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["retry_after_failure"] = True commit_cmd = commands.Commit(config, {}) temp_file = commit_cmd.backup_file_path @@ -152,7 +147,9 @@ def test_commit_retry_after_failure_works(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean", "backup_file") -def test_commit_retry_after_failure_with_no_retry_works(config, mocker: MockFixture): +def test_commit_retry_after_failure_with_no_retry_works( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -163,10 +160,6 @@ def test_commit_retry_after_failure_with_no_retry_works(config, mocker: MockFixt "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["retry_after_failure"] = True commit_cmd = commands.Commit(config, {"no_retry": True}) temp_file = commit_cmd.backup_file_path @@ -191,13 +184,12 @@ def test_commit_command_with_dry_run_option(config, mocker: MockFixture): } with pytest.raises(DryRunExit): - commit_cmd = commands.Commit(config, {"dry_run": True}) - commit_cmd() + commands.Commit(config, {"dry_run": True})() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "commit_mock") def test_commit_command_with_write_message_to_file_option( - config, tmp_path, mocker: MockFixture + config, tmp_path, success_mock: MockType, mocker: MockFixture ): tmp_file = tmp_path / "message" @@ -211,10 +203,6 @@ def test_commit_command_with_write_message_to_file_option( "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - commands.Commit(config, {"write_message_to_file": tmp_file})() success_mock.assert_called_once() assert tmp_file.exists() @@ -236,12 +224,13 @@ def test_commit_command_with_invalid_write_message_to_file_option( } with pytest.raises(NotAllowed): - commit_cmd = commands.Commit(config, {"write_message_to_file": tmp_path}) - commit_cmd() + commands.Commit(config, {"write_message_to_file": tmp_path})() @pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_signoff_option(config, mocker: MockFixture): +def test_commit_command_with_signoff_option( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -252,10 +241,6 @@ def test_commit_command_with_signoff_option(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - commands.Commit(config, {"signoff": True})() commit_mock.assert_called_once_with(ANY, args="-s") @@ -263,7 +248,9 @@ def test_commit_command_with_signoff_option(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_always_signoff_enabled(config, mocker: MockFixture): +def test_commit_command_with_always_signoff_enabled( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -274,10 +261,6 @@ def test_commit_command_with_always_signoff_enabled(config, mocker: MockFixture) "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["always_signoff"] = True commands.Commit(config, {})() @@ -287,7 +270,7 @@ def test_commit_command_with_always_signoff_enabled(config, mocker: MockFixture) @pytest.mark.usefixtures("staging_is_clean") def test_commit_command_with_gpgsign_and_always_signoff_enabled( - config, mocker: MockFixture + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType ): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { @@ -299,10 +282,6 @@ def test_commit_command_with_gpgsign_and_always_signoff_enabled( "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["always_signoff"] = True commands.Commit(config, {"extra_cli_args": "-S"})() @@ -316,14 +295,15 @@ def test_commit_when_nothing_to_commit(config, mocker: MockFixture): is_staging_clean_mock.return_value = True with pytest.raises(NothingToCommitError) as excinfo: - commit_cmd = commands.Commit(config, {}) - commit_cmd() + commands.Commit(config, {})() assert "No files added to staging!" in str(excinfo.value) @pytest.mark.usefixtures("staging_is_clean") -def test_commit_with_allow_empty(config, mocker: MockFixture): +def test_commit_with_allow_empty( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -334,10 +314,6 @@ def test_commit_with_allow_empty(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - commands.Commit(config, {"extra_cli_args": "--allow-empty"})() commit_mock.assert_called_with( @@ -347,7 +323,9 @@ def test_commit_with_allow_empty(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_with_signoff_and_allow_empty(config, mocker: MockFixture): +def test_commit_with_signoff_and_allow_empty( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -358,10 +336,6 @@ def test_commit_with_signoff_and_allow_empty(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["always_signoff"] = True commands.Commit(config, {"extra_cli_args": "--allow-empty"})() @@ -379,8 +353,7 @@ def test_commit_when_customized_expected_raised(config, mocker: MockFixture, cap prompt_mock.side_effect = _err with pytest.raises(CustomError) as excinfo: - commit_cmd = commands.Commit(config, {}) - commit_cmd() + commands.Commit(config, {})() # Assert only the content in the formatted text assert "This is the root custom err" in str(excinfo.value) @@ -395,8 +368,7 @@ def test_commit_when_non_customized_expected_raised( prompt_mock.side_effect = _err with pytest.raises(ValueError): - commit_cmd = commands.Commit(config, {}) - commit_cmd() + commands.Commit(config, {})() @pytest.mark.usefixtures("staging_is_clean") @@ -405,8 +377,7 @@ def test_commit_when_no_user_answer(config, mocker: MockFixture, capsys): prompt_mock.return_value = None with pytest.raises(NoAnswersError): - commit_cmd = commands.Commit(config, {}) - commit_cmd() + commands.Commit(config, {})() def test_commit_in_non_git_project(tmpdir, config): @@ -415,8 +386,10 @@ def test_commit_in_non_git_project(tmpdir, config): commands.Commit(config, {}) -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_all_option(config, mocker: MockFixture): +@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +def test_commit_command_with_all_option( + config, success_mock: MockType, mocker: MockFixture +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -427,9 +400,6 @@ def test_commit_command_with_all_option(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") add_mock = mocker.patch("commitizen.git.add") commands.Commit(config, {"all": True})() add_mock.assert_called() @@ -437,7 +407,9 @@ def test_commit_command_with_all_option(config, mocker: MockFixture): @pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_extra_args(config, mocker: MockFixture): +def test_commit_command_with_extra_args( + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType +): prompt_mock = mocker.patch("questionary.prompt") prompt_mock.return_value = { "prefix": "feat", @@ -448,16 +420,15 @@ def test_commit_command_with_extra_args(config, mocker: MockFixture): "footer": "", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") commands.Commit(config, {"extra_cli_args": "-- -extra-args1 -extra-arg2"})() commit_mock.assert_called_once_with(ANY, args="-- -extra-args1 -extra-arg2") success_mock.assert_called_once() -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_message_length_limit(config, mocker: MockFixture): +@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +def test_commit_command_with_message_length_limit( + config, success_mock: MockType, mocker: MockFixture +): prompt_mock = mocker.patch("questionary.prompt") prefix = "feat" subject = "random subject" @@ -471,10 +442,6 @@ def test_commit_command_with_message_length_limit(config, mocker: MockFixture): "footer": "random footer", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - commands.Commit(config, {"message_length_limit": message_length})() success_mock.assert_called_once() @@ -504,9 +471,7 @@ def test_manual_edit(editor, config, mocker: MockFixture, tmp_path): commit_cmd.manual_edit(test_message) else: edited_message = commit_cmd.manual_edit(test_message) - subprocess_mock.assert_called_once_with(["vim", str(temp_file)]) - assert edited_message == test_message.strip() @@ -541,8 +506,10 @@ def test_commit_when_nothing_added_to_commit(config, mocker: MockFixture, out): error_mock.assert_called_once_with(out) -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_config_message_length_limit(config, mocker: MockFixture): +@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +def test_commit_command_with_config_message_length_limit( + config, success_mock: MockType, mocker: MockFixture +): prompt_mock = mocker.patch("questionary.prompt") prefix = "feat" subject = "random subject" @@ -556,10 +523,6 @@ def test_commit_command_with_config_message_length_limit(config, mocker: MockFix "footer": "random footer", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["message_length_limit"] = message_length commands.Commit(config, {})() success_mock.assert_called_once() @@ -571,7 +534,7 @@ def test_commit_command_with_config_message_length_limit(config, mocker: MockFix @pytest.mark.usefixtures("staging_is_clean") def test_commit_command_cli_overrides_config_message_length_limit( - config, mocker: MockFixture + config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType ): prompt_mock = mocker.patch("questionary.prompt") prefix = "feat" @@ -586,10 +549,6 @@ def test_commit_command_cli_overrides_config_message_length_limit( "footer": "random footer", } - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - success_mock = mocker.patch("commitizen.out.success") - config.settings["message_length_limit"] = message_length - 1 commands.Commit(config, {"message_length_limit": message_length})() diff --git a/tests/test_cz_customize.py b/tests/test_cz_customize.py index dd354d65ea..22a3e80f38 100644 --- a/tests/test_cz_customize.py +++ b/tests/test_cz_customize.py @@ -376,9 +376,9 @@ def config_with_unicode(request): def test_initialize_cz_customize_failed(): + config = BaseConfig() with pytest.raises(MissingCzCustomizeConfigError) as excinfo: - config = BaseConfig() - _ = CustomizeCommitsCz(config) + CustomizeCommitsCz(config) assert MissingCzCustomizeConfigError.message in str(excinfo.value) From 38483e935dc9b86f31f6b960a0d9502e492dc1fb Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 17 Jan 2026 15:06:17 +0800 Subject: [PATCH 193/221] test(version_schemes): replace match with strict string assertions (#1805) --- tests/test_version_schemes.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_version_schemes.py b/tests/test_version_schemes.py index d51c8eeb2f..7b1ec7579a 100644 --- a/tests/test_version_schemes.py +++ b/tests/test_version_schemes.py @@ -61,5 +61,8 @@ class NotVersionProtocol: ep.load.return_value = NotVersionProtocol mocker.patch.object(metadata, "entry_points", return_value=(ep,)) - with pytest.warns(match="VersionProtocol"): + with pytest.warns() as warnings: get_version_scheme(config.settings, "any") + assert "Version scheme any does not implement the VersionProtocol" in str( + warnings[0].message + ) From f6aef690e7471f648c0228ee55c2bedfc7acf372 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sun, 18 Jan 2026 23:05:02 +0800 Subject: [PATCH 194/221] test(check): shorten tests and dedup logic (#1807) --- tests/commands/test_check_command.py | 98 ++++++++++------------------ 1 file changed, 36 insertions(+), 62 deletions(-) diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index 4b15da6eb1..b5e3fd2b08 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -28,7 +28,7 @@ COMMIT_LOG = [ "refactor: A code change that neither fixes a bug nor adds a feature", - r"refactor(cz/connventional_commit): use \S to check scope", + r"refactor(cz/conventional_commit): use \S to check scope", "refactor(git): remove unnecessary dot between git range", "bump: version 1.16.3 → 1.16.4", ( @@ -79,46 +79,21 @@ def test_check_jira_fails(mocker: MockFixture, util: UtilFixture): assert "commit validation: failed!" in str(excinfo.value) -def test_check_jira_command_after_issue_one_space( - mocker: MockFixture, capsys, util: UtilFixture -): - mocker.patch( - "commitizen.commands.check.open", - mocker.mock_open(read_data="JR-23 #command some arguments etc"), - ) - util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") - out, _ = capsys.readouterr() - assert "Commit validation: successful!" in out - - -def test_check_jira_command_after_issue_two_spaces( - mocker: MockFixture, capsys, util: UtilFixture -): - mocker.patch( - "commitizen.commands.check.open", - mocker.mock_open(read_data="JR-2 #command some arguments etc"), - ) - util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") - out, _ = capsys.readouterr() - assert "Commit validation: successful!" in out - - -def test_check_jira_text_between_issue_and_command( - mocker: MockFixture, capsys, util: UtilFixture +@pytest.mark.parametrize( + "commit_msg", + [ + "JR-23 #command some arguments etc", + "JR-2 #command some arguments etc", + "JR-234 some text #command some arguments etc", + "JRA-23 some text #command1 args #command2 args", + ], +) +def test_check_jira_command_after_issue( + mocker: MockFixture, capsys, util: UtilFixture, commit_msg: str ): mocker.patch( "commitizen.commands.check.open", - mocker.mock_open(read_data="JR-234 some text #command some arguments etc"), - ) - util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") - out, _ = capsys.readouterr() - assert "Commit validation: successful!" in out - - -def test_check_jira_multiple_commands(mocker: MockFixture, capsys, util: UtilFixture): - mocker.patch( - "commitizen.commands.check.open", - mocker.mock_open(read_data="JRA-23 some text #command1 args #command2 args"), + mocker.mock_open(read_data=commit_msg), ) util.run_cli("-n", "cz_jira", "check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() @@ -237,9 +212,7 @@ def test_check_a_range_of_failed_git_commits(config, mocker: MockFixture): assert all([msg in str(excinfo.value) for msg in ill_formatted_commits_msgs]) -def test_check_command_with_valid_message( - config, success_mock: MockType, mocker: MockFixture -): +def test_check_command_with_valid_message(config, success_mock: MockType): commands.Check( config=config, arguments={"message": "fix(scope): some commit message"} )() @@ -335,28 +308,29 @@ def test_check_command_with_comment_in_message_file( def test_check_conventional_commit_succeed_with_git_diff( mocker, capsys, util: UtilFixture ): - commit_msg = ( - "feat: This is a test commit\n" - "# Please enter the commit message for your changes. Lines starting\n" - "# with '#' will be ignored, and an empty message aborts the commit.\n" - "#\n" - "# On branch ...\n" - "# Changes to be committed:\n" - "# modified: ...\n" - "#\n" - "# ------------------------ >8 ------------------------\n" - "# Do not modify or remove the line above.\n" - "# Everything below it will be ignored.\n" - "diff --git a/... b/...\n" - "index f1234c..1c5678 1234\n" - "--- a/...\n" - "+++ b/...\n" - "@@ -92,3 +92,4 @@ class Command(BaseCommand):\n" - '+ "this is a test"\n' - ) mocker.patch( "commitizen.commands.check.open", - mocker.mock_open(read_data=commit_msg), + mocker.mock_open( + read_data=( + "feat: This is a test commit\n" + "# Please enter the commit message for your changes. Lines starting\n" + "# with '#' will be ignored, and an empty message aborts the commit.\n" + "#\n" + "# On branch ...\n" + "# Changes to be committed:\n" + "# modified: ...\n" + "#\n" + "# ------------------------ >8 ------------------------\n" + "# Do not modify or remove the line above.\n" + "# Everything below it will be ignored.\n" + "diff --git a/... b/...\n" + "index f1234c..1c5678 1234\n" + "--- a/...\n" + "+++ b/...\n" + "@@ -92,3 +92,4 @@ class Command(BaseCommand):\n" + '+ "this is a test"\n' + ) + ), ) util.run_cli("check", "--commit-msg-file", "some_file") out, _ = capsys.readouterr() @@ -407,7 +381,7 @@ def test_check_command_with_config_message_length_limit_exceeded(config): def test_check_command_cli_overrides_config_message_length_limit( - config, success_mock: MockType, mocker: MockFixture + config, success_mock: MockType ): message = "fix(scope): some commit message" config.settings["message_length_limit"] = len(message) - 1 From c176f7cf5ef1f8bccc54bfaaa923479a22745e72 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Mon, 19 Jan 2026 10:07:33 +0800 Subject: [PATCH 195/221] test(commit): extract fixtures to dedup logic in tests (#1806) --- tests/commands/test_commit_command.py | 354 ++++++-------------------- 1 file changed, 81 insertions(+), 273 deletions(-) diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index c17001292e..87c7aca42c 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -22,15 +22,29 @@ @pytest.fixture def commit_mock(mocker: MockFixture): - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) - return commit_mock + return mocker.patch( + "commitizen.git.commit", return_value=cmd.Command("success", "", b"", b"", 0) + ) + + +@pytest.fixture +def prompt_mock_feat(mocker: MockFixture): + return mocker.patch( + "questionary.prompt", + return_value={ + "prefix": "feat", + "subject": "user created", + "scope": "", + "is_breaking_change": False, + "body": "closes #21", + "footer": "", + }, + ) @pytest.fixture def staging_is_clean(mocker: MockFixture, tmp_git_project): - is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean") - is_staging_clean_mock.return_value = False + mocker.patch("commitizen.git.is_staging_clean", return_value=False) return tmp_git_project @@ -40,36 +54,18 @@ def backup_file(tmp_git_project): backup_file.write("backup commit") -@pytest.mark.usefixtures("staging_is_clean", "commit_mock") -def test_commit(config, success_mock: MockType, mocker: MockFixture): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - +@pytest.mark.usefixtures("staging_is_clean", "commit_mock", "prompt_mock_feat") +def test_commit(config, success_mock: MockType): commands.Commit(config, {})() success_mock.assert_called_once() @pytest.mark.usefixtures("staging_is_clean") -def test_commit_backup_on_failure(config, mocker: MockFixture): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "closes #21", - "footer": "", - } - - mocker.patch("commitizen.git.commit").return_value = cmd.Command( - "", "error", b"", b"", 9 +def test_commit_backup_on_failure( + config, mocker: MockFixture, prompt_mock_feat: MockType +): + mocker.patch( + "commitizen.git.commit", return_value=cmd.Command("", "error", b"", b"", 9) ) error_mock = mocker.patch("commitizen.out.error") @@ -78,7 +74,7 @@ def test_commit_backup_on_failure(config, mocker: MockFixture): with pytest.raises(CommitError): commit_cmd() - prompt_mock.assert_called_once() + prompt_mock_feat.assert_called_once() error_mock.assert_called_once() assert os.path.isfile(temp_file) @@ -109,23 +105,13 @@ def test_commit_retry_works( @pytest.mark.usefixtures("staging_is_clean") def test_commit_retry_after_failure_no_backup( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType, prompt_mock_feat: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "closes #21", - "footer": "", - } - config.settings["retry_after_failure"] = True commands.Commit(config, {})() commit_mock.assert_called_with("feat: user created\n\ncloses #21", args="") - prompt_mock.assert_called_once() + prompt_mock_feat.assert_called_once() success_mock.assert_called_once() @@ -148,119 +134,56 @@ def test_commit_retry_after_failure_works( @pytest.mark.usefixtures("staging_is_clean", "backup_file") def test_commit_retry_after_failure_with_no_retry_works( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType, prompt_mock_feat: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "closes #21", - "footer": "", - } - config.settings["retry_after_failure"] = True commit_cmd = commands.Commit(config, {"no_retry": True}) temp_file = commit_cmd.backup_file_path commit_cmd() commit_mock.assert_called_with("feat: user created\n\ncloses #21", args="") - prompt_mock.assert_called_once() + prompt_mock_feat.assert_called_once() success_mock.assert_called_once() assert not os.path.isfile(temp_file) -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_dry_run_option(config, mocker: MockFixture): - prompt_mock = mocker = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "closes #57", - "footer": "", - } - +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") +def test_commit_command_with_dry_run_option(config): with pytest.raises(DryRunExit): commands.Commit(config, {"dry_run": True})() -@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +@pytest.mark.usefixtures("staging_is_clean", "commit_mock", "prompt_mock_feat") def test_commit_command_with_write_message_to_file_option( - config, tmp_path, success_mock: MockType, mocker: MockFixture + config, tmp_path, success_mock: MockType ): tmp_file = tmp_path / "message" - - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - commands.Commit(config, {"write_message_to_file": tmp_file})() success_mock.assert_called_once() assert tmp_file.exists() - assert tmp_file.read_text() == "feat: user created" - + assert "feat: user created" in tmp_file.read_text() -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_with_invalid_write_message_to_file_option( - config, tmp_path, mocker: MockFixture -): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") +def test_commit_command_with_invalid_write_message_to_file_option(config, tmp_path): with pytest.raises(NotAllowed): commands.Commit(config, {"write_message_to_file": tmp_path})() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") def test_commit_command_with_signoff_option( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - commands.Commit(config, {"signoff": True})() commit_mock.assert_called_once_with(ANY, args="-s") success_mock.assert_called_once() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") def test_commit_command_with_always_signoff_enabled( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - config.settings["always_signoff"] = True commands.Commit(config, {})() @@ -268,20 +191,10 @@ def test_commit_command_with_always_signoff_enabled( success_mock.assert_called_once() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") def test_commit_command_with_gpgsign_and_always_signoff_enabled( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - config.settings["always_signoff"] = True commands.Commit(config, {"extra_cli_args": "-S"})() @@ -291,8 +204,7 @@ def test_commit_command_with_gpgsign_and_always_signoff_enabled( @pytest.mark.usefixtures("tmp_git_project") def test_commit_when_nothing_to_commit(config, mocker: MockFixture): - is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean") - is_staging_clean_mock.return_value = True + mocker.patch("commitizen.git.is_staging_clean", return_value=True) with pytest.raises(NothingToCommitError) as excinfo: commands.Commit(config, {})() @@ -300,42 +212,19 @@ def test_commit_when_nothing_to_commit(config, mocker: MockFixture): assert "No files added to staging!" in str(excinfo.value) -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_with_allow_empty( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType -): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "closes #21", - "footer": "", - } - +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") +def test_commit_with_allow_empty(config, success_mock: MockType, commit_mock: MockType): commands.Commit(config, {"extra_cli_args": "--allow-empty"})() - commit_mock.assert_called_with( "feat: user created\n\ncloses #21", args="--allow-empty" ) success_mock.assert_called_once() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") def test_commit_with_signoff_and_allow_empty( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "closes #21", - "footer": "", - } - config.settings["always_signoff"] = True commands.Commit(config, {"extra_cli_args": "--allow-empty"})() @@ -346,12 +235,10 @@ def test_commit_with_signoff_and_allow_empty( @pytest.mark.usefixtures("staging_is_clean") -def test_commit_when_customized_expected_raised(config, mocker: MockFixture, capsys): +def test_commit_when_customized_expected_raised(config, mocker: MockFixture): _err = ValueError() _err.__context__ = CzException("This is the root custom err") - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.side_effect = _err - + mocker.patch("questionary.prompt", side_effect=_err) with pytest.raises(CustomError) as excinfo: commands.Commit(config, {})() @@ -360,22 +247,15 @@ def test_commit_when_customized_expected_raised(config, mocker: MockFixture, cap @pytest.mark.usefixtures("staging_is_clean") -def test_commit_when_non_customized_expected_raised( - config, mocker: MockFixture, capsys -): - _err = ValueError() - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.side_effect = _err - +def test_commit_when_non_customized_expected_raised(config, mocker: MockFixture): + mocker.patch("questionary.prompt", side_effect=ValueError()) with pytest.raises(ValueError): commands.Commit(config, {})() @pytest.mark.usefixtures("staging_is_clean") -def test_commit_when_no_user_answer(config, mocker: MockFixture, capsys): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = None - +def test_commit_when_no_user_answer(config, mocker: MockFixture): + mocker.patch("questionary.prompt", return_value=None) with pytest.raises(NoAnswersError): commands.Commit(config, {})() @@ -386,69 +266,25 @@ def test_commit_in_non_git_project(tmpdir, config): commands.Commit(config, {}) -@pytest.mark.usefixtures("staging_is_clean", "commit_mock") +@pytest.mark.usefixtures("staging_is_clean", "commit_mock", "prompt_mock_feat") def test_commit_command_with_all_option( config, success_mock: MockType, mocker: MockFixture ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - add_mock = mocker.patch("commitizen.git.add") commands.Commit(config, {"all": True})() add_mock.assert_called() success_mock.assert_called_once() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") def test_commit_command_with_extra_args( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType + config, success_mock: MockType, commit_mock: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - commands.Commit(config, {"extra_cli_args": "-- -extra-args1 -extra-arg2"})() commit_mock.assert_called_once_with(ANY, args="-- -extra-args1 -extra-arg2") success_mock.assert_called_once() -@pytest.mark.usefixtures("staging_is_clean", "commit_mock") -def test_commit_command_with_message_length_limit( - config, success_mock: MockType, mocker: MockFixture -): - prompt_mock = mocker.patch("questionary.prompt") - prefix = "feat" - subject = "random subject" - message_length = len(prefix) + len(": ") + len(subject) - prompt_mock.return_value = { - "prefix": prefix, - "subject": subject, - "scope": "", - "is_breaking_change": False, - "body": "random body", - "footer": "random footer", - } - - commands.Commit(config, {"message_length_limit": message_length})() - success_mock.assert_called_once() - - with pytest.raises(CommitMessageLengthExceededError): - commands.Commit(config, {"message_length_limit": message_length - 1})() - - @pytest.mark.usefixtures("staging_is_clean") @pytest.mark.parametrize("editor", ["vim", None]) def test_manual_edit(editor, config, mocker: MockFixture, tmp_path): @@ -475,28 +311,20 @@ def test_manual_edit(editor, config, mocker: MockFixture, tmp_path): assert edited_message == test_message.strip() -@pytest.mark.usefixtures("staging_is_clean") +@pytest.mark.usefixtures("staging_is_clean", "prompt_mock_feat") @pytest.mark.parametrize( "out", ["no changes added to commit", "nothing added to commit"] ) def test_commit_when_nothing_added_to_commit(config, mocker: MockFixture, out): - prompt_mock = mocker.patch("questionary.prompt") - prompt_mock.return_value = { - "prefix": "feat", - "subject": "user created", - "scope": "", - "is_breaking_change": False, - "body": "", - "footer": "", - } - - commit_mock = mocker.patch("commitizen.git.commit") - commit_mock.return_value = cmd.Command( - out=out, - err="", - stdout=out.encode(), - stderr=b"", - return_code=0, + commit_mock = mocker.patch( + "commitizen.git.commit", + return_value=cmd.Command( + out=out, + err="", + stdout=out.encode(), + stderr=b"", + return_code=0, + ), ) error_mock = mocker.patch("commitizen.out.error") @@ -508,22 +336,20 @@ def test_commit_when_nothing_added_to_commit(config, mocker: MockFixture, out): @pytest.mark.usefixtures("staging_is_clean", "commit_mock") def test_commit_command_with_config_message_length_limit( - config, success_mock: MockType, mocker: MockFixture + config, success_mock: MockType, prompt_mock_feat: MockType ): - prompt_mock = mocker.patch("questionary.prompt") - prefix = "feat" - subject = "random subject" - message_length = len(prefix) + len(": ") + len(subject) - prompt_mock.return_value = { - "prefix": prefix, - "subject": subject, - "scope": "", - "is_breaking_change": False, - "body": "random body", - "footer": "random footer", - } + prefix = prompt_mock_feat.return_value["prefix"] + subject = prompt_mock_feat.return_value["subject"] + message_length = len(f"{prefix}: {subject}") + + commands.Commit(config, {"message_length_limit": message_length})() + success_mock.assert_called_once() + + with pytest.raises(CommitMessageLengthExceededError): + commands.Commit(config, {"message_length_limit": message_length - 1})() config.settings["message_length_limit"] = message_length + success_mock.reset_mock() commands.Commit(config, {})() success_mock.assert_called_once() @@ -531,26 +357,8 @@ def test_commit_command_with_config_message_length_limit( with pytest.raises(CommitMessageLengthExceededError): commands.Commit(config, {})() - -@pytest.mark.usefixtures("staging_is_clean") -def test_commit_command_cli_overrides_config_message_length_limit( - config, success_mock: MockType, mocker: MockFixture, commit_mock: MockType -): - prompt_mock = mocker.patch("questionary.prompt") - prefix = "feat" - subject = "random subject" - message_length = len(prefix) + len(": ") + len(subject) - prompt_mock.return_value = { - "prefix": prefix, - "subject": subject, - "scope": "", - "is_breaking_change": False, - "body": "random body", - "footer": "random footer", - } - - config.settings["message_length_limit"] = message_length - 1 - + # Test config message length limit is overridden by CLI argument + success_mock.reset_mock() commands.Commit(config, {"message_length_limit": message_length})() success_mock.assert_called_once() From 7d1bcc8df176ad64455b56586a2d8c3b4b0b8e2b Mon Sep 17 00:00:00 2001 From: Yazdan Ranjbar <yazdanra@icloud.com> Date: Mon, 19 Jan 2026 00:24:48 -0500 Subject: [PATCH 196/221] feat(prek): supporting prek as an alternative to pre-commit and switching to prek (#1799) * feat(prek): support 'prek' as an alternative to 'pre-commit' in project_info * build(prek): replace 'pre-commit' with 'prek' in project configuration * docs(auto_check): update installation instructions to include 'prek' as an alternative to 'pre-commit' * test: brought back the `pre-commit` tests along with `prek` * docs(README): update badge to reflect support for 'prek' instead of 'pre-commit' * refactor(project_info): enhance pre-commit check to support multiple tools * docs(auto_check): update auto check installation by only keeping one example * docs: update documentation to reflect 'prek' integration and improve clarity * docs(auto_check): add tip for using pre-commit framework alongside prek * docs: improve formatting and clarity for rendering * docs(auto_check): clarify usage of pre-commit framework in instructions --- commitizen/project_info.py | 2 +- docs/README.md | 8 ++--- docs/tutorials/auto_check.md | 40 ++++++++++++++------- pyproject.toml | 7 ++-- tests/test_bump_create_commit_message.py | 10 +++--- tests/test_project_info.py | 1 + uv.lock | 46 +++++++++++++++++++----- 7 files changed, 80 insertions(+), 34 deletions(-) diff --git a/commitizen/project_info.py b/commitizen/project_info.py index a754388008..381629304e 100644 --- a/commitizen/project_info.py +++ b/commitizen/project_info.py @@ -6,7 +6,7 @@ def is_pre_commit_installed() -> bool: - return bool(shutil.which("pre-commit")) + return any(shutil.which(tool) for tool in ("pre-commit", "prek")) def get_default_version_provider() -> Literal[ diff --git a/docs/README.md b/docs/README.md index ad0911e3a3..97cd2880d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,7 +7,7 @@ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/commitizen?style=flat-square)](https://anaconda.org/conda-forge/commitizen) [![homebrew](https://img.shields.io/homebrew/v/commitizen?color=teal&style=flat-square)](https://formulae.brew.sh/formula/commitizen) [![Codecov](https://img.shields.io/codecov/c/github/commitizen-tools/commitizen.svg?style=flat-square)](https://codecov.io/gh/commitizen-tools/commitizen) -[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?style=flat-square&logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) +[![prek](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json&style=flat-square&color=brightgreen)](https://github.com/j178/prek) ![Using Commitizen cli](images/demo.gif) @@ -182,7 +182,7 @@ This command is particularly useful for automation scripts and CI/CD pipelines. For example, you can use the output of the command `cz changelog --dry-run "$(cz version -p)"` to notify your team about a new release in Slack. -#### Pre-commit Integration +#### Prek and Pre-commit Integration Commitizen can automatically validate your commit messages using pre-commit hooks. @@ -200,7 +200,7 @@ repos: 2. Install the hooks: ```sh -pre-commit install --hook-type commit-msg --hook-type pre-push +prek install --hook-type commit-msg --hook-type pre-push ``` | Hook | Recommended Stage | @@ -210,7 +210,7 @@ pre-commit install --hook-type commit-msg --hook-type pre-push > **Note**: Replace `master` with the [latest tag](https://github.com/commitizen-tools/commitizen/tags) to avoid warnings. You can automatically update this with: > ```sh -> pre-commit autoupdate +> prek autoupdate > ``` For more details about commit validation, see the [check command documentation](https://commitizen-tools.github.io/commitizen/commands/check/). diff --git a/docs/tutorials/auto_check.md b/docs/tutorials/auto_check.md index d877d5009f..dc2b6a90c2 100644 --- a/docs/tutorials/auto_check.md +++ b/docs/tutorials/auto_check.md @@ -2,22 +2,35 @@ ## About -To automatically check a commit message prior to committing, you can use a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). This ensures that all commit messages follow your project's commitizen format before they are accepted into the repository. +To automatically check a commit message before committing, use a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). This ensures all commit messages match your project's commitizen format before they are accepted into the repository. -When a commit message fails validation, Git will reject the commit and display an error message explaining what went wrong. You'll need to amend your commit message to follow the required format before the commit can proceed. +When a commit message fails validation, Git rejects the commit and displays an error explaining what went wrong. Update the message to the required format before trying again. ## How to There are two common methods for installing the hooks: -### Method 1: Using [pre-commit](https://pre-commit.com/) (Recommended) +### Method 1: Using pre-commit hook frameworks (Recommended) -[pre-commit](https://pre-commit.com/) is a framework for managing and maintaining multi-language pre-commit hooks. It's the recommended approach as it handles hook installation, updates, and execution automatically. +Using pre-commit hook frameworks is the recommended approach because hook installation, updates, and execution are handled automatically. +Two common frameworks are: -#### Step 1: Install pre-commit +1. [prek](https://prek.j178.dev) (faster) +2. [pre-commit](https://pre-commit.com/) + + +In the steps below, we'll use `prek`. + + +!!! tip "Using pre-commit framework" + If you use pre-commit instead of prek, you can run the same commands. Simply replace prek with pre-commit in the steps below. + + + +#### Step 1: Install prek ```sh -python -m pip install pre-commit +python -m pip install prek ``` #### Step 2: Create `.pre-commit-config.yaml` @@ -42,14 +55,14 @@ repos: Install the configuration into Git's hook system: ```bash -pre-commit install --hook-type commit-msg +prek install --hook-type commit-msg ``` The hook is now active! Every time you create a commit, commitizen will automatically validate your commit message. ### Method 2: Manual Git hook installation -If you prefer not to use pre-commit, you can manually create a Git hook. This gives you full control over the hook script but requires manual maintenance. +If you prefer not to use a pre-commit framework, you can manually create a Git hook. This gives you full control over the hook script but requires manual maintenance. #### Step 1: Create the commit-msg hook @@ -90,7 +103,7 @@ git commit -m "invalid commit message" git commit -m "feat: add new feature" ``` -If the hook is working correctly, invalid commit messages will be rejected with an error message explaining what's wrong. +If the hook is working correctly, invalid commit messages are rejected with an error explaining what's wrong. ## What happens when validation fails? @@ -123,12 +136,12 @@ pattern: ^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\)) - **Verify commitizen is installed**: Run `cz --version` to confirm commitizen is available in your PATH - **Check Git version**: Ensure you're using a recent version of Git that supports hooks -### Pre-commit hook not working +### Prek hook not working -- **Verify installation**: Run `pre-commit --version` to confirm pre-commit is installed -- **Reinstall the hook**: Try running `pre-commit install --hook-type commit-msg` again +- **Verify installation**: Run `prek --version` to confirm pre-commit is installed +- **Reinstall the hook**: Try running `prek install --hook-type commit-msg` again - **Check configuration**: Verify your `.pre-commit-config.yaml` file is valid YAML and in the project root -- **Update hooks**: Run `pre-commit autoupdate` to update to the latest versions +- **Update hooks**: Run `prek autoupdate` to update to the latest versions ### Bypassing the hook (when needed) @@ -145,4 +158,5 @@ git commit --no-verify -m "your message" - Learn more about [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) - See the [check command documentation](../commands/check.md) for more validation options +- Check out [prek documentation](https://prek.j178.dev/) for advanced hook management - Check out [pre-commit documentation](https://pre-commit.com/) for advanced hook management diff --git a/pyproject.toml b/pyproject.toml index fdad366543..a6d851f642 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -107,17 +107,18 @@ test = [ "pytest-freezer>=0.4.6", "pytest-xdist>=3.1.0", "pytest-gitconfig>=0.9.0", + "pre-commit>=4.5.1", ] linters = [ "ruff>=0.11.5", - "pre-commit>=3.2.0", "mypy>=1.16.0", "types-deprecated>=1.2.9.2", "types-python-dateutil>=2.8.19.13", "types-PyYAML>=5.4.3", "types-termcolor>=0.1.1", "types-colorama>=0.4.15.20240311", + "prek>=0.2.28", ] documentation = ["mkdocs>=1.4.2", "mkdocs-material>=9.1.6"] @@ -303,8 +304,8 @@ doc.help = "Live documentation server" doc.cmd = "mkdocs serve --livereload" # mkdocs hot reload failure workaround. Ref: https://github.com/mkdocs/mkdocs/issues/4032#issuecomment-3591002290 ci.help = "Run all tasks in CI" -ci.sequence = ["check-commit", { cmd = "pre-commit run --all-files" }, "cover"] +ci.sequence = ["check-commit", { cmd = "prek run --all-files" }, "cover"] ci.env = { SKIP = "no-commit-to-branch" } setup-pre-commit.help = "Install pre-commit hooks" -setup-pre-commit.cmd = "pre-commit install" +setup-pre-commit.cmd = "prek install" diff --git a/tests/test_bump_create_commit_message.py b/tests/test_bump_create_commit_message.py index 0477b5eeb9..bdafd2364a 100644 --- a/tests/test_bump_create_commit_message.py +++ b/tests/test_bump_create_commit_message.py @@ -24,6 +24,7 @@ def test_create_tag(test_input, expected): assert new_tag == expected +@pytest.mark.parametrize("hook_runner", ("pre-commit", "prek")) @pytest.mark.parametrize( "retry", ( @@ -38,7 +39,7 @@ def test_create_tag(test_input, expected): ), ) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_pre_commit_changelog(util: UtilFixture, retry): +def test_bump_pre_commit_changelog(util: UtilFixture, retry, hook_runner): util.freezer.move_to("2022-04-01") bump_args = ["bump", "--changelog", "--yes"] if retry: @@ -69,7 +70,7 @@ def test_bump_pre_commit_changelog(util: UtilFixture, retry): ) cmd.run("git add -A") cmd.run('git commit -m "fix: _test"') - cmd.run("pre-commit install") + cmd.run(f"{hook_runner} install") util.run_cli(*bump_args) # Pre-commit fixed last line adding extra indent and "\" char assert Path("CHANGELOG.md").read_text() == dedent( @@ -83,9 +84,10 @@ def test_bump_pre_commit_changelog(util: UtilFixture, retry): ) +@pytest.mark.parametrize("hook_runner", ("pre-commit", "prek")) @pytest.mark.parametrize("retry", (True, False)) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry): +def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry, hook_runner): util.freezer.move_to("2022-04-01") bump_args = ["bump", "--changelog", "--yes"] if retry: @@ -106,7 +108,7 @@ def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry): ) cmd.run("git add -A") cmd.run('git commit -m "feat: forbid changelogs"') - cmd.run("pre-commit install") + cmd.run(f"{hook_runner} install") with pytest.raises(exceptions.BumpCommitFailedError): util.run_cli(*bump_args) diff --git a/tests/test_project_info.py b/tests/test_project_info.py index d30a743e58..9fe26d3612 100644 --- a/tests/test_project_info.py +++ b/tests/test_project_info.py @@ -22,6 +22,7 @@ def _create_project_files(files: dict[str, str | None]) -> None: "which_return, expected", [ ("/usr/local/bin/pre-commit", True), + ("/usr/local/bin/prek", True), (None, False), ("", False), ], diff --git a/uv.lock b/uv.lock index 33c98d0344..80c092f73f 100644 --- a/uv.lock +++ b/uv.lock @@ -225,6 +225,7 @@ dev = [ { name = "mypy" }, { name = "poethepoet" }, { name = "pre-commit" }, + { name = "prek" }, { name = "pytest" }, { name = "pytest-cov" }, { name = "pytest-freezer" }, @@ -248,7 +249,7 @@ documentation = [ ] linters = [ { name = "mypy" }, - { name = "pre-commit" }, + { name = "prek" }, { name = "ruff" }, { name = "types-colorama" }, { name = "types-deprecated" }, @@ -260,6 +261,7 @@ script = [ { name = "rich" }, ] test = [ + { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-cov" }, { name = "pytest-freezer" }, @@ -295,7 +297,8 @@ dev = [ { name = "mkdocs-material", specifier = ">=9.1.6" }, { name = "mypy", specifier = ">=1.16.0" }, { name = "poethepoet", specifier = ">=0.34.0" }, - { name = "pre-commit", specifier = ">=3.2.0" }, + { name = "pre-commit", specifier = ">=4.5.1" }, + { name = "prek", specifier = ">=0.2.28" }, { name = "pytest", specifier = ">=9" }, { name = "pytest-cov", specifier = ">=4" }, { name = "pytest-freezer", specifier = ">=0.4.6" }, @@ -319,7 +322,7 @@ documentation = [ ] linters = [ { name = "mypy", specifier = ">=1.16.0" }, - { name = "pre-commit", specifier = ">=3.2.0" }, + { name = "prek", specifier = ">=0.2.28" }, { name = "ruff", specifier = ">=0.11.5" }, { name = "types-colorama", specifier = ">=0.4.15.20240311" }, { name = "types-deprecated", specifier = ">=1.2.9.2" }, @@ -329,6 +332,7 @@ linters = [ ] script = [{ name = "rich", specifier = ">=13.7.1" }] test = [ + { name = "pre-commit", specifier = ">=4.5.1" }, { name = "pytest", specifier = ">=9" }, { name = "pytest-cov", specifier = ">=4" }, { name = "pytest-freezer", specifier = ">=0.4.6" }, @@ -546,11 +550,11 @@ wheels = [ [[package]] name = "identify" -version = "2.6.15" +version = "2.6.16" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ff/e7/685de97986c916a6d93b3876139e00eef26ad5bbbd61925d670ae8013449/identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf", size = 99311, upload-time = "2025-10-02T17:43:40.631Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/8d/e8b97e6bd3fb6fb271346f7981362f1e04d6a7463abd0de79e1fda17c067/identify-2.6.16.tar.gz", hash = "sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980", size = 99360, upload-time = "2026-01-12T18:58:58.201Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/1c/e5fd8f973d4f375adb21565739498e2e9a1e54c858a97b9a8ccfdc81da9b/identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757", size = 99183, upload-time = "2025-10-02T17:43:39.137Z" }, + { url = "https://files.pythonhosted.org/packages/b8/58/40fbbcefeda82364720eba5cf2270f98496bdfa19ea75b4cccae79c698e6/identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0", size = 99202, upload-time = "2026-01-12T18:58:56.627Z" }, ] [[package]] @@ -992,11 +996,11 @@ wheels = [ [[package]] name = "nodeenv" -version = "1.9.1" +version = "1.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] [[package]] @@ -1104,6 +1108,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, ] +[[package]] +name = "prek" +version = "0.2.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/d7/dda8a6b7819bdb9d1f54fa046911e80974d862bacba75a3539b43a9bb858/prek-0.2.28.tar.gz", hash = "sha256:ac54f58cad26e617a5c5459b705ff1cbaaa41640db03d8d35e39645aca1b82cf", size = 283945, upload-time = "2026-01-13T15:12:20.185Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/8c/2e18867e31d06dfa4974bf31c4e597dc1d2b3671b3c04d85f1f6a32ebc74/prek-0.2.28-py3-none-linux_armv6l.whl", hash = "sha256:1705c0bd035379cb5f1d03c19481821363d72d7923303fe8c84fd8cc7c6c3318", size = 4802811, upload-time = "2026-01-13T15:12:14.698Z" }, + { url = "https://files.pythonhosted.org/packages/26/fa/6c6d0b0d8b2f21301da2bb3441f22232ed5a8cba1b63eeb18244d2192a2e/prek-0.2.28-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:67677c08767c278335b31ebcbf00c1c73e14eadd99a0d8537dfb43c54482673a", size = 4904156, upload-time = "2026-01-13T15:12:21.184Z" }, + { url = "https://files.pythonhosted.org/packages/fc/5a/aa071ef1c2e6c3f58b50d9138676c96dd6de2323a44e1a3e56e18d25c382/prek-0.2.28-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ffac92215058ea6ba954a8e3f978dcd2a5e89922a318fcb7035fb9c0ab4de395", size = 4630803, upload-time = "2026-01-13T15:12:06.158Z" }, + { url = "https://files.pythonhosted.org/packages/77/dc/66498e805a0bb17820de0c3575d75b202c66045a9bfeeff9305d9bedd126/prek-0.2.28-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:413c3da1c9b252b3fd5113f4a04c2dead3c793b0ec56fc55294bb797ba7ca056", size = 4826037, upload-time = "2026-01-13T15:12:12.726Z" }, + { url = "https://files.pythonhosted.org/packages/27/ad/99cccc9283c7b34cd92356fcb301a2b1c25a8b65dc34b86c671b0f8e29d8/prek-0.2.28-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e99639bb68b70704e7b3f7f1a51cb23527c4dbd4b8a01dfccaa70f26f8f6c58b", size = 4723658, upload-time = "2026-01-13T15:12:01.538Z" }, + { url = "https://files.pythonhosted.org/packages/53/13/ce3edc2dda7b65485612e08ab038b8dd1ef7b10a94b0193f527b19a5e246/prek-0.2.28-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33c4a1b2a8a76581476ae327d6d4f1b0af6af42a90d436e21e45c72cb1081b81", size = 5044611, upload-time = "2026-01-13T15:12:26.331Z" }, + { url = "https://files.pythonhosted.org/packages/48/47/6405d7ad7959d9b57d56fec9a1b4b2e00abeb955084dd45d100fb50a8377/prek-0.2.28-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6236dda18152fc56b9f802ce2914fbb2d19f9891595d552228c7894004b3332f", size = 5511371, upload-time = "2026-01-13T15:12:24.453Z" }, + { url = "https://files.pythonhosted.org/packages/92/cc/108c227fae40268ece36b80e5649037f1a816518e9b6d585d128b263df79/prek-0.2.28-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6506709d9a52ee431d48b249b8b5fb93597a9511eb260ee85d868750425057f", size = 5099352, upload-time = "2026-01-13T15:12:18.876Z" }, + { url = "https://files.pythonhosted.org/packages/12/d6/156ad3996d3a078a1bc2c0839b8681634216a494dcb298b8751beb28b327/prek-0.2.28-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:7cc920c12613440c105a767dc19acf048e8a05342ba38b48450d673bea33bd62", size = 4834340, upload-time = "2026-01-13T15:11:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/06/c632d4c4bb9c63d25bcc26149f99c715206a40e414fb6b80e7f800ae2e2d/prek-0.2.28-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:322a1922e6d2fcb2a4c487e01b2613856dc3206269bdc317ad28770704159e63", size = 4844870, upload-time = "2026-01-13T15:12:03.243Z" }, + { url = "https://files.pythonhosted.org/packages/ba/03/763f62d292399ee962e2583e7bc3fd2f8ee2609813c89cc10ec89a39204c/prek-0.2.28-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a07baefe3562371368135eac3c8b9cdb831bac17b83cb1b6a8f5688050918e6c", size = 4709011, upload-time = "2026-01-13T15:12:04.701Z" }, + { url = "https://files.pythonhosted.org/packages/e1/62/49397d1a5c2aaf5e7a8c0644be901ee97934a8a2cac0052652d01b7c6585/prek-0.2.28-py3-none-musllinux_1_1_i686.whl", hash = "sha256:17e95cab33067365028ffc1d4ab6c80c6c150f88e352d7c64bdc15e0570778f6", size = 4928435, upload-time = "2026-01-13T15:11:58.147Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e8/8ec73b5bb3fb9d5daf77f181cc46c541bd476075c7613f9b4c9c953925cc/prek-0.2.28-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:bc5272e2e8d81438a3cd2785c3b14b6e73dcb8e61b8a2b7ce6e693d57f7181ac", size = 5209880, upload-time = "2026-01-13T15:12:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/f3/52/a784a52bf72619bdfaafdbb6c964bda404b377213e7dc786f9ad6024501c/prek-0.2.28-py3-none-win32.whl", hash = "sha256:74657a1663191fb5f09f15873704c2d2640095ce56277d36860bbd08ba7eea94", size = 4622786, upload-time = "2026-01-13T15:12:22.967Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b8/ec6aafefeb05ef3a0bfcc044d036890f2b732b90ed1426acbf1e33289a44/prek-0.2.28-py3-none-win_amd64.whl", hash = "sha256:c350046d623362db65e2be1455ef1c5a96ea476e235445752fa946a705f1c1c9", size = 5316389, upload-time = "2026-01-13T15:12:17.501Z" }, + { url = "https://files.pythonhosted.org/packages/df/3f/9d4aba92cb9199cad0b056de8292a78dcca1dc1f6a6a34550799f19bde3d/prek-0.2.28-py3-none-win_arm64.whl", hash = "sha256:81db6ba7e5cf1d5ceec7d3b04e01aded32b8db8f1238ad812ac6ebc0bd35f141", size = 4974627, upload-time = "2026-01-13T15:11:56.333Z" }, +] + [[package]] name = "prompt-toolkit" version = "3.0.51" From 89a69f56703fb6c1d4096bc1d82a1ed0774156df Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 05:25:15 +0000 Subject: [PATCH 197/221] =?UTF-8?q?bump:=20version=204.11.6=20=E2=86=92=20?= =?UTF-8?q?4.12.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 602683fa50..e9c41fd360 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.11.6 # automatically updated by Commitizen + rev: v4.12.0 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ce1bd2a6a..c81becb841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.12.0 (2026-01-19) + +### Feat + +- **prek**: supporting prek as an alternative to pre-commit and switching to prek (#1799) + ## v4.11.6 (2026-01-15) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 54bf8651d7..ade1e2b4ce 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.11.6" +__version__ = "4.12.0" diff --git a/pyproject.toml b/pyproject.toml index a6d851f642..976978f2cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.11.6" +version = "4.12.0" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index 80c092f73f..81ed84d661 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.11.6" +version = "4.12.0" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 3462f947d15482f08b2ff305bce22520a6a325ed Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Mon, 19 Jan 2026 13:45:14 +0800 Subject: [PATCH 198/221] test: extract fixtures to shorten tests (#1809) --- tests/commands/conftest.py | 22 +- tests/commands/test_bump_command.py | 334 +++++++----------- tests/commands/test_changelog_command.py | 274 ++++++-------- ...aming_user_to_users_n_nfooter_content_.md} | 0 ...NGE__migrate_by_renaming_user_to_users_.md | 10 + ..._newline_separates_new_content_from_old.md | 7 + .../test_invalid_subject_is_skipped.md | 6 + tests/commands/test_init_command.py | 2 +- tests/conftest.py | 24 +- tests/test_bump_update_version_in_files.py | 18 +- tests/test_changelog.py | 15 +- 11 files changed, 295 insertions(+), 417 deletions(-) rename tests/commands/test_changelog_command/{test_breaking_change_content_v1_beta.md => test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_n_nfooter_content_.md} (100%) create mode 100644 tests/commands/test_changelog_command/test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nbody_content_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_.md create mode 100644 tests/commands/test_changelog_command/test_changelog_incremental_newline_separates_new_content_from_old.md create mode 100644 tests/commands/test_changelog_command/test_invalid_subject_is_skipped.md diff --git a/tests/commands/conftest.py b/tests/commands/conftest.py index 88fc89b7cb..c7d5904504 100644 --- a/tests/commands/conftest.py +++ b/tests/commands/conftest.py @@ -1,22 +1,23 @@ import os +from pathlib import Path import pytest -from pytest_mock import MockerFixture +from pytest_mock import MockerFixture, MockType from commitizen import defaults from commitizen.config import BaseConfig from commitizen.config.json_config import JsonConfig -@pytest.fixture() -def config(): +@pytest.fixture +def config() -> BaseConfig: _config = BaseConfig() _config.settings.update({"name": defaults.DEFAULT_SETTINGS["name"]}) return _config -@pytest.fixture() -def config_customize(): +@pytest.fixture +def config_customize() -> JsonConfig: json_string = r"""{ "commitizen": { "name": "cz_customize", @@ -41,20 +42,19 @@ def config_customize(): } } }""" - _config = JsonConfig(data=json_string, path="not_exist.json") - return _config + return JsonConfig(data=json_string, path=Path("not_exist.json")) -@pytest.fixture() +@pytest.fixture def changelog_path() -> str: return os.path.join(os.getcwd(), "CHANGELOG.md") -@pytest.fixture() +@pytest.fixture def config_path() -> str: return os.path.join(os.getcwd(), "pyproject.toml") -@pytest.fixture() -def success_mock(mocker: MockerFixture): +@pytest.fixture +def success_mock(mocker: MockerFixture) -> MockType: return mocker.patch("commitizen.out.success") diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index d79a76b5ae..a1c70b9480 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -5,7 +5,7 @@ from pathlib import Path from textwrap import dedent from typing import TYPE_CHECKING -from unittest.mock import MagicMock, call +from unittest.mock import call import pytest @@ -53,8 +53,7 @@ def test_bump_patch_increment(commit_msg: str, util: UtilFixture): util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.1.1") - assert tag_exists is True + assert git.tag_exist("0.1.1") is True @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @@ -62,9 +61,11 @@ def test_bump_patch_increment(commit_msg: str, util: UtilFixture): def test_bump_minor_increment(commit_msg: str, util: UtilFixture): util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.2.0") - cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') - assert tag_exists is True and "commit:refs/tags/0.2.0\n" in cmd_res.out + assert git.tag_exist("0.2.0") is True + assert ( + "commit:refs/tags/0.2.0" + in cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"').out + ) @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @@ -72,12 +73,13 @@ def test_bump_minor_increment(commit_msg: str, util: UtilFixture): def test_bump_minor_increment_annotated(commit_msg: str, util: UtilFixture): util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes", "--annotated-tag") - tag_exists = git.tag_exist("0.2.0") - cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') - assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out + assert git.tag_exist("0.2.0") is True + assert ( + "tag:refs/tags/0.2.0" + in cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"').out + ) - _is_signed = git.is_signed_tag("0.2.0") - assert _is_signed is False + assert git.is_signed_tag("0.2.0") is False @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @@ -85,30 +87,29 @@ def test_bump_minor_increment_annotated(commit_msg: str, util: UtilFixture): def test_bump_minor_increment_signed(commit_msg: str, util: UtilFixture): util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes", "--gpg-sign") - tag_exists = git.tag_exist("0.2.0") - cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') - assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out + assert git.tag_exist("0.2.0") is True + assert ( + "tag:refs/tags/0.2.0" + in cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"').out + ) - _is_signed = git.is_signed_tag("0.2.0") - assert _is_signed is True + assert git.is_signed_tag("0.2.0") is True @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) def test_bump_minor_increment_annotated_config_file( - commit_msg: str, util: UtilFixture, tmp_commitizen_project + commit_msg: str, util: UtilFixture, pyproject: Path ): - tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") - tmp_commitizen_cfg_file.write( - f"{tmp_commitizen_cfg_file.read()}\nannotated_tag = 1" - ) + pyproject.write_text(pyproject.read_text() + "\nannotated_tag = 1") util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.2.0") - cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') - assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out + assert git.tag_exist("0.2.0") is True + assert ( + "tag:refs/tags/0.2.0" + in cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"').out + ) - _is_signed = git.is_signed_tag("0.2.0") - assert _is_signed is False + assert git.is_signed_tag("0.2.0") is False @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @@ -119,12 +120,13 @@ def test_bump_minor_increment_signed_config_file( tmp_commitizen_cfg_file.write(f"{tmp_commitizen_cfg_file.read()}\ngpg_sign = 1") util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.2.0") - cmd_res = cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"') - assert tag_exists is True and "tag:refs/tags/0.2.0\n" in cmd_res.out + assert git.tag_exist("0.2.0") is True + assert ( + "tag:refs/tags/0.2.0" + in cmd.run('git for-each-ref refs/tags --format "%(objecttype):%(refname)"').out + ) - _is_signed = git.is_signed_tag("0.2.0") - assert _is_signed is True + assert git.is_signed_tag("0.2.0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -143,11 +145,8 @@ def test_bump_minor_increment_signed_config_file( ) def test_bump_major_increment(commit_msg: str, util: UtilFixture): util.create_file_and_commit(commit_msg) - util.run_cli("bump", "--yes") - - tag_exists = git.tag_exist("1.0.0") - assert tag_exists is True + assert git.tag_exist("1.0.0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -166,11 +165,8 @@ def test_bump_major_increment(commit_msg: str, util: UtilFixture): ) def test_bump_major_increment_major_version_zero(commit_msg: str, util: UtilFixture): util.create_file_and_commit(commit_msg) - util.run_cli("bump", "--yes", "--major-version-zero") - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -187,11 +183,8 @@ def test_bump_command_increment_option( commit_msg: str, increment: str, expected_tag: str, util: UtilFixture ): util.create_file_and_commit(commit_msg) - util.run_cli("bump", "--increment", increment, "--yes") - - tag_exists = git.tag_exist(expected_tag) - assert tag_exists is True + assert git.tag_exist(expected_tag) is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -200,109 +193,76 @@ def test_bump_command_prerelease(util: UtilFixture): # Create an alpha pre-release. util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("0.2.0a0") - assert tag_exists is True + assert git.tag_exist("0.2.0a0") is True # Create a beta pre-release. util.run_cli("bump", "--prerelease", "beta", "--yes") - - tag_exists = git.tag_exist("0.2.0b0") - assert tag_exists is True + assert git.tag_exist("0.2.0b0") is True # With a current beta pre-release, bumping alpha must bump beta # because we can't bump "backwards". util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("0.2.0a1") - assert tag_exists is False - tag_exists = git.tag_exist("0.2.0b1") - assert tag_exists is True + assert git.tag_exist("0.2.0a1") is False + assert git.tag_exist("0.2.0b1") is True # Create a rc pre-release. util.run_cli("bump", "--prerelease", "rc", "--yes") - - tag_exists = git.tag_exist("0.2.0rc0") - assert tag_exists is True + assert git.tag_exist("0.2.0rc0") is True # With a current rc pre-release, bumping alpha must bump rc. util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("0.2.0a1") - assert tag_exists is False - tag_exists = git.tag_exist("0.2.0b2") - assert tag_exists is False - tag_exists = git.tag_exist("0.2.0rc1") - assert tag_exists is True + assert git.tag_exist("0.2.0a1") is False + assert git.tag_exist("0.2.0b2") is False + assert git.tag_exist("0.2.0rc1") is True # With a current rc pre-release, bumping beta must bump rc. util.run_cli("bump", "--prerelease", "beta", "--yes") - - tag_exists = git.tag_exist("0.2.0a2") - assert tag_exists is False - tag_exists = git.tag_exist("0.2.0b2") - assert tag_exists is False - tag_exists = git.tag_exist("0.2.0rc2") - assert tag_exists is True + assert git.tag_exist("0.2.0a2") is False + assert git.tag_exist("0.2.0b2") is False + assert git.tag_exist("0.2.0rc2") is True # Create a final release from the current pre-release. util.run_cli("bump") - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_command_prerelease_increment(util: UtilFixture): # FINAL RELEASE util.create_file_and_commit("fix: location") - util.run_cli("bump", "--yes") - assert git.tag_exist("0.1.1") + assert git.tag_exist("0.1.1") is True # PRERELEASE util.create_file_and_commit("fix: location") - util.run_cli("bump", "--prerelease", "alpha", "--yes") - - assert git.tag_exist("0.1.2a0") + assert git.tag_exist("0.1.2a0") is True util.create_file_and_commit("feat: location") - util.run_cli("bump", "--prerelease", "alpha", "--yes") - - assert git.tag_exist("0.2.0a0") + assert git.tag_exist("0.2.0a0") is True util.create_file_and_commit("feat!: breaking") - util.run_cli("bump", "--prerelease", "alpha", "--yes") - - assert git.tag_exist("1.0.0a0") + assert git.tag_exist("1.0.0a0") is True @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_command_prerelease_exact_mode(util: UtilFixture): # PRERELEASE util.create_file_and_commit("feat: location") - util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("0.2.0a0") - assert tag_exists is True + assert git.tag_exist("0.2.0a0") is True # PRERELEASE + PATCH BUMP util.run_cli("bump", "--prerelease", "alpha", "--yes", "--increment-mode=exact") - tag_exists = git.tag_exist("0.2.0a1") - assert tag_exists is True + assert git.tag_exist("0.2.0a1") is True # PRERELEASE + MINOR BUMP # --increment-mode allows the minor version to bump, and restart the prerelease util.create_file_and_commit("feat: location") - util.run_cli("bump", "--prerelease", "alpha", "--yes", "--increment-mode=exact") - - tag_exists = git.tag_exist("0.3.0a0") - assert tag_exists is True + assert git.tag_exist("0.3.0a0") is True # PRERELEASE + MAJOR BUMP # --increment-mode=exact allows the major version to bump, and restart the prerelease @@ -315,8 +275,7 @@ def test_bump_command_prerelease_exact_mode(util: UtilFixture): "--increment-mode=exact", ) - tag_exists = git.tag_exist("1.0.0a0") - assert tag_exists is True + assert git.tag_exist("1.0.0a0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -329,11 +288,8 @@ def test_bump_on_git_with_hooks_no_verify_disabled(util: UtilFixture): # MINOR util.create_file_and_commit("feat: new file") - util.run_cli("bump", "--yes") - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -361,11 +317,8 @@ def test_bump_on_git_with_hooks_no_verify_enabled(util: UtilFixture): # MINOR util.create_file_and_commit("feat: new file") - util.run_cli("bump", "--yes", "--no-verify") - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -376,7 +329,6 @@ def test_bump_when_bumping_is_not_support(util: UtilFixture): with pytest.raises(NoPatternMapError) as excinfo: util.run_cli("-n", "cz_jira", "bump", "--yes") - assert "'cz_jira' rule does not support bump" in str(excinfo.value) @@ -400,8 +352,7 @@ def test_bump_when_no_new_commit(util: UtilFixture): with pytest.raises(NoCommitsFoundError) as excinfo: util.run_cli("bump", "--yes") - expected_error_message = "[NO_COMMITS_FOUND]\nNo new commits found." - assert expected_error_message in str(excinfo.value) + assert "[NO_COMMITS_FOUND]\nNo new commits found." in str(excinfo.value) def test_bump_when_version_inconsistent_in_version_files( @@ -421,8 +372,7 @@ def test_bump_when_version_inconsistent_in_version_files( with pytest.raises(CurrentVersionNotFoundError) as excinfo: util.run_cli("bump", "--yes", "--check-consistency") - partial_expected_error_message = "Current version 0.1.0 is not found in" - assert partial_expected_error_message in str(excinfo.value) + assert "Current version 0.1.0 is not found in" in str(excinfo.value) def test_bump_major_version_zero_when_major_is_not_zero( @@ -447,10 +397,9 @@ def test_bump_major_version_zero_when_major_is_not_zero( with pytest.raises(NotAllowed) as excinfo: util.run_cli("bump", "--yes", "--major-version-zero") - expected_error_message = ( - "--major-version-zero is meaningless for current version 1.0.0" + assert "--major-version-zero is meaningless for current version 1.0.0" in str( + excinfo.value ) - assert expected_error_message in str(excinfo.value) def test_bump_files_only(tmp_commitizen_project, util: UtilFixture): @@ -465,15 +414,12 @@ def test_bump_files_only(tmp_commitizen_project, util: UtilFixture): util.create_file_and_commit("feat: new user interface") util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True util.create_file_and_commit("feat: another new feature") with pytest.raises(ExpectedExit): util.run_cli("bump", "--yes", "--files-only") - - tag_exists = git.tag_exist("0.3.0") - assert tag_exists is False + assert git.tag_exist("0.3.0") is False with open(tmp_version_file, encoding="utf-8") as f: assert "0.3.0" in f.read() @@ -495,15 +441,14 @@ def test_bump_local_version(tmp_commitizen_project, util: UtilFixture): util.create_file_and_commit("feat: new user interface") util.run_cli("bump", "--yes", "--local-version") - tag_exists = git.tag_exist("4.5.1+0.2.0") - assert tag_exists is True + assert git.tag_exist("4.5.1+0.2.0") is True with open(tmp_version_file, encoding="utf-8") as f: assert "4.5.1+0.2.0" in f.read() @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_dry_run(util: UtilFixture, capsys): +def test_bump_dry_run(util: UtilFixture, capsys: pytest.CaptureFixture): util.create_file_and_commit("feat: new file") with pytest.raises(DryRunExit): @@ -511,12 +456,10 @@ def test_bump_dry_run(util: UtilFixture, capsys): out, _ = capsys.readouterr() assert "0.2.0" in out - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is False + assert git.tag_exist("0.2.0") is False -def test_bump_in_non_git_project(tmpdir, config, util: UtilFixture): +def test_bump_in_non_git_project(tmpdir, util: UtilFixture): with tmpdir.as_cwd(): with pytest.raises(NotAGitProjectError): with pytest.raises(ExpectedExit): @@ -541,31 +484,24 @@ def test_none_increment_exit_is_exception(): @pytest.mark.usefixtures("tmp_commitizen_project") def test_none_increment_should_not_call_git_tag_and_error_code_is_not_zero( - mocker: MockFixture, util: UtilFixture + mocker: MockFixture, + util: UtilFixture, ): util.create_file_and_commit("test(test_get_all_droplets): fix bad comparison test") - - # stash git.tag for later restore - stashed_git_tag = git.tag - dummy_value = git.tag("0.0.2") - git.tag = MagicMock(return_value=dummy_value) + git_tag_mock = mocker.patch("commitizen.git.tag") with pytest.raises(NoneIncrementExit) as e: util.run_cli("bump", "--yes") - git.tag.assert_not_called() + git_tag_mock.assert_not_called() assert e.value.exit_code == ExitCode.NO_INCREMENT - # restore pop stashed - git.tag = stashed_git_tag - @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_with_changelog_arg(util: UtilFixture, changelog_path): util.create_file_and_commit("feat(user): new file") util.run_cli("bump", "--yes", "--changelog") - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -580,8 +516,7 @@ def test_bump_with_changelog_config(util: UtilFixture, changelog_path, config_pa fp.write("update_changelog_on_bump = true\n") util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -590,7 +525,9 @@ def test_bump_with_changelog_config(util: UtilFixture, changelog_path, config_pa @pytest.mark.usefixtures("tmp_commitizen_project") -def test_prevent_prerelease_when_no_increment_detected(util: UtilFixture, capsys): +def test_prevent_prerelease_when_no_increment_detected( + util: UtilFixture, capsys: pytest.CaptureFixture +): util.create_file_and_commit("feat: new file") util.run_cli("bump", "--yes") @@ -603,21 +540,21 @@ def test_prevent_prerelease_when_no_increment_detected(util: UtilFixture, capsys with pytest.raises(NoCommitsFoundError) as excinfo: util.run_cli("bump", "-pr", "beta") - expected_error_message = ( - "[NO_COMMITS_FOUND]\nNo commits found to generate a pre-release." + assert "[NO_COMMITS_FOUND]\nNo commits found to generate a pre-release." in str( + excinfo.value ) - assert expected_error_message in str(excinfo.value) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_changelog_to_stdout_arg(util: UtilFixture, capsys, changelog_path): +def test_bump_with_changelog_to_stdout_arg( + util: UtilFixture, capsys: pytest.CaptureFixture, changelog_path: Path +): util.create_file_and_commit("feat(user): this should appear in stdout") util.run_cli("bump", "--yes", "--changelog-to-stdout") out, _ = capsys.readouterr() assert "this should appear in stdout" in out - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -627,7 +564,7 @@ def test_bump_with_changelog_to_stdout_arg(util: UtilFixture, capsys, changelog_ @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_with_changelog_to_stdout_dry_run_arg( - util: UtilFixture, capsys, changelog_path + util: UtilFixture, capsys: pytest.CaptureFixture, changelog_path: Path ): util.create_file_and_commit( "feat(user): this should appear in stdout with dry-run enabled" @@ -636,15 +573,16 @@ def test_bump_with_changelog_to_stdout_dry_run_arg( util.run_cli("bump", "--yes", "--changelog-to-stdout", "--dry-run") out, _ = capsys.readouterr() - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is False + assert git.tag_exist("0.2.0") is False assert out.startswith("#") assert "this should appear in stdout with dry-run enabled" in out assert "0.2.0" in out @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_without_git_to_stdout_arg(util: UtilFixture, capsys, changelog_path): +def test_bump_without_git_to_stdout_arg( + util: UtilFixture, capsys: pytest.CaptureFixture +): util.create_file_and_commit("feat(user): this should appear in stdout") util.run_cli("bump", "--yes") out, _ = capsys.readouterr() @@ -656,7 +594,7 @@ def test_bump_without_git_to_stdout_arg(util: UtilFixture, capsys, changelog_pat @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_with_git_to_stdout_arg(util: UtilFixture, capsys, changelog_path): +def test_bump_with_git_to_stdout_arg(util: UtilFixture, capsys: pytest.CaptureFixture): util.create_file_and_commit("feat(user): this should appear in stdout") util.run_cli("bump", "--yes", "--git-output-to-stderr") out, _ = capsys.readouterr() @@ -799,10 +737,10 @@ def test_bump_invalid_manual_version_raises_exception( with pytest.raises(InvalidManualVersion) as excinfo: util.run_cli("bump", "--yes", manual_version) - expected_error_message = ( + assert ( f"[INVALID_MANUAL_VERSION]\nInvalid manual version: '{manual_version}'" + in str(excinfo.value) ) - assert expected_error_message in str(excinfo.value) @pytest.mark.usefixtures("tmp_commitizen_project") @@ -823,23 +761,18 @@ def test_bump_manual_version(util: UtilFixture, manual_version): util.create_file_and_commit("feat: new file") util.run_cli("bump", "--yes", manual_version) - tag_exists = git.tag_exist(manual_version) - assert tag_exists is True + assert git.tag_exist(manual_version) is True @pytest.mark.usefixtures("tmp_commitizen_project") def test_bump_manual_version_disallows_major_version_zero(util: UtilFixture): util.create_file_and_commit("feat: new file") - - manual_version = "0.2.0" - with pytest.raises(NotAllowed) as excinfo: - util.run_cli("bump", "--yes", "--major-version-zero", manual_version) + util.run_cli("bump", "--yes", "--major-version-zero", "0.2.0") - expected_error_message = ( - "--major-version-zero cannot be combined with MANUAL_VERSION" + assert "--major-version-zero cannot be combined with MANUAL_VERSION" in str( + excinfo.value ) - assert expected_error_message in str(excinfo.value) @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) @@ -862,8 +795,7 @@ def test_bump_with_pre_bump_hooks( util.create_file_and_commit(commit_msg) util.run_cli("bump", "--yes") - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True run_mock.assert_has_calls( [ @@ -914,8 +846,7 @@ def test_bump_with_hooks_and_increment( util.create_file_and_commit("test: some test") util.run_cli("bump", "--yes", "--increment", "MINOR") - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True @pytest.mark.usefixtures("tmp_git_project") @@ -929,7 +860,7 @@ def test_bump_use_version_provider(mocker: MockFixture, util: UtilFixture): util.create_file_and_commit("fix: fake commit") util.run_cli("bump", "--yes", "--changelog") - assert git.tag_exist("0.0.1") + assert git.tag_exist("0.0.1") is True get_provider.assert_called_once() mock.get_version.assert_called_once() mock.set_version.assert_called_once_with("0.0.1") @@ -950,9 +881,7 @@ def test_bump_command_prerelease_scheme_via_cli( "--version-scheme", "semver", ) - - tag_exists = git.tag_exist("0.2.0-a0") - assert tag_exists is True + assert git.tag_exist("0.2.0-a0") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: @@ -960,9 +889,7 @@ def test_bump_command_prerelease_scheme_via_cli( # PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE util.run_cli("bump", "--yes") - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: @@ -979,18 +906,14 @@ def test_bump_command_prerelease_scheme_via_config( tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("0.2.0-a0") - assert tag_exists is True + assert git.tag_exist("0.2.0-a0") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: assert "0.2.0-a0" in f.read() util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("0.2.0-a1") - assert tag_exists is True + assert git.tag_exist("0.2.0-a1") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: @@ -998,9 +921,7 @@ def test_bump_command_prerelease_scheme_via_config( # PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE util.run_cli("bump", "--yes") - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is True + assert git.tag_exist("0.2.0") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: @@ -1017,18 +938,14 @@ def test_bump_command_prerelease_scheme_check_old_tags( tmp_commitizen_cfg_file = tmp_commitizen_project.join("pyproject.toml") util.run_cli("bump", "--prerelease", "alpha", "--yes") - - tag_exists = git.tag_exist("v0.2.0-a0") - assert tag_exists is True + assert git.tag_exist("v0.2.0-a0") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: assert "0.2.0-a0" in f.read() util.run_cli("bump", "--prerelease", "alpha") - - tag_exists = git.tag_exist("v0.2.0-a1") - assert tag_exists is True + assert git.tag_exist("v0.2.0-a1") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: @@ -1036,9 +953,7 @@ def test_bump_command_prerelease_scheme_check_old_tags( # PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE util.run_cli("bump") - - tag_exists = git.tag_exist("v0.2.0") - assert tag_exists is True + assert git.tag_exist("v0.2.0") is True for version_file in [tmp_version_file, tmp_commitizen_cfg_file]: with open(version_file) as f: @@ -1057,11 +972,8 @@ def test_bump_command_prerelease_scheme_check_old_tags( ) def test_bump_with_plugin(util: UtilFixture, message: str, expected_tag: str): util.create_file_and_commit(message) - util.run_cli("--name", "cz_semver", "bump", "--yes") - - tag_exists = git.tag_exist(expected_tag) - assert tag_exists is True + assert git.tag_exist(expected_tag) is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -1078,11 +990,8 @@ def test_bump_with_major_version_zero_with_plugin( util: UtilFixture, message: str, expected_tag: str ): util.create_file_and_commit(message) - util.run_cli("--name", "cz_semver", "bump", "--yes", "--major-version-zero") - - tag_exists = git.tag_exist(expected_tag) - assert tag_exists is True + assert git.tag_exist(expected_tag) is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -1099,7 +1008,7 @@ def test_bump_command_version_type_deprecation(util: UtilFixture): "semver", ) - assert git.tag_exist("0.2.0-a0") + assert git.tag_exist("0.2.0-a0") is True @pytest.mark.usefixtures("tmp_commitizen_project") @@ -1118,7 +1027,7 @@ def test_bump_command_version_scheme_priority_over_version_type(util: UtilFixtur "pep440", ) - assert git.tag_exist("0.2.0a0") + assert git.tag_exist("0.2.0a0") is True @pytest.mark.parametrize( @@ -1169,8 +1078,7 @@ def test_bump_template_option_precedence( args.append("0.1.1") util.run_cli(*args) - out = changelog.read_text() - assert out == expected + assert changelog.read_text() == expected def test_bump_template_extras_precedence( @@ -1244,7 +1152,7 @@ def test_bump_template_extra_quotes( def test_bump_changelog_contains_increment_only( - tmp_commitizen_project, util: UtilFixture, capsys + tmp_commitizen_project: Path, util: UtilFixture, capsys: pytest.CaptureFixture ): """Issue 1024""" # Initialize commitizen up to v1.0.0 @@ -1275,7 +1183,7 @@ def test_bump_changelog_contains_increment_only( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next(util: UtilFixture, capsys): +def test_bump_get_next(util: UtilFixture, capsys: pytest.CaptureFixture): util.create_file_and_commit("feat: new file") with pytest.raises(DryRunExit): @@ -1283,13 +1191,13 @@ def test_bump_get_next(util: UtilFixture, capsys): out, _ = capsys.readouterr() assert "0.2.0" in out - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is False + assert git.tag_exist("0.2.0") is False @pytest.mark.usefixtures("tmp_commitizen_project") -def test_bump_get_next_update_changelog_on_bump(util: UtilFixture, capsys, config_path): +def test_bump_get_next_update_changelog_on_bump( + util: UtilFixture, capsys: pytest.CaptureFixture, config_path: Path +): util.create_file_and_commit("feat: new file") with open(config_path, "a", encoding="utf-8") as fp: fp.write("update_changelog_on_bump = true\n") @@ -1299,9 +1207,7 @@ def test_bump_get_next_update_changelog_on_bump(util: UtilFixture, capsys, confi out, _ = capsys.readouterr() assert "0.2.0" in out - - tag_exists = git.tag_exist("0.2.0") - assert tag_exists is False + assert git.tag_exist("0.2.0") is False @pytest.mark.usefixtures("tmp_commitizen_project") @@ -1416,7 +1322,7 @@ def test_bump_detect_legacy_tags_from_scm( util.run_cli("bump", "--increment", "patch", "--changelog") - assert git.tag_exist("v0.4.3") + assert git.tag_exist("v0.4.3") is True def test_bump_warn_but_dont_fail_on_invalid_tags( @@ -1446,7 +1352,7 @@ def test_bump_warn_but_dont_fail_on_invalid_tags( _, err = capsys.readouterr() assert err.count("Invalid version tag: '0.4.3.deadbeaf'") == 1 - assert git.tag_exist("0.4.3") + assert git.tag_exist("0.4.3") is True def test_is_initial_tag(mocker: MockFixture, tmp_commitizen_project, util: UtilFixture): diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index 08a2b6cf78..dc97852144 100644 --- a/tests/commands/test_changelog_command.py +++ b/tests/commands/test_changelog_command.py @@ -30,6 +30,25 @@ from tests.utils import UtilFixture +@pytest.fixture +def changelog_jinja_file(tmp_project_root: Path) -> Path: + return tmp_project_root / "changelog.jinja" + + +@pytest.fixture +def changelog_tpl( + tmp_project_root: Path, any_changelog_format: ChangelogFormat +) -> Path: + return tmp_project_root / any_changelog_format.template + + +@pytest.fixture +def changelog_file( + tmp_project_root: Path, any_changelog_format: ChangelogFormat +) -> Path: + return tmp_project_root / any_changelog_format.default_changelog_file + + @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_from_version_zero_point_two( capsys: pytest.CaptureFixture, @@ -391,21 +410,14 @@ def test_changelog_multiple_incremental_do_not_add_new_lines( util: UtilFixture, ): """Test for bug https://github.com/commitizen-tools/commitizen/issues/192""" - util.create_file_and_commit("feat: add new output") - - util.run_cli("changelog", "--incremental") - - util.create_file_and_commit("fix: output glitch") - - util.run_cli("changelog", "--incremental") - - util.create_file_and_commit("fix: no more explosions") - - util.run_cli("changelog", "--incremental") - - util.create_file_and_commit("feat: add more stuff") - - util.run_cli("changelog", "--incremental") + for commit_message in [ + "feat: add new output", + "fix: output glitch", + "fix: no more explosions", + "feat: add more stuff", + ]: + util.create_file_and_commit(commit_message) + util.run_cli("changelog", "--incremental") with open(changelog_path, encoding="utf-8") as f: out = f.read() @@ -415,28 +427,24 @@ def test_changelog_multiple_incremental_do_not_add_new_lines( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_incremental_newline_separates_new_content_from_old( - changelog_path: str, util: UtilFixture + changelog_path: str, + util: UtilFixture, + file_regression: FileRegressionFixture, ): """Test for https://github.com/commitizen-tools/commitizen/issues/509""" with open(changelog_path, "w", encoding="utf-8") as f: f.write("Pre-existing content that should be kept\n") util.create_file_and_commit("feat: add more cat videos") - util.run_cli("changelog", "--incremental") - with open(changelog_path, encoding="utf-8") as f: out = f.read() - assert ( - out - == "Pre-existing content that should be kept\n\n## Unreleased\n\n### Feat\n\n- add more cat videos\n" - ) + file_regression.check(out, extension=".md") def test_changelog_without_revision(tmp_commitizen_project, util: UtilFixture): - changelog_file = tmp_commitizen_project.join("CHANGELOG.md") - changelog_file.write( + tmp_commitizen_project.join("CHANGELOG.md").write( """ # Unreleased @@ -444,6 +452,14 @@ def test_changelog_without_revision(tmp_commitizen_project, util: UtilFixture): """ ) + # No revision + with pytest.raises(NoRevisionError): + util.run_cli("changelog", "--incremental") + + util.create_file_and_commit("feat: new file") + util.create_tag("2.0.0") + + # With different tag name and changelog content with pytest.raises(NoRevisionError): util.run_cli("changelog", "--incremental") @@ -455,64 +471,34 @@ def test_changelog_incremental_with_revision(util: UtilFixture): util.run_cli("changelog", "--incremental", "0.2.0") -def test_changelog_with_different_tag_name_and_changelog_content( - tmp_commitizen_project, util: UtilFixture -): - changelog_file = tmp_commitizen_project.join("CHANGELOG.md") - changelog_file.write( - """ - # Unreleased - - ## v1.0.0 - """ - ) - util.create_file_and_commit("feat: new file") - util.create_tag("2.0.0") - - with pytest.raises(NoRevisionError): - util.run_cli("changelog", "--incremental") - - @pytest.mark.usefixtures("chdir") def test_changelog_in_non_git_project(util: UtilFixture): with pytest.raises(NotAGitProjectError): util.run_cli("changelog", "--incremental") -@pytest.mark.usefixtures("tmp_commitizen_project") -def test_breaking_change_content_v1_beta( - capsys: pytest.CaptureFixture, - file_regression: FileRegressionFixture, - util: UtilFixture, -): - commit_message = ( +@pytest.mark.parametrize( + "commit_message", + [ "feat(users): email pattern corrected\n\n" "BREAKING CHANGE: migrate by renaming user to users\n\n" - "footer content" - ) - util.create_file_and_commit(commit_message) - with pytest.raises(DryRunExit): - util.run_cli("changelog", "--dry-run") - out, _ = capsys.readouterr() - file_regression.check(out, extension=".md") - - + "footer content", + "feat(users): email pattern corrected\n\n" + "body content\n\n" + "BREAKING CHANGE: migrate by renaming user to users", + ], +) @pytest.mark.usefixtures("tmp_commitizen_project") -def test_breaking_change_content_v1( +def test_breaking_change_content_v1_beta( capsys: pytest.CaptureFixture, file_regression: FileRegressionFixture, util: UtilFixture, + commit_message: str, ): - commit_message = ( - "feat(users): email pattern corrected\n\n" - "body content\n\n" - "BREAKING CHANGE: migrate by renaming user to users" - ) util.create_file_and_commit(commit_message) with pytest.raises(DryRunExit): util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() - file_regression.check(out, extension=".md") @@ -803,9 +789,7 @@ def test_changelog_incremental_with_merge_prerelease( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_changelog_with_filename_as_empty_string( - changelog_path: str, config_path: str, util: UtilFixture -): +def test_changelog_with_filename_as_empty_string(config_path: str, util: UtilFixture): with open(config_path, "a", encoding="utf-8") as f: f.write("changelog_file = true\n") @@ -928,7 +912,7 @@ def test_changelog_multiple_matching_tags( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_from_rev_range_default_tag_format( - config_path: str, changelog_path: str, util: UtilFixture + changelog_path: str, util: UtilFixture ): """Checks that rev_range is calculated with the default (None) tag format""" # create commit and tag @@ -1013,7 +997,6 @@ def test_changelog_from_rev_version_range_with_legacy_tags( file_regression: FileRegressionFixture, util: UtilFixture, ): - changelog = Path(changelog_path) Path(config_path).write_text( "\n".join( [ @@ -1036,7 +1019,7 @@ def test_changelog_from_rev_version_range_with_legacy_tags( util.create_tag("legacy-0.4.0") util.run_cli("changelog", "0.2.0..0.4.0") - file_regression.check(changelog.read_text(), extension=".md") + file_regression.check(Path(changelog_path).read_text(), extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") @@ -1081,7 +1064,6 @@ def test_changelog_from_rev_version_with_big_range_from_arg( def test_changelog_from_rev_latest_version_dry_run( capsys: pytest.CaptureFixture, config_path: str, - changelog_path: str, file_regression: FileRegressionFixture, util: UtilFixture, ): @@ -1107,7 +1089,11 @@ def test_changelog_from_rev_latest_version_dry_run( @pytest.mark.usefixtures("tmp_commitizen_project") -def test_invalid_subject_is_skipped(capsys: pytest.CaptureFixture, util: UtilFixture): +def test_invalid_subject_is_skipped( + capsys: pytest.CaptureFixture, + file_regression: FileRegressionFixture, + util: UtilFixture, +): """Fix #510""" non_conformant_commit_title = ( "Merge pull request #487 from manang/master\n\n" @@ -1119,7 +1105,7 @@ def test_invalid_subject_is_skipped(capsys: pytest.CaptureFixture, util: UtilFix util.run_cli("changelog", "--dry-run") out, _ = capsys.readouterr() - assert out == ("## Unreleased\n\n### Feat\n\n- a new world\n\n") + file_regression.check(out, extension=".md") @pytest.mark.usefixtures("tmp_commitizen_project") @@ -1170,10 +1156,8 @@ def test_empty_commit_list(mocker: MockFixture, util: UtilFixture): @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2022-02-13") def test_changelog_prerelease_rev_with_use_scheme_semver( - mocker: MockFixture, capsys: pytest.CaptureFixture, config_path: str, - changelog_path: str, file_regression: FileRegressionFixture, util: UtilFixture, ): @@ -1190,27 +1174,23 @@ def test_changelog_prerelease_rev_with_use_scheme_semver( util.run_cli("bump", "--yes", "--prerelease", "alpha") capsys.readouterr() - tag_exists = git.tag_exist("0.3.0-a0") - assert tag_exists is True + assert git.tag_exist("0.3.0-a0") with pytest.raises(DryRunExit): util.run_cli("changelog", "0.3.0-a0", "--dry-run") out, _ = capsys.readouterr() - file_regression.check(out, extension=".md") util.run_cli("bump", "--yes", "--prerelease", "alpha") capsys.readouterr() - tag_exists = git.tag_exist("0.3.0-a1") - assert tag_exists is True + assert git.tag_exist("0.3.0-a1") with pytest.raises(DryRunExit): util.run_cli("changelog", "0.3.0-a1", "--dry-run") out, _ = capsys.readouterr() - file_regression.check(out, extension=".second-prerelease.md") @@ -1269,26 +1249,24 @@ def test_changelog_from_current_version_tag_with_nonversion_tag( write_patch = mocker.patch("commitizen.commands.changelog.out.write") - changelog = Changelog( - config, - { - "dry_run": True, - "incremental": False, - "unreleased_version": None, - "rev_range": "2.0.0", - }, - ) - with pytest.raises(DryRunExit): - changelog() - - full_changelog = "\ + Changelog( + config, + { + "dry_run": True, + "incremental": False, + "unreleased_version": None, + "rev_range": "2.0.0", + }, + )() + + write_patch.assert_called_with( + "\ ## 2.0.0 (2022-02-13)\n\n\ ### Feat\n\n\ - commit 2\n\ - commit 1\n" - - write_patch.assert_called_with(full_changelog) + ) @pytest.mark.parametrize( @@ -1302,23 +1280,21 @@ def test_changelog_from_current_version_tag_with_nonversion_tag( ), ) def test_changelog_template_option_precedence( - mocker: MockFixture, tmp_commitizen_project: Path, - any_changelog_format: ChangelogFormat, arg: str, cfg: str, expected: str, util: UtilFixture, + changelog_file: Path, + changelog_tpl: Path, ): project_root = Path(tmp_commitizen_project) cfg_template = project_root / "changelog.cfg" cmd_template = project_root / "changelog.cmd" - default_template = project_root / any_changelog_format.template - changelog = project_root / any_changelog_format.default_changelog_file cfg_template.write_text("from config") cmd_template.write_text("from cmd") - default_template.write_text("default") + changelog_tpl.write_text("default") util.create_file_and_commit("feat: new file") @@ -1339,26 +1315,22 @@ def test_changelog_template_option_precedence( testargs.append(arg) util.run_cli(*testargs) - out = changelog.read_text() - assert out == expected + assert changelog_file.read_text() == expected def test_changelog_template_extras_precedence( - mocker: MockFixture, - tmp_commitizen_project: Path, + changelog_tpl: Path, mock_plugin: BaseCommitizen, - any_changelog_format: ChangelogFormat, + pyproject: Path, + changelog_file: Path, util: UtilFixture, ): - project_root = Path(tmp_commitizen_project) - changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("{{first}} - {{second}} - {{third}}") mock_plugin.template_extras = dict( first="from-plugin", second="from-plugin", third="from-plugin" ) - pyproject = project_root / "pyproject.toml" pyproject.write_text( dedent( """\ @@ -1372,17 +1344,14 @@ def test_changelog_template_extras_precedence( ) util.create_file_and_commit("feat: new file") - util.run_cli("changelog", "--extra", "first=from-command") - changelog = project_root / any_changelog_format.default_changelog_file - assert changelog.read_text() == "from-command - from-config - from-plugin" + assert changelog_file.read_text() == "from-command - from-config - from-plugin" @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2021-06-11") def test_changelog_only_tag_matching_tag_format_included_prefix( - mocker: MockFixture, changelog_path: Path, config_path: Path, util: UtilFixture, @@ -1406,7 +1375,6 @@ def test_changelog_only_tag_matching_tag_format_included_prefix( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_only_tag_matching_tag_format_included_prefix_sep( - mocker: MockFixture, changelog_path: Path, config_path: Path, util: UtilFixture, @@ -1484,7 +1452,6 @@ def test_changelog_only_tag_matching_tag_format_included_suffix_sep( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_legacy_tags( - mocker: MockFixture, changelog_path: Path, config_path: Path, util: UtilFixture, @@ -1519,7 +1486,6 @@ def test_changelog_legacy_tags( @pytest.mark.usefixtures("tmp_commitizen_project") @pytest.mark.freeze_time("2024-11-18") def test_changelog_incremental_change_tag_format( - mocker: MockFixture, changelog_path: Path, config_path: Path, file_regression: FileRegressionFixture, @@ -1563,7 +1529,6 @@ def test_changelog_incremental_change_tag_format( @pytest.mark.usefixtures("tmp_commitizen_project") def test_changelog_ignored_tags( - mocker: MockFixture, changelog_path: Path, config_path: Path, capsys: pytest.CaptureFixture, @@ -1588,29 +1553,27 @@ def test_changelog_ignored_tags( util.create_file_and_commit("feat: another new file") util.create_tag("not-ignored") util.run_cli("bump", "--changelog", "--yes") - out = open(changelog_path).read() - _, err = capsys.readouterr() + with open(changelog_path) as f: + out = f.read() assert "## ignore-0.1.0" not in out - assert "Invalid version tag: 'ignore-0.1.0'" not in err assert "## ignored" not in out - assert "Invalid version tag: 'ignored'" not in err assert "## not-ignored" not in out - assert "Invalid version tag: 'not-ignored'" in err assert "## v0.3.0" in out + + _, err = capsys.readouterr() + assert "Invalid version tag: 'ignore-0.1.0'" not in err + assert "Invalid version tag: 'ignored'" not in err + assert "Invalid version tag: 'not-ignored'" in err assert "Invalid version tag: 'v0.3.0'" not in err def test_changelog_template_extra_quotes( - tmp_commitizen_project: Path, - any_changelog_format: ChangelogFormat, + changelog_tpl: Path, + changelog_file: Path, util: UtilFixture, ): - project_root = Path(tmp_commitizen_project) - changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("{{first}} - {{second}} - {{third}}") - util.create_file_and_commit("feat: new file") - util.run_cli( "changelog", "-e", @@ -1621,99 +1584,80 @@ def test_changelog_template_extra_quotes( 'third="double quotes"', ) - changelog = project_root / any_changelog_format.default_changelog_file - assert changelog.read_text() == "no-quote - single quotes - double quotes" + assert changelog_file.read_text() == "no-quote - single quotes - double quotes" @pytest.mark.parametrize( "extra, expected", ( pytest.param("key=value=", "value=", id="2-equals"), - pytest.param("key==value", "=value", id="2-consecutives-equals"), + pytest.param("key==value", "=value", id="2-consecutive-equals"), pytest.param("key==value==", "=value==", id="multiple-equals"), ), ) def test_changelog_template_extra_weird_but_valid( - tmp_commitizen_project: Path, - any_changelog_format: ChangelogFormat, + changelog_tpl: Path, + changelog_file: Path, extra: str, expected: str, util: UtilFixture, ): - project_root = Path(tmp_commitizen_project) - changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("{{key}}") - util.create_file_and_commit("feat: new file") - util.run_cli("changelog", "-e", extra) - changelog = project_root / any_changelog_format.default_changelog_file - assert changelog.read_text() == expected + assert changelog_file.read_text() == expected @pytest.mark.parametrize("extra", ("no-equal", "", "=no-key")) def test_changelog_template_extra_bad_format( - tmp_commitizen_project: Path, - any_changelog_format: ChangelogFormat, + changelog_tpl: Path, extra: str, util: UtilFixture, ): - project_root = Path(tmp_commitizen_project) - changelog_tpl = project_root / any_changelog_format.template changelog_tpl.write_text("") - util.create_file_and_commit("feat: new file") - with pytest.raises(InvalidCommandArgumentError): util.run_cli("changelog", "-e", extra) def test_export_changelog_template_from_default( - tmp_commitizen_project: Path, any_changelog_format: ChangelogFormat, util: UtilFixture, + changelog_jinja_file: Path, repo_root: Path, ): - project_root = Path(tmp_commitizen_project) - target = project_root / "changelog.jinja" src = repo_root / "commitizen" / "templates" / any_changelog_format.template - util.run_cli("changelog", "--export-template", str(target)) + util.run_cli("changelog", "--export-template", str(changelog_jinja_file)) - assert target.exists() - assert target.read_text() == src.read_text() + assert changelog_jinja_file.exists() + assert changelog_jinja_file.read_text() == src.read_text() def test_export_changelog_template_from_plugin( - mocker: MockFixture, - tmp_commitizen_project: Path, + changelog_jinja_file: Path, mock_plugin: BaseCommitizen, changelog_format: ChangelogFormat, tmp_path: Path, util: UtilFixture, ): - project_root = Path(tmp_commitizen_project) - target = project_root / "changelog.jinja" src = tmp_path / changelog_format.template tpl = "I am a custom template" src.write_text(tpl) mock_plugin.template_loader = FileSystemLoader(tmp_path) - util.run_cli("changelog", "--export-template", str(target)) + util.run_cli("changelog", "--export-template", str(changelog_jinja_file)) - assert target.exists() - assert target.read_text() == tpl + assert changelog_jinja_file.exists() + assert changelog_jinja_file.read_text() == tpl def test_export_changelog_template_fails_when_template_has_no_filename( mocker: MockFixture, - tmp_commitizen_project: Path, + changelog_jinja_file: Path, util: UtilFixture, ): - project_root = Path(tmp_commitizen_project) - target = project_root / "changelog.jinja" - # Mock a template object with no filename class FakeTemplate: filename = None @@ -1724,7 +1668,7 @@ class FakeTemplate: ) with pytest.raises(NotAllowed) as exc_info: - util.run_cli("changelog", "--export-template", str(target)) + util.run_cli("changelog", "--export-template", str(changelog_jinja_file)) - assert not target.exists() + assert not changelog_jinja_file.exists() assert "Template filename is not set" in str(exc_info.value) diff --git a/tests/commands/test_changelog_command/test_breaking_change_content_v1_beta.md b/tests/commands/test_changelog_command/test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_n_nfooter_content_.md similarity index 100% rename from tests/commands/test_changelog_command/test_breaking_change_content_v1_beta.md rename to tests/commands/test_changelog_command/test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_n_nfooter_content_.md diff --git a/tests/commands/test_changelog_command/test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nbody_content_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_.md b/tests/commands/test_changelog_command/test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nbody_content_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_.md new file mode 100644 index 0000000000..c4809739a9 --- /dev/null +++ b/tests/commands/test_changelog_command/test_breaking_change_content_v1_beta_feat_users___email_pattern_corrected_n_nbody_content_n_nBREAKING_CHANGE__migrate_by_renaming_user_to_users_.md @@ -0,0 +1,10 @@ +## Unreleased + +### BREAKING CHANGE + +- migrate by renaming user to users + +### Feat + +- **users**: email pattern corrected + diff --git a/tests/commands/test_changelog_command/test_changelog_incremental_newline_separates_new_content_from_old.md b/tests/commands/test_changelog_command/test_changelog_incremental_newline_separates_new_content_from_old.md new file mode 100644 index 0000000000..788105a3f6 --- /dev/null +++ b/tests/commands/test_changelog_command/test_changelog_incremental_newline_separates_new_content_from_old.md @@ -0,0 +1,7 @@ +Pre-existing content that should be kept + +## Unreleased + +### Feat + +- add more cat videos diff --git a/tests/commands/test_changelog_command/test_invalid_subject_is_skipped.md b/tests/commands/test_changelog_command/test_invalid_subject_is_skipped.md new file mode 100644 index 0000000000..d24ea7ba7c --- /dev/null +++ b/tests/commands/test_changelog_command/test_invalid_subject_is_skipped.md @@ -0,0 +1,6 @@ +## Unreleased + +### Feat + +- a new world + diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index e766524139..8398e784bc 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -119,7 +119,7 @@ def test_init_without_choosing_tag(config: BaseConfig, mocker: MockFixture, tmpd commands.Init(config)() -@pytest.fixture(scope="function") +@pytest.fixture def pre_commit_installed(mocker: MockFixture): # Assume the `pre-commit` is installed mocker.patch( diff --git a/tests/conftest.py b/tests/conftest.py index 9b4c033e5b..bcafc09267 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -72,7 +72,7 @@ def chdir(tmp_path: Path) -> Iterator[Path]: os.chdir(cwd) -@pytest.fixture(scope="function") +@pytest.fixture def tmp_git_project(tmpdir): with tmpdir.as_cwd(): cmd.run("git init") @@ -80,7 +80,7 @@ def tmp_git_project(tmpdir): yield tmpdir -@pytest.fixture(scope="function") +@pytest.fixture def tmp_commitizen_project(tmp_git_project): tmp_commitizen_cfg_file = tmp_git_project.join("pyproject.toml") tmp_commitizen_cfg_file.write('[tool.commitizen]\nversion="0.1.0"\n') @@ -88,7 +88,17 @@ def tmp_commitizen_project(tmp_git_project): yield tmp_git_project -@pytest.fixture(scope="function") +@pytest.fixture +def tmp_project_root(tmp_commitizen_project) -> Path: + return Path(tmp_commitizen_project) + + +@pytest.fixture +def pyproject(tmp_project_root: Path) -> Path: + return tmp_project_root / "pyproject.toml" + + +@pytest.fixture def tmp_commitizen_project_initial(tmp_git_project, util: UtilFixture): def _initial( config_extra: str | None = None, @@ -124,7 +134,7 @@ def _get_gpg_keyid(signer_mail): return _m.group(1) if _m else None -@pytest.fixture(scope="function") +@pytest.fixture def tmp_commitizen_project_with_gpg(tmp_commitizen_project): # create a temporary GPGHOME to store a temporary keyring. # Home path must be less than 104 characters @@ -148,14 +158,14 @@ def tmp_commitizen_project_with_gpg(tmp_commitizen_project): yield tmp_commitizen_project -@pytest.fixture() +@pytest.fixture def config(): _config = BaseConfig() _config.settings.update({"name": defaults.DEFAULT_SETTINGS["name"]}) return _config -@pytest.fixture() +@pytest.fixture def config_path() -> str: return os.path.join(os.getcwd(), "pyproject.toml") @@ -241,7 +251,7 @@ def info(self) -> str: return "" -@pytest.fixture() +@pytest.fixture def use_cz_semver(mocker): new_cz = {**registry, "cz_semver": SemverCommitizen} mocker.patch.dict("commitizen.cz.registry", new_cz) diff --git a/tests/test_bump_update_version_in_files.py b/tests/test_bump_update_version_in_files.py index 5fb812f19f..2cc464e8f1 100644 --- a/tests/test_bump_update_version_in_files.py +++ b/tests/test_bump_update_version_in_files.py @@ -26,32 +26,32 @@ def fixture(source: str, destination: str) -> Path: return fixture -@pytest.fixture(scope="function") +@pytest.fixture def commitizen_config_file(sample_file: SampleFileFixture) -> Path: return sample_file("sample_pyproject.toml", "pyproject.toml") -@pytest.fixture(scope="function") +@pytest.fixture def python_version_file(sample_file: SampleFileFixture) -> Path: return sample_file("sample_version.py", "__version__.py") -@pytest.fixture(scope="function") +@pytest.fixture def inconsistent_python_version_file(sample_file: SampleFileFixture) -> Path: return sample_file("inconsistent_version.py", "__version__.py") -@pytest.fixture(scope="function") +@pytest.fixture def random_location_version_file(sample_file: SampleFileFixture) -> Path: return sample_file("sample_cargo.lock", "Cargo.lock") -@pytest.fixture(scope="function") +@pytest.fixture def version_repeated_file(sample_file: SampleFileFixture) -> Path: return sample_file("repeated_version_number.json", "package.json") -@pytest.fixture(scope="function") +@pytest.fixture def docker_compose_file(sample_file: SampleFileFixture) -> Path: return sample_file("sample_docker_compose.yaml", "docker-compose.yaml") @@ -70,21 +70,21 @@ def multiple_versions_to_update_poetry_lock( return sample_file(request.param, "pyproject.toml") -@pytest.fixture(scope="function") +@pytest.fixture def multiple_versions_increase_string(tmp_path: Path) -> str: tmp_file = tmp_path / "anyfile" tmp_file.write_text(MULTIPLE_VERSIONS_INCREASE_STRING) return str(tmp_file) -@pytest.fixture(scope="function") +@pytest.fixture def multiple_versions_reduce_string(tmp_path: Path) -> str: tmp_file = tmp_path / "anyfile" tmp_file.write_text(MULTIPLE_VERSIONS_REDUCE_STRING) return str(tmp_file) -@pytest.fixture(scope="function") +@pytest.fixture def version_files( commitizen_config_file: Path, python_version_file: Path, diff --git a/tests/test_changelog.py b/tests/test_changelog.py index bcf90b11da..0831bcc1ff 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -587,27 +587,25 @@ def changelog_content(data_dir: Path) -> str: def test_get_commit_tag_is_a_version(gitcommits, tags): commit = gitcommits[0] tag = git.GitTag(*TAGS[0]) - current_key = changelog.get_commit_tag(commit, tags) - assert current_key == tag + assert changelog.get_commit_tag(commit, tags) == tag def test_get_commit_tag_is_None(gitcommits, tags): commit = gitcommits[1] - current_key = changelog.get_commit_tag(commit, tags) - assert current_key is None + assert changelog.get_commit_tag(commit, tags) is None @pytest.mark.parametrize("test_input", TAGS) def test_valid_tag_included_in_changelog(test_input): tag = git.GitTag(*test_input) rules = changelog.TagRules() - assert rules.include_in_changelog(tag) + assert rules.include_in_changelog(tag) is True def test_invalid_tag_included_in_changelog(): tag = git.GitTag("not_a_version", "rev", "date") rules = changelog.TagRules() - assert not rules.include_in_changelog(tag) + assert rules.include_in_changelog(tag) is False COMMITS_TREE = ( @@ -1188,12 +1186,9 @@ def test_generate_tree_from_commits(gitcommits, tags, merge_prereleases): def test_generate_tree_from_commits_with_no_commits(tags): - gitcommits = [] parser = ConventionalCommitsCz.commit_parser changelog_pattern = ConventionalCommitsCz.bump_pattern - tree = changelog.generate_tree_from_commits( - gitcommits, tags, parser, changelog_pattern - ) + tree = changelog.generate_tree_from_commits([], tags, parser, changelog_pattern) assert tuple(tree) == ({"changes": {}, "date": "", "version": "Unreleased"},) From de24815cac9edde88ca0e64674e582e9c4a96873 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Mon, 19 Jan 2026 10:55:24 +0800 Subject: [PATCH 199/221] test(conftest): typo --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index bcafc09267..b1690ccab8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -59,7 +59,7 @@ def set_default_gitconfig() -> dict[str, str]: return { "user.name": "SIGNER", "user.email": SIGNER_MAIL, - "safe.cirectory": "*", + "safe.directory": "*", "init.defaultBranch": "master", } From 047c914f072a781c6daa1280f929f5a81a985690 Mon Sep 17 00:00:00 2001 From: Gaby Roch <gaby@g-roch.ch> Date: Thu, 22 Jan 2026 12:34:19 +0100 Subject: [PATCH 200/221] fix(pre-commit-hooks): remove magic constants on pre-push hook (#1815) * fix(pre-commit-hooks): remove magic constants on pre-push hook - Remove static reference to origin (work with other name) - now work when remote/HEAD isn't setted (e.g. on `git init .; git remote add origin git@...`) * fix(pre-commit-hooks): some `"` consistency in the file --- .pre-commit-hooks.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index c142634581..650f0acedb 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -19,7 +19,7 @@ the fact (e.g., pre-push or in CI) without an expensive check of the entire repository history. entry: cz check - args: [--rev-range, origin/HEAD..HEAD] + args: [--rev-range, "$PRE_COMMIT_TO_REF $PRE_COMMIT_FROM_REF"] always_run: true pass_filenames: false language: python From 5857050259653556030b6b1f19f53e8868a427f6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:34:44 +0000 Subject: [PATCH 201/221] =?UTF-8?q?bump:=20version=204.12.0=20=E2=86=92=20?= =?UTF-8?q?4.12.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 6 ++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e9c41fd360..2a7cc5672b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.12.0 # automatically updated by Commitizen + rev: v4.12.1 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index c81becb841..6c7b7598c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v4.12.1 (2026-01-22) + +### Fix + +- **pre-commit-hooks**: remove magic constants on pre-push hook (#1815) + ## v4.12.0 (2026-01-19) ### Feat diff --git a/commitizen/__version__.py b/commitizen/__version__.py index ade1e2b4ce..33111828cc 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.12.0" +__version__ = "4.12.1" diff --git a/pyproject.toml b/pyproject.toml index 976978f2cf..a4a13d1377 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.12.0" +version = "4.12.1" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index 81ed84d661..71951762ae 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.12.0" +version = "4.12.1" source = { editable = "." } dependencies = [ { name = "argcomplete" }, From 78d776955c9aa77e6ce98f26325413ff6ae7f287 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Mon, 19 Jan 2026 23:23:27 +0800 Subject: [PATCH 202/221] docs: add revision date plugin --- mkdocs.yml | 4 ++++ pyproject.toml | 6 ++++- uv.lock | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 328a601962..85205e2da0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -103,3 +103,7 @@ markdown_extensions: - name: mermaid class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format + +plugins: + - search + - git-revision-date-localized diff --git a/pyproject.toml b/pyproject.toml index a4a13d1377..855bfb6c72 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -121,7 +121,11 @@ linters = [ "prek>=0.2.28", ] -documentation = ["mkdocs>=1.4.2", "mkdocs-material>=9.1.6"] +documentation = [ + "mkdocs>=1.4.2", + "mkdocs-git-revision-date-localized-plugin>=1.5.0", + "mkdocs-material>=9.1.6", +] script = [ # for scripts/gen_cli_help_screenshots.py diff --git a/uv.lock b/uv.lock index 71951762ae..75732c7ac0 100644 --- a/uv.lock +++ b/uv.lock @@ -221,6 +221,7 @@ dev = [ { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "ipython", version = "9.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "mkdocs" }, + { name = "mkdocs-git-revision-date-localized-plugin" }, { name = "mkdocs-material" }, { name = "mypy" }, { name = "poethepoet" }, @@ -245,6 +246,7 @@ dev = [ ] documentation = [ { name = "mkdocs" }, + { name = "mkdocs-git-revision-date-localized-plugin" }, { name = "mkdocs-material" }, ] linters = [ @@ -294,6 +296,7 @@ base = [{ name = "poethepoet", specifier = ">=0.34.0" }] dev = [ { name = "ipython", specifier = ">=8.0" }, { name = "mkdocs", specifier = ">=1.4.2" }, + { name = "mkdocs-git-revision-date-localized-plugin", specifier = ">=1.5.0" }, { name = "mkdocs-material", specifier = ">=9.1.6" }, { name = "mypy", specifier = ">=1.16.0" }, { name = "poethepoet", specifier = ">=0.34.0" }, @@ -318,6 +321,7 @@ dev = [ ] documentation = [ { name = "mkdocs", specifier = ">=1.4.2" }, + { name = "mkdocs-git-revision-date-localized-plugin", specifier = ">=1.5.0" }, { name = "mkdocs-material", specifier = ">=9.1.6" }, ] linters = [ @@ -548,6 +552,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, ] +[[package]] +name = "gitdb" +version = "4.0.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "smmap" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684, upload-time = "2025-01-02T07:20:46.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794, upload-time = "2025-01-02T07:20:43.624Z" }, +] + +[[package]] +name = "gitpython" +version = "3.1.46" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gitdb" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/b5/59d16470a1f0dfe8c793f9ef56fd3826093fc52b3bd96d6b9d6c26c7e27b/gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f", size = 215371, upload-time = "2026-01-01T15:37:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058", size = 208620, upload-time = "2026-01-01T15:37:30.574Z" }, +] + [[package]] name = "identify" version = "2.6.16" @@ -908,6 +936,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, ] +[[package]] +name = "mkdocs-git-revision-date-localized-plugin" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "gitpython" }, + { name = "mkdocs" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/c5/1d3c4e6ddae6230b89d09105cb79de711655e3ebd6745f7a92efea0f5160/mkdocs_git_revision_date_localized_plugin-1.5.0.tar.gz", hash = "sha256:17345ccfdf69a1905dc96fb1070dce82d03a1eb6b0d48f958081a7589ce3c248", size = 460697, upload-time = "2025-10-31T16:11:34.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/51/fe0e3fdb16f6eed65c9459d12bae6a4e1f0bb4e2228cb037e7907b002678/mkdocs_git_revision_date_localized_plugin-1.5.0-py3-none-any.whl", hash = "sha256:933f9e35a8c135b113f21bb57610d82e9b7bcc71dd34fb06a029053c97e99656", size = 26153, upload-time = "2025-10-31T16:11:32.987Z" }, +] + [[package]] name = "mkdocs-material" version = "9.7.1" @@ -1468,6 +1511,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "smmap" +version = "5.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329, upload-time = "2025-01-02T07:14:40.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" }, +] + [[package]] name = "stack-data" version = "0.6.3" @@ -1649,6 +1701,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +] + [[package]] name = "urllib3" version = "2.6.2" From 94d66dedb9f501ecc081485e231e85cfee0a296c Mon Sep 17 00:00:00 2001 From: YU HAN-CHENG <boy19990222@gmail.com> Date: Sat, 31 Jan 2026 12:01:14 +0800 Subject: [PATCH 203/221] docs(READMD.md): add star history to README (#1824) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 余翰承 <hankyu@yuhanchengdeMacBook-Air.local> --- docs/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/README.md b/docs/README.md index 97cd2880d7..313d5494d2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -303,6 +303,11 @@ After installation, you can verify the completion is working by: For more detailed information about argcomplete configuration and troubleshooting, visit the [argcomplete documentation](https://kislyuk.github.io/argcomplete/). +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=commitizen-tools/commitizen)](https://star-history.com/#commitizen-tools/commitizen) + + ## Sponsors These are our cool sponsors! From 1eb8ffff6bc790e37a5f5dd96ef2a62f2d4ae88b Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 12:05:17 +0800 Subject: [PATCH 204/221] docs(github_actions): improve github action tutorial page (#1782) --- docs/tutorials/github_actions.md | 169 +++++++++++++++++++++---------- 1 file changed, 117 insertions(+), 52 deletions(-) diff --git a/docs/tutorials/github_actions.md b/docs/tutorials/github_actions.md index f15b62fbaa..c3b06336a9 100644 --- a/docs/tutorials/github_actions.md +++ b/docs/tutorials/github_actions.md @@ -1,26 +1,49 @@ ## Create a new release with GitHub Actions -### Automatic bumping of version +This guide shows you how to automatically bump versions, create changelogs, and publish releases using Commitizen in GitHub Actions. -To execute `cz bump` in your CI, and push the new commit and -the new tag, back to your master branch, we have to: +### Prerequisites -1. Create a personal access token. [Follow the instructions here](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line#creating-a-token). And copy the generated key -2. Create a secret called `PERSONAL_ACCESS_TOKEN`, with the copied key, by going to your - project repository and then `Settings > Secrets > Add new secret`. -3. In your repository create a new file `.github/workflows/bumpversion.yml` - with the following content. +Before setting up the workflow, you'll need: -!!! warning - If you use `GITHUB_TOKEN` instead of `PERSONAL_ACCESS_TOKEN`, the job won't trigger another workflow. It's like using `[skip ci]` in other CI's. +1. A personal access token with repository write permissions +2. Commitizen configured in your project (see [configuration documentation](../config/configuration_file.md)) -```yaml +### Automatic version bumping + +To automatically execute `cz bump` in your CI and push the new commit and tag back to your repository, follow these steps: + +#### Step 1: Create a personal access token + +1. Go to [GitHub Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens) +2. Click "Generate new token (classic)" +3. Give it a descriptive name (e.g., "Commitizen CI") +4. Select the `repo` scope to grant full repository access +5. Click "Generate token" and **copy the token immediately** (you won't be able to see it again) + +!!! warning "Important: Use Personal Access Token, not GITHUB_TOKEN" + If you use `GITHUB_TOKEN` instead of `PERSONAL_ACCESS_TOKEN`, the workflow won't trigger another workflow run. This is a GitHub security feature to prevent infinite loops. The `GITHUB_TOKEN` is treated like using `[skip ci]` in other CI systems. + +#### Step 2: Add the token as a repository secret + +1. Go to your repository on GitHub +2. Navigate to `Settings > Secrets and variables > Actions` +3. Click "New repository secret" +4. Name it `PERSONAL_ACCESS_TOKEN` +5. Paste the token you copied in Step 1 +6. Click "Add secret" + +#### Step 3: Create the workflow file + +Create a new file `.github/workflows/bumpversion.yml` in your repository with the following content: + +```yaml title=".github/workflows/bumpversion.yml" name: Bump version on: push: branches: - - master + - master # or 'main' if that's your default branch jobs: bump-version: @@ -29,7 +52,7 @@ jobs: name: "Bump version and create changelog with commitizen" steps: - name: Check out - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" fetch-depth: 0 @@ -39,62 +62,106 @@ jobs: github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} ``` -Push to master and that's it. +#### How it works + +- **Trigger**: The workflow runs on every push to the `master` branch (or `main` if you change it) +- **Conditional check**: The `if` condition prevents infinite loops by skipping the job if the commit message starts with `bump:` +- **Checkout**: Uses your personal access token to check out the repository with full history (`fetch-depth: 0`) +- **Bump**: The `commitizen-action` automatically: + - Determines the version increment based on your commit messages + - Updates version files (as configured in your `pyproject.toml` or other config) + - Creates a new git tag + - Generates/updates the changelog + - Pushes the commit and tag back to the repository + +Once you push this workflow file to your repository, it will automatically run on the next push to your default branch. + +Check out [commitizen-action](https://github.com/commitizen-tools/commitizen-action) for more details. ### Creating a GitHub release -You can modify the previous action. - -Add the variable `changelog_increment_filename` in the `commitizen-action`, specifying -where to output the content of the changelog for the newly created version. - -And then add a step using a GitHub action to create the release: `softprops/action-gh-release` - -Commitizen action creates an env variable called `REVISION`, containing the -newly created version. - -```yaml -- name: Create bump and changelog - uses: commitizen-tools/commitizen-action@master - with: - github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - changelog_increment_filename: body.md -- name: Release - uses: softprops/action-gh-release@v1 - with: - body_path: "body.md" - tag_name: ${{ env.REVISION }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +To automatically create a GitHub release when a new version is bumped, you can extend the workflow above. + +The `commitizen-action` creates an environment variable called `REVISION` containing the newly created version. You can use this to create a release with the changelog content. + +```yaml title=".github/workflows/bumpversion.yml" +name: Bump version + +on: + push: + branches: + - master # or 'main' if that's your default branch + +jobs: + bump-version: + if: "!startsWith(github.event.head_commit.message, 'bump:')" + runs-on: ubuntu-latest + name: "Bump version and create changelog with commitizen" + steps: + - name: Check out + uses: actions/checkout@v6 + with: + token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" + fetch-depth: 0 + - name: Create bump and changelog + uses: commitizen-tools/commitizen-action@master + with: + github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + changelog_increment_filename: body.md + - name: Release + uses: ncipollo/release-action@v1 + with: + tag: v${{ env.REVISION }} + bodyFile: "body.md" + skipIfReleaseExists: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` -### Publishing a python package +You can find the complete workflow in our repository at [bumpversion.yml](https://github.com/commitizen-tools/commitizen/blob/master/.github/workflows/bumpversion.yml). -Once the new tag is created, triggering an automatic publish command would be desired. +### Publishing a Python package -In order to do so, the credential needs to be added with the information of our PyPI account. +After a new version tag is created by the bump workflow, you can automatically publish your package to PyPI. -Instead of using username and password, we suggest using [api token](https://pypi.org/help/#apitoken) generated from PyPI. +#### Step 1: Create a PyPI API token -After generate api token, use the token as the PyPI password and `__token__` as the username. +1. Go to [PyPI Account Settings](https://pypi.org/manage/account/) +2. Scroll to the "API tokens" section +3. Click "Add API token" +4. Give it a name (e.g., "GitHub Actions") +5. Set the scope (project-specific or account-wide) +6. Click "Add token" and **copy the token immediately** -Go to `Settings > Secrets > Add new secret` and add the secret: `PYPI_PASSWORD`. +!!! tip "Using trusted publishing (recommended)" + Instead of API tokens, consider using [PyPI trusted publishing](https://docs.pypi.org/trusted-publishers/) with OpenID Connect (OIDC). This is more secure as it doesn't require storing secrets. The `pypa/gh-action-pypi-publish` action supports trusted publishing when you configure it in your PyPI project settings. -Create a file in `.github/workflows/pythonpublish.yaml` with the following content: +#### Step 2: Add the token as a repository secret -```yaml +1. Go to your repository on GitHub +2. Navigate to `Settings > Secrets and variables > Actions` +3. Click "New repository secret" +4. Name it `PYPI_PASSWORD` +5. Paste the PyPI token +6. Click "Add secret" + +#### Step 3: Create the publish workflow + +Create a new file `.github/workflows/pythonpublish.yml` that triggers on tag pushes: + +```yaml title=".github/workflows/pythonpublish.yml" name: Upload Python Package on: push: tags: - - "*" # Will trigger for every tag, alternative: 'v*' + - "*" # Will trigger for every tag, alternative: 'v*' jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set up Python @@ -118,9 +185,7 @@ jobs: run: poetry publish --build ``` -Notice that we are using poetry to publish the package. - - -You can also use [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) to publish your package. +This workflow uses Poetry to build and publish the package. You can find the complete workflow in our repository at [pythonpublish.yml](https://github.com/commitizen-tools/commitizen/blob/master/.github/workflows/pythonpublish.yml). -Push the changes and that's it. +!!! note "Alternative publishing methods" + You can also use [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) or other build tools like `setuptools`, `flit`, or `hatchling` to publish your package. From 5b02acfc1652bd516ae8901ba2cc858047aa1a9b Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 12:05:41 +0800 Subject: [PATCH 205/221] docs(changelog): fix minor mistakes in changelog documentation, improve fluency (#1792) --- docs/commands/changelog.md | 75 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/docs/commands/changelog.md b/docs/commands/changelog.md index 3f2425a51f..da40eb6fbe 100644 --- a/docs/commands/changelog.md +++ b/docs/commands/changelog.md @@ -1,6 +1,6 @@ ## About -This command will generate a changelog following the committing rules established. +Generates a changelog following the committing rules established. !!! tip To create the changelog automatically on bump, add the setting [update_changelog_on_bump](../config/bump.md#update_changelog_on_bump) @@ -20,7 +20,7 @@ This command will generate a changelog following the committing rules establishe # Generate full changelog cz changelog -# or use the alias +# Or use the alias cz ch # Get the changelog for the given version @@ -30,7 +30,7 @@ cz changelog 0.3.0 --dry-run cz changelog 0.3.0..0.4.0 --dry-run ``` -## Constrains +## Constraints Changelog generation is constrained only to **markdown** files. @@ -46,30 +46,30 @@ These are the variables used by the changelog generator. - **<scope>**: <message> ``` -It will create a full block like above per version found in the tags. -And it will create a list of the commits found. -The `change_type` and the `scope` are optional, they don't need to be provided, -but if your regex does, they will be rendered. +Creates a full block like above per version found in the tags, and a list of the commits found. +The `change_type` and `scope` are optional and don't need to be provided, +but if your regex parses them, they will be rendered. -The format followed by the changelog is the one from [keep a changelog][keepachangelog] +The format followed by the changelog is from [keep a changelog][keepachangelog] and the following variables are expected: | Variable | Description | Source | | ------------- | ---------------------------------------------------------------------------------------------- | -------------- | | `version` | Version number which should follow [semver][semver] | `tags` | -| `date` | Date in which the tag was created | `tags` | +| `date` | Date when the tag was created | `tags` | | `change_type` | The group where the commit belongs to, this is optional. Example: fix | `commit regex` | -| `message`\* | Information extracted from the commit message | `commit regex` | +| `message` | Information extracted from the commit message | `commit regex` | | `scope` | Contextual information. Should be parsed using the regex from the message, it will be **bold** | `commit regex` | -| `breaking` | Whether is a breaking change or not | `commit regex` | +| `breaking` | Whether it is a breaking change or not | `commit regex` | -- **required**: is the only one required to be parsed by the regex +!!! note + `message` is the only variable required to be parsed by the regex. ## Command line options ### `--extras` -Provides your own changelog extra variables by using the `extras` settings or the `--extra/-e` parameter. +Provide your own changelog extra variables by using the `extras` settings or the `--extra/-e` parameter. ```bash cz changelog --extra key=value -e short="quoted value" @@ -77,9 +77,9 @@ cz changelog --extra key=value -e short="quoted value" ### `--file-name` -This value can be updated in the configuration file with the key `changelog_file` under `tools.commitizen` +This value can be updated in the configuration file with the key `changelog_file` under `tool.commitizen`. -Specify the name of the output file, remember that changelog only works with Markdown. +Specify the name of the output file. Note that changelog generation only works with Markdown files. ```bash cz changelog --file-name="CHANGES.md" @@ -87,27 +87,27 @@ cz changelog --file-name="CHANGES.md" ### `--incremental` -This flag can be set in the configuration file with the key `changelog_incremental` under `tools.commitizen` +This flag can be set in the configuration file with the key `changelog_incremental` under `tool.commitizen` Benefits: -- Build from the latest version found in changelog, this is useful if you have a different changelog and want to use commitizen +- Build from the latest version found in changelog. This is useful if you have an existing changelog and want to use commitizen to extend it. - Update unreleased area -- Allows users to manually touch the changelog without being rewritten. +- Allows users to manually edit the changelog without it being completely rewritten. ```bash cz changelog --incremental ``` ```toml -[tools.commitizen] +[tool.commitizen] # ... changelog_incremental = true ``` ### `--start-rev` -This value can be set in the configuration file with the key `changelog_start_rev` under `tools.commitizen` +This value can be set in the configuration file with the key `changelog_start_rev` under `tool.commitizen` Start from a given git rev to generate the changelog. Commits before that rev will not be considered. This is especially useful for long-running projects adopting conventional commits, where old commit messages might fail to be parsed for changelog generation. @@ -116,43 +116,43 @@ cz changelog --start-rev="v0.2.0" ``` ```toml -[tools.commitizen] +[tool.commitizen] # ... changelog_start_rev = "v0.2.0" ``` ### `--merge-prerelease` -This flag can be set in the configuration file with the key `changelog_merge_prerelease` under `tools.commitizen` +This flag can be set in the configuration file with the key `changelog_merge_prerelease` under `tool.commitizen` -Collects changes from prereleases into the next non-prerelease. This means that if you have a prerelease version, and then a normal release, the changelog will show the prerelease changes as part of the changes of the normal release. If not set, it will include prereleases in the changelog. +Collects changes from prereleases into the next non-prerelease version. If you have a prerelease version followed by a normal release, the changelog will show the prerelease changes as part of the normal release. If not set, prereleases will be included as separate entries in the changelog. ```bash cz changelog --merge-prerelease ``` ```toml -[tools.commitizen] +[tool.commitizen] # ... changelog_merge_prerelease = true ``` ### `--template` -Provides your own changelog jinja template by using the `template` settings or the `--template` parameter. +Provide your own changelog Jinja template by using the `template` settings or the `--template` parameter. + +```bash +cz changelog --template="path/to/template.j2" +``` ### `--unreleased-version` -There is usually a chicken and egg situation when automatically -bumping the version and creating the changelog. -If you bump the version first, you have no changelog, you have to -create it later, and it won't be included in -the release of the created version. +There is usually a chicken-and-egg situation when automatically bumping the version and creating the changelog: -If you create the changelog before bumping the version, then you -usually don't have the latest tag, and the _Unreleased_ title appears. +- If you bump the version first, you have no changelog yet, and it won't be included in the release of the created version. +- If you create the changelog before bumping the version, you usually don't have the latest tag, and the _Unreleased_ title appears. -By introducing `--unreleased-version` you can prevent this situation. +By using `--unreleased-version`, you can prevent this situation. Before bumping you can run: @@ -160,12 +160,11 @@ Before bumping you can run: cz changelog --unreleased-version="v1.0.0" ``` -Remember to use the tag instead of the raw version number +Remember to use the tag format instead of the raw version number. -For example if the format of your tag includes a `v` (`v1.0.0`), then you should use that, -if your tag is the same as the raw version, then ignore this. +For example, if your tag format includes a `v` prefix (e.g., `v1.0.0`), use that format. If your tag is the same as the raw version (e.g., `1.0.0`), use the raw version. -Alternatively you can directly bump the version and create the changelog by doing +Alternatively, you can directly bump the version and create the changelog by running: ```bash cz bump --changelog @@ -175,7 +174,7 @@ cz bump --changelog Supported hook methods: -- Per parsed message: Useful to add links +- Per parsed message: Useful to add links to commits or issues - End of changelog generation: Useful to send Slack or chat messages, or notify another department Read more about hooks in the [customization page][customization] From 0497ef20b8cbfb2f2bce865753f5861ad09333e4 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 12:07:30 +0800 Subject: [PATCH 206/221] docs(contributing): add pull request guideline and add notes about AI assisted contributions (#1778) --- .github/pull_request_template.md | 36 +++++++--- docs/{ => contributing}/contributing.md | 4 +- docs/{ => contributing}/contributing_tldr.md | 2 + docs/contributing/pull_request.md | 71 ++++++++++++++++++++ mkdocs.yml | 6 +- 5 files changed, 106 insertions(+), 13 deletions(-) rename docs/{ => contributing}/contributing.md (96%) rename docs/{ => contributing}/contributing_tldr.md (97%) create mode 100644 docs/contributing/pull_request.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 061dce44cb..87189d131c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,7 +9,19 @@ Please fill in the following content to let us know better about this change. ## Checklist -- [ ] I have read the [contributing guidelines](https://commitizen-tools.github.io/commitizen/contributing/) +- [ ] I have read the [contributing guidelines](https://commitizen-tools.github.io/commitizen/contributing/contributing) + +### Was generative AI tooling used to co-author this PR? + +<!-- +If generative AI tooling has been used in the process of authoring this PR, please change below checkbox to `[X]` followed by the name of the tool, uncomment the "Generated-by". +--> + +- [ ] Yes (please specify the tool below) + +<!-- +Generated-by: [Tool Name] following [the guidelines](http://commitizen-tools.github.io/commitizen/contributing/pull_request/#ai-assisted-contributions) +--> ### Code Changes @@ -23,25 +35,31 @@ Please fill in the following content to let us know better about this change. - [ ] Update the documentation for the changes ### Documentation Changes +<!-- You can skip this section if you are not making any documentation changes --> + - [ ] Run `uv run poe doc` locally to ensure the documentation pages renders correctly -- [ ] Check and fix any broken links (internal or external) in the documentation +- [ ] Check and fix any broken links (internal or external) -> When running `uv run poe doc`, any broken internal documentation links will be reported in the console output like this: -> -> ```text -> INFO - Doc file 'config.md' contains a link 'commands/bump.md#-post_bump_hooks', but the doc 'commands/bump.md' does not contain an anchor '#-post_bump_hooks'. -> ``` +<!-- +When running `uv run poe doc`, any broken internal documentation links will be reported in the console output like this: + +```text +INFO - Doc file 'config.md' contains a link 'commands/bump.md#-post_bump_hooks', but the doc 'commands/bump.md' does not contain an anchor '#-post_bump_hooks'. +``` +--> ## Expected Behavior <!-- A clear and concise description of what you expected to happen --> ## Steps to Test This Pull Request -<!-- Steps to reproduce the behavior: +<!-- +Steps to reproduce the behavior: 1. ... 2. ... -3. ... --> +3. ... +--> ## Additional Context diff --git a/docs/contributing.md b/docs/contributing/contributing.md similarity index 96% rename from docs/contributing.md rename to docs/contributing/contributing.md index 827dfc7ac2..446410533c 100644 --- a/docs/contributing.md +++ b/docs/contributing/contributing.md @@ -1,10 +1,10 @@ -## Contributing to Commitizen +# Contributing to Commitizen First, thank you for taking the time to contribute! 🎉 Your contributions help make Commitizen better for everyone. When contributing to Commitizen, we encourage you to: -1. First, check out the [issues](https://github.com/commitizen-tools/commitizen/issues) and [Features we won't add](features_wont_add.md) to see if there's already a discussion about the change you wish to make. +1. First, check out the [issues](https://github.com/commitizen-tools/commitizen/issues) and [Features we won't add](../features_wont_add.md) to see if there's already a discussion about the change you wish to make. 2. If there's no discussion, [create an issue](https://github.com/commitizen-tools/commitizen/issues/new) to discuss your proposed changes. 3. Follow our [development workflow](#development-workflow) and guidelines below. diff --git a/docs/contributing_tldr.md b/docs/contributing/contributing_tldr.md similarity index 97% rename from docs/contributing_tldr.md rename to docs/contributing/contributing_tldr.md index 91f49d1ca4..af350d2bb7 100644 --- a/docs/contributing_tldr.md +++ b/docs/contributing/contributing_tldr.md @@ -1,3 +1,5 @@ +# Contributing TL;DR + Feel free to send a PR to update this file if you find anything useful. 🙇 ## Environment diff --git a/docs/contributing/pull_request.md b/docs/contributing/pull_request.md new file mode 100644 index 0000000000..4682496b4c --- /dev/null +++ b/docs/contributing/pull_request.md @@ -0,0 +1,71 @@ +# Pull Request Guidelines + +This document outlines important guidelines to follow when creating a pull request. + +## Before Creating a Pull Request + +1. **Check Existing Issues**: Ensure there's a related issue or discussion for your changes. If not, create one first to discuss the proposed changes. +2. **Follow the Development Workflow**: Make sure you've followed all steps in the [contributing guidelines](contributing.md). + +## Making Changes + +When adding new code, match the existing coding style in the file you're modifying. Consistency within a file and throughout the project is crucial for maintainability. + +## Following PR Description Template Instructions + +The PR description template includes a checklist and specific requirements. Please: + +1. **Complete the Checklist**: Check off all applicable items before requesting review. +2. **Provide Clear Descriptions**: Clearly describe what the change does, expected behavior, and steps to test. +3. **Respond to Feedback**: Carefully read maintainer feedback and address all points raised. Ask for clarification if something is unclear. + +## AI-Assisted Contributions + +We welcome contributions that use AI tools for assistance, but we have strict quality standards to maintain code quality and avoid "AI spaghetti code." + +!!! note + Most of our new documentation changes are, of course, generated by AI, but we still need to review it and make sure it's correct. + +![when bro's code is filled with "🔥 🚀 💥 ❌ ✅"](https://images3.memedroid.com/images/UPLOADED78/69501f1c23cab.webp) + +### Guidelines for AI-Assisted PRs + +1. **Review and Refine**: Thoroughly review and understand all AI-generated code. Refactor to match our project's style and remove unnecessary complexity. +2. **Test Thoroughly**: Don't assume AI-generated code works—test it extensively with comprehensive test cases and manual testing when possible. +3. **Understand the Code**: You should be able to explain every line. If you don't understand something, learn about it or rewrite it. Maintainers may ask you to explain your code. +4. **Avoid Common Pitfalls**: + - Over-engineering (simplify when possible) + - Inconsistent style (ensure consistency with our standards) + - Unnecessary dependencies + - Copy-paste without adaptation + - Verbose or obvious comments +5. **Code Quality Still Matters**: AI assistance doesn't excuse poor code quality. All code must pass linting, type checking, and follow best practices. +6. **Be Transparent**: **Mention AI assistance in the PR description**. Code quality standards remain the same regardless of how the code was written. + +!!! warning "Consequences of Poor AI-Assisted Contributions" + Maintainers who identify low-quality AI-generated code or copy-pasted responses will have no choice but to close the related PRs. This adds unnecessary burden on maintainers and doesn't help the project. Additionally, the contributor's reputation is impacted as maintainers may lose confidence and might restrict the user from making further contributions. + +### What We Consider "AI Spaghetti" + +Red flags that may result in PR rejection or requests for significant refactoring: + +- Overly complex solutions when simpler ones exist +- Unnecessary abstractions or design patterns +- Code that's difficult to understand or maintain +- Missing or inadequate tests +- Copy-pasted code blocks that don't fit the project structure +- Excessive comments explaining obvious things + +**Remember**: If you use AI tools, you're still responsible for the quality of the final code. Use AI as a starting point, not a final solution. + +## Commenting on the PR + +When commenting on the PR: + +- Address the feedback points raised by maintainers +- Ask questions if something is unclear +- **Do not** just copy-paste AI-generated responses + - Maintainers want to see your thought process and understanding of the codebase + - Maintainers and other contributors can tell if you're just copying and pasting AI-generated responses + +Thank you for helping make Commitizen better! 🎉 diff --git a/mkdocs.yml b/mkdocs.yml index 85205e2da0..a38dcd276d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -83,8 +83,10 @@ nav: - "third-party-plugins/cz-legacy.md" - "third-party-plugins/cz-path.md" - "third-party-plugins/github-jira-conventional.md" - - Contributing: "contributing.md" - - Contributing TL;DR: "contributing_tldr.md" + - Contributing: + - "contributing/contributing_tldr.md" + - "contributing/contributing.md" + - "contributing/pull_request.md" - "history.md" - Resources: "external_links.md" From 0c53ecd7fdeb6e1b62ed739218fc6964b97b63b8 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 11:51:22 +0800 Subject: [PATCH 207/221] refactor(bump): fix unbounded variable type issue --- commitizen/commands/bump.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index f6637b5c74..affe2bd358 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -306,6 +306,7 @@ def __call__(self) -> None: ) updated_files: list[str] = [] + changelog_file_name = None dry_run = self.arguments["dry_run"] if self.changelog_flag: changelog_args = { @@ -318,12 +319,11 @@ def __call__(self) -> None: "during_version_bump": self.arguments["prerelease"] is None, } if self.changelog_to_stdout: - changelog_cmd = Changelog( - self.config, - {**changelog_args, "dry_run": True}, # type: ignore[typeddict-item] - ) try: - changelog_cmd() + Changelog( + self.config, + {**changelog_args, "dry_run": True}, # type: ignore[typeddict-item] + )() except DryRunExit: pass @@ -332,7 +332,8 @@ def __call__(self) -> None: {**changelog_args, "file_name": self.file_name}, # type: ignore[typeddict-item] ) changelog_cmd() - updated_files.append(changelog_cmd.file_name) + changelog_file_name = changelog_cmd.file_name + updated_files.append(changelog_file_name) # Do not perform operations over files or git. if dry_run: @@ -361,9 +362,7 @@ def __call__(self) -> None: new_tag_version=new_tag_version, message=message, increment=increment, - changelog_file_name=changelog_cmd.file_name - if self.changelog_flag - else None, + changelog_file_name=changelog_file_name, ) if self.arguments["files_only"]: @@ -419,9 +418,7 @@ def __call__(self) -> None: current_tag_version=new_tag_version, message=message, increment=increment, - changelog_file_name=changelog_cmd.file_name - if self.changelog_flag - else None, + changelog_file_name=changelog_file_name, ) # TODO: For v3 output this only as diagnostic and remove this if From e5de7e5027030e2701f1782a31fc348653833af7 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Tue, 6 Jan 2026 22:34:47 +0800 Subject: [PATCH 208/221] fix(cli): capitalize the first characters of help texts and fix minor grammar errors --- commitizen/cli.py | 203 +++++++++--------- ...ion_when_use_help_option_py_3_10_bump_.txt | 88 ++++---- ...hen_use_help_option_py_3_10_changelog_.txt | 40 ++-- ...on_when_use_help_option_py_3_10_check_.txt | 29 +-- ...n_when_use_help_option_py_3_10_commit_.txt | 29 +-- ..._when_use_help_option_py_3_10_example_.txt | 2 +- ...ion_when_use_help_option_py_3_10_info_.txt | 2 +- ...ion_when_use_help_option_py_3_10_init_.txt | 2 +- ...ption_when_use_help_option_py_3_10_ls_.txt | 2 +- ...n_when_use_help_option_py_3_10_schema_.txt | 2 +- ..._when_use_help_option_py_3_10_version_.txt | 16 +- ...ion_when_use_help_option_py_3_11_bump_.txt | 88 ++++---- ...hen_use_help_option_py_3_11_changelog_.txt | 40 ++-- ...on_when_use_help_option_py_3_11_check_.txt | 29 +-- ...n_when_use_help_option_py_3_11_commit_.txt | 29 +-- ..._when_use_help_option_py_3_11_example_.txt | 2 +- ...ion_when_use_help_option_py_3_11_info_.txt | 2 +- ...ion_when_use_help_option_py_3_11_init_.txt | 2 +- ...ption_when_use_help_option_py_3_11_ls_.txt | 2 +- ...n_when_use_help_option_py_3_11_schema_.txt | 2 +- ..._when_use_help_option_py_3_11_version_.txt | 16 +- ...ion_when_use_help_option_py_3_12_bump_.txt | 88 ++++---- ...hen_use_help_option_py_3_12_changelog_.txt | 40 ++-- ...on_when_use_help_option_py_3_12_check_.txt | 29 +-- ...n_when_use_help_option_py_3_12_commit_.txt | 29 +-- ..._when_use_help_option_py_3_12_example_.txt | 2 +- ...ion_when_use_help_option_py_3_12_info_.txt | 2 +- ...ion_when_use_help_option_py_3_12_init_.txt | 2 +- ...ption_when_use_help_option_py_3_12_ls_.txt | 2 +- ...n_when_use_help_option_py_3_12_schema_.txt | 2 +- ..._when_use_help_option_py_3_12_version_.txt | 16 +- ...ion_when_use_help_option_py_3_13_bump_.txt | 88 ++++---- ...hen_use_help_option_py_3_13_changelog_.txt | 40 ++-- ...on_when_use_help_option_py_3_13_check_.txt | 29 +-- ...n_when_use_help_option_py_3_13_commit_.txt | 29 +-- ..._when_use_help_option_py_3_13_example_.txt | 2 +- ...ion_when_use_help_option_py_3_13_info_.txt | 2 +- ...ion_when_use_help_option_py_3_13_init_.txt | 2 +- ...ption_when_use_help_option_py_3_13_ls_.txt | 2 +- ...n_when_use_help_option_py_3_13_schema_.txt | 2 +- ..._when_use_help_option_py_3_13_version_.txt | 16 +- ...ion_when_use_help_option_py_3_14_bump_.txt | 88 ++++---- ...hen_use_help_option_py_3_14_changelog_.txt | 40 ++-- ...on_when_use_help_option_py_3_14_check_.txt | 29 +-- ...n_when_use_help_option_py_3_14_commit_.txt | 29 +-- ..._when_use_help_option_py_3_14_example_.txt | 2 +- ...ion_when_use_help_option_py_3_14_info_.txt | 2 +- ...ion_when_use_help_option_py_3_14_init_.txt | 2 +- ...ption_when_use_help_option_py_3_14_ls_.txt | 2 +- ...n_when_use_help_option_py_3_14_schema_.txt | 2 +- ..._when_use_help_option_py_3_14_version_.txt | 16 +- 51 files changed, 643 insertions(+), 620 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 364bc93f85..99c36f8e4c 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -67,7 +67,7 @@ def __call__( { "name": ["--template", "-t"], "help": ( - "changelog template file name (relative to the current working directory)" + "Changelog template file name (relative to the current working directory)." ), }, { @@ -75,7 +75,7 @@ def __call__( "action": ParseKwargs, "dest": "extras", "metavar": "EXTRA", - "help": "a changelog extra variable (in the form 'key=value')", + "help": "Changelog extra variables (in the form 'key=value').", }, ) @@ -89,18 +89,18 @@ def __call__( "arguments": [ { "name": "--config", - "help": "the path of configuration file", + "help": "The path to the configuration file.", }, - {"name": "--debug", "action": "store_true", "help": "use debug mode"}, + {"name": "--debug", "action": "store_true", "help": "Use debug mode."}, { "name": ["-n", "--name"], - "help": "use the given commitizen (default: cz_conventional_commits)", + "help": "Use the given commitizen (default: cz_conventional_commits).", }, { "name": ["-nr", "--no-raise"], "type": str, "required": False, - "help": "comma separated error codes that won't raise error, e.g: cz -nr 1,2,3 bump. See codes at https://commitizen-tools.github.io/commitizen/exit_codes/", + "help": "Comma-separated error codes that won't raise error, e.g., cz -nr 1,2,3 bump. See codes at https://commitizen-tools.github.io/commitizen/exit_codes/", }, ], "subcommands": { @@ -109,157 +109,157 @@ def __call__( "commands": [ { "name": ["init"], - "description": "init commitizen configuration", - "help": "init commitizen configuration", + "description": "Initialize commitizen configuration", + "help": "Initialize commitizen configuration.", "func": commands.Init, }, { "name": ["commit", "c"], - "description": "create new commit", - "help": "create new commit", + "description": "Create new commit", + "help": "Create new commit.", "func": commands.Commit, "arguments": [ { "name": ["--retry"], "action": "store_true", - "help": "retry last commit", + "help": "Retry the last commit.", }, { "name": ["--no-retry"], "action": "store_true", "default": False, - "help": "skip retry if retry_after_failure is set to true", + "help": "Skip retry if --retry or `retry_after_failure` is set to true.", }, { "name": "--dry-run", "action": "store_true", - "help": "show output to stdout, no commit, no modified files", + "help": "Perform a dry run, without committing or modifying files.", }, { "name": "--write-message-to-file", "type": Path, "metavar": "FILE_PATH", - "help": "write message to file before committing (can be combined with --dry-run)", + "help": "Write message to FILE_PATH before committing (can be used with --dry-run).", }, { "name": ["-s", "--signoff"], "action": "store_true", - "help": "Deprecated, use 'cz commit -- -s' instead", + "help": "Deprecated, use `cz commit -- -s` instead.", }, { "name": ["-a", "--all"], "action": "store_true", - "help": "Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.", + # The help text aligns with the description of git commit --all + "help": "Automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.", }, { "name": ["-e", "--edit"], "action": "store_true", "default": False, - "help": "edit the commit message before committing", + "help": "Edit the commit message before committing.", }, { "name": ["-l", "--message-length-limit"], "type": int, - "help": "length limit of the commit message; 0 for no limit", + "help": "Set the length limit of the commit message; 0 for no limit.", }, { "name": ["--"], "action": "store_true", "dest": "double_dash", - "help": "Positional arguments separator (recommended)", + "help": "Positional arguments separator (recommended).", }, ], }, { "name": "ls", - "description": "show available commitizens", - "help": "show available commitizens", + "description": "Show available Commitizens", + "help": "Show available Commitizens.", "func": commands.ListCz, }, { "name": "example", - "description": "show commit example", - "help": "show commit example", + "description": "Show commit example", + "help": "Show commit example.", "func": commands.Example, }, { "name": "info", - "description": "show information about the cz", - "help": "show information about the cz", + "description": "Show information about the cz", + "help": "Show information about the cz.", "func": commands.Info, }, { "name": "schema", - "description": "show commit schema", - "help": "show commit schema", + "description": "Show commit schema", + "help": "Show commit schema.", "func": commands.Schema, }, { "name": "bump", - "description": "bump semantic version based on the git log", - "help": "bump semantic version based on the git log", + "description": "Bump semantic version based on the git log", + "help": "Bump semantic version based on the git log.", "func": commands.Bump, "arguments": [ { "name": "--dry-run", "action": "store_true", - "help": "show output to stdout, no commit, no modified files", + "help": "Perform a dry run, without committing or modifying files.", }, { - "name": "--files-only", + "name": "--files-only", # TODO: rename to --version-files-only "action": "store_true", - "help": "bump version in the files from the config", + "help": "Bump version in the `version_files` specified in the configuration file only.", }, { "name": "--local-version", "action": "store_true", - "help": "bump only the local version portion", + "help": "Bump version only the local version portion (ignoring the public version).", }, { "name": ["--changelog", "-ch"], "action": "store_true", "default": False, - "help": "generate the changelog for the newest version", + "help": "Generate the changelog for the latest version.", }, { "name": ["--no-verify"], "action": "store_true", "default": False, - "help": "this option bypasses the pre-commit and commit-msg hooks", + # The help text aligns with the description of git commit --no-verify + "help": "Bypass the pre-commit and commit-msg hooks.", }, { "name": "--yes", "action": "store_true", - "help": "accept automatically questions done", + "help": "Accept automatically answered questions.", }, { "name": "--tag-format", "help": ( - "the format used to tag the commit and read it, " - "use it in existing projects, " - "wrap around simple quotes" + "The format used to tag the commit and read it. " + "Use it in existing projects, and wrap around simple quotes." ), }, { "name": "--bump-message", "help": ( - "template used to create the release commit, " - "useful when working with CI" + "Template used to create the release commit, useful when working with CI." ), }, { "name": ["--prerelease", "-pr"], - "help": "choose type of prerelease", + "help": "Type of prerelease.", "choices": ["alpha", "beta", "rc"], }, { "name": ["--devrelease", "-d"], - "help": "specify non-negative integer for dev. release", + "help": "Specify non-negative integer for dev release.", "type": int, }, { "name": ["--increment"], - "help": "manually specify the desired increment", + "help": "Specify the desired increment.", "choices": ["MAJOR", "MINOR", "PATCH"], "type": str.upper, }, @@ -268,35 +268,34 @@ def __call__( "choices": ["linear", "exact"], "default": "linear", "help": ( - "set the method by which the new version is chosen. " - "'linear' (default) guesses the next version based on typical linear version progression, " - "such that bumping of a pre-release with lower precedence than the current pre-release " + "Set the method by which the new version is chosen. " + "'linear' (default) resolves the next version based on typical linear version progression, " + "where bumping of a pre-release with lower precedence than the current pre-release " "phase maintains the current phase of higher precedence. " "'exact' applies the changes that have been specified (or determined from the commit log) " - "without interpretation, such that the increment and pre-release are always honored" + "without interpretation, ensuring the increment and pre-release are always honored." ), }, { "name": ["--check-consistency", "-cc"], "help": ( - "check consistency among versions defined in " - "commitizen configuration and version_files" + "Check consistency among versions defined in Commitizen configuration file and `version_files`." ), "action": "store_true", }, { "name": ["--annotated-tag", "-at"], - "help": "create annotated tag instead of lightweight one", + "help": "Create annotated tag instead of lightweight one.", "action": "store_true", }, { "name": ["--annotated-tag-message", "-atm"], - "help": "create annotated tag message", + "help": "Create annotated tag message.", "type": str, }, { "name": ["--gpg-sign", "-s"], - "help": "sign tag instead of lightweight one", + "help": "Sign tag instead of lightweight one.", "default": False, "action": "store_true", }, @@ -304,46 +303,46 @@ def __call__( "name": ["--changelog-to-stdout"], "action": "store_true", "default": False, - "help": "Output changelog to the stdout", + "help": "Output changelog to stdout.", }, { "name": ["--git-output-to-stderr"], "action": "store_true", "default": False, - "help": "Redirect git output to stderr", + "help": "Redirect git output to stderr.", }, { "name": ["--retry"], "action": "store_true", "default": False, - "help": "retry commit if it fails the 1st time", + "help": "Retry commit if it fails for the first time.", }, { "name": ["--major-version-zero"], "action": "store_true", "default": None, - "help": "keep major version at zero, even for breaking changes", + "help": "Keep major version at zero, even for breaking changes.", }, *deepcopy(tpl_arguments), { "name": "--file-name", - "help": "file name of changelog (default: 'CHANGELOG.md')", + "help": "File name of changelog (default: 'CHANGELOG.md').", }, { "name": ["--prerelease-offset"], "type": int, "default": None, - "help": "start pre-releases with this offset", + "help": "Start pre-releases with this offset.", }, { "name": ["--version-scheme"], - "help": "choose version scheme", + "help": "Choose version scheme.", "default": None, "choices": version_schemes.KNOWN_SCHEMES, }, { "name": ["--version-type"], - "help": "Deprecated, use --version-scheme instead", + "help": "Deprecated, use `--version-scheme` instead.", "default": None, "choices": version_schemes.KNOWN_SCHEMES, }, @@ -351,24 +350,24 @@ def __call__( "name": "manual_version", "type": str, "nargs": "?", - "help": "bump to the given version (e.g: 1.5.3)", + "help": "Bump to the given version (e.g., 1.5.3).", "metavar": "MANUAL_VERSION", }, { "name": ["--build-metadata"], - "help": "Add additional build-metadata to the version-number", + "help": "Add additional build-metadata to the version-number.", "default": None, }, { "name": ["--get-next"], "action": "store_true", - "help": "Determine the next version and write to stdout", + "help": "Determine the next version and write to stdout.", "default": False, }, { "name": ["--allow-no-commit"], "default": False, - "help": "bump version without eligible commits", + "help": "Bump version without eligible commits.", "action": "store_true", }, ], @@ -376,10 +375,10 @@ def __call__( { "name": ["changelog", "ch"], "description": ( - "generate changelog (note that it will overwrite existing file)" + "Generate changelog (note that it will overwrite existing files)" ), "help": ( - "generate changelog (note that it will overwrite existing file)" + "Generate changelog (note that it will overwrite existing files)." ), "func": commands.Changelog, "arguments": [ @@ -387,17 +386,17 @@ def __call__( "name": "--dry-run", "action": "store_true", "default": False, - "help": "show changelog to stdout", + "help": "Show changelog to stdout.", }, { "name": "--file-name", - "help": "file name of changelog (default: 'CHANGELOG.md')", + "help": "File name of changelog (default: 'CHANGELOG.md').", }, { "name": "--unreleased-version", "help": ( - "set the value for the new version (use the tag value), " - "instead of using unreleased" + "Set the value for the new version (use the tag value), " + "instead of using unreleased versions." ), }, { @@ -405,22 +404,22 @@ def __call__( "action": "store_true", "default": False, "help": ( - "generates changelog from last created version, " - "useful if the changelog has been manually modified" + "Generate changelog from the last created version, " + "useful if the changelog has been manually modified." ), }, { "name": "rev_range", "type": str, "nargs": "?", - "help": "generates changelog for the given version (e.g: 1.5.3) or version range (e.g: 1.5.3..1.7.9)", + "help": "Generate changelog for the given version (e.g., 1.5.3) or version range (e.g., 1.5.3..1.7.9).", }, { "name": "--start-rev", "default": None, "help": ( - "start rev of the changelog. " - "If not set, it will generate changelog from the start" + "Start rev of the changelog. " + "If not set, it will generate changelog from the beginning." ), }, { @@ -428,128 +427,122 @@ def __call__( "action": "store_true", "default": False, "help": ( - "collect all changes from prereleases into next non-prerelease. " - "If not set, it will include prereleases in the changelog" + "Collect all changes from prereleases into the next non-prerelease. " + "If not set, it will include prereleases in the changelog." ), }, { "name": ["--version-scheme"], - "help": "choose version scheme", + "help": "Choose version scheme.", "default": None, "choices": version_schemes.KNOWN_SCHEMES, }, { "name": "--export-template", "default": None, - "help": "Export the changelog template into this file instead of rendering it", + "help": "Export the changelog template into this file instead of rendering it.", }, *deepcopy(tpl_arguments), { "name": "--tag-format", - "help": "The format of the tag, wrap around simple quotes", + "help": "The format of the tag, wrap around simple quotes.", }, ], }, { "name": ["check"], - "description": "validates that a commit message matches the commitizen schema", - "help": "validates that a commit message matches the commitizen schema", + "description": "Validate that a commit message matches the commitizen schema", + "help": "Validate that a commit message matches the commitizen schema.", "func": commands.Check, "arguments": [ { "name": "--commit-msg-file", "help": ( - "ask for the name of the temporal file that contains " - "the commit message. " - "Using it in a git hook script: MSG_FILE=$1" + "Ask for the name of the temporary file that contains the commit message. " + "Use it in a git hook script: MSG_FILE=$1." ), "exclusive_group": "group1", }, { "name": "--rev-range", - "help": "a range of git rev to check. e.g, master..HEAD", + "help": "Validate the commits in the given range of git rev, e.g., master..HEAD.", "exclusive_group": "group1", }, { "name": ["-d", "--use-default-range"], "action": "store_true", "default": False, - "help": "check from the default branch to HEAD. e.g, refs/remotes/origin/master..HEAD", + "help": "Validate the commits from the default branch to HEAD, e.g., refs/remotes/origin/master..HEAD.", "exclusive_group": "group1", }, { "name": ["-m", "--message"], - "help": "commit message that needs to be checked", + "help": "Validate the given commit message.", "exclusive_group": "group1", }, { "name": ["--allow-abort"], "action": "store_true", "default": False, - "help": "allow empty commit messages, which typically abort a commit", + "help": "Allow empty commit messages, which typically abort a commit.", }, { "name": ["--allowed-prefixes"], "nargs": "*", - "help": "allowed commit message prefixes. " - "If the message starts by one of these prefixes, " - "the message won't be checked against the regex", + "help": "Skip validation for commit messages that start with the specified prefixes.", }, { "name": ["-l", "--message-length-limit"], "type": int, - "help": "length limit of the commit message; 0 for no limit", + "help": "Restrict the length of the **first line** of the commit message; 0 for no limit.", }, ], }, { "name": ["version"], "description": ( - "get the version of the installed commitizen or the current project" - " (default: installed commitizen)" + "Get the version of the installed commitizen or the current project (default: installed commitizen)" ), "help": ( - "get the version of the installed commitizen or the current project" - " (default: installed commitizen)" + "Get the version of the installed commitizen or the current project (default: installed commitizen)." ), "func": commands.Version, "arguments": [ { "name": ["-r", "--report"], - "help": "get system information for reporting bugs", + "help": "Output the system information for reporting bugs.", "action": "store_true", "exclusive_group": "group1", }, { "name": ["-p", "--project"], - "help": "get the version of the current project", + "help": "Output the version of the current project.", "action": "store_true", "exclusive_group": "group1", }, { "name": ["-c", "--commitizen"], - "help": "get the version of the installed commitizen", + "help": "Output the version of the installed commitizen.", "action": "store_true", "exclusive_group": "group1", }, { "name": ["-v", "--verbose"], "help": ( - "get the version of both the installed commitizen " - "and the current project" + "Output the version of both the installed commitizen and the current project." ), "action": "store_true", "exclusive_group": "group1", }, { "name": ["--major"], - "help": "get just the major version. Need to be used with --project or --verbose.", + "help": "Output just the major version. Must be used with --project or --verbose.", "action": "store_true", "exclusive_group": "group2", }, { "name": ["--minor"], - "help": "get just the minor version. Need to be used with --project or --verbose.", + "help": "Output just the minor version. Must be used with --project or --verbose.", "action": "store_true", "exclusive_group": "group2", }, diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt index ad0a693278..d56e739277 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt @@ -14,69 +14,71 @@ usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] [--allow-no-commit] [MANUAL_VERSION] -bump semantic version based on the git log +Bump semantic version based on the git log positional arguments: - MANUAL_VERSION bump to the given version (e.g: 1.5.3) + MANUAL_VERSION Bump to the given version (e.g., 1.5.3). options: -h, --help show this help message and exit - --dry-run show output to stdout, no commit, no modified files - --files-only bump version in the files from the config - --local-version bump only the local version portion - --changelog, -ch generate the changelog for the newest version - --no-verify this option bypasses the pre-commit and commit-msg - hooks - --yes accept automatically questions done + --dry-run Perform a dry run, without committing or modifying + files. + --files-only Bump version in the `version_files` specified in the + configuration file only. + --local-version Bump version only the local version portion (ignoring + the public version). + --changelog, -ch Generate the changelog for the latest version. + --no-verify Bypass the pre-commit and commit-msg hooks. + --yes Accept automatically answered questions. --tag-format TAG_FORMAT - the format used to tag the commit and read it, use it - in existing projects, wrap around simple quotes + The format used to tag the commit and read it. Use it + in existing projects, and wrap around simple quotes. --bump-message BUMP_MESSAGE - template used to create the release commit, useful - when working with CI + Template used to create the release commit, useful + when working with CI. --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc} - choose type of prerelease + Type of prerelease. --devrelease DEVRELEASE, -d DEVRELEASE - specify non-negative integer for dev. release + Specify non-negative integer for dev release. --increment {MAJOR,MINOR,PATCH} - manually specify the desired increment + Specify the desired increment. --increment-mode {linear,exact} - set the method by which the new version is chosen. - 'linear' (default) guesses the next version based on - typical linear version progression, such that bumping - of a pre-release with lower precedence than the - current pre-release phase maintains the current phase - of higher precedence. 'exact' applies the changes that + Set the method by which the new version is chosen. + 'linear' (default) resolves the next version based on + typical linear version progression, where bumping of a + pre-release with lower precedence than the current + pre-release phase maintains the current phase of + higher precedence. 'exact' applies the changes that have been specified (or determined from the commit - log) without interpretation, such that the increment - and pre-release are always honored + log) without interpretation, ensuring the increment + and pre-release are always honored. --check-consistency, -cc - check consistency among versions defined in commitizen - configuration and version_files - --annotated-tag, -at create annotated tag instead of lightweight one + Check consistency among versions defined in Commitizen + configuration file and `version_files`. + --annotated-tag, -at Create annotated tag instead of lightweight one. --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE - create annotated tag message - --gpg-sign, -s sign tag instead of lightweight one + Create annotated tag message. + --gpg-sign, -s Sign tag instead of lightweight one. --changelog-to-stdout - Output changelog to the stdout + Output changelog to stdout. --git-output-to-stderr - Redirect git output to stderr - --retry retry commit if it fails the 1st time - --major-version-zero keep major version at zero, even for breaking changes + Redirect git output to stderr. + --retry Retry commit if it fails for the first time. + --major-version-zero Keep major version at zero, even for breaking changes. --template TEMPLATE, -t TEMPLATE - changelog template file name (relative to the current - working directory) + Changelog template file name (relative to the current + working directory). --extra EXTRA, -e EXTRA - a changelog extra variable (in the form 'key=value') + Changelog extra variables (in the form 'key=value'). --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --prerelease-offset PRERELEASE_OFFSET - start pre-releases with this offset + Start pre-releases with this offset. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --version-type {pep440,semver,semver2} - Deprecated, use --version-scheme instead + Deprecated, use `--version-scheme` instead. --build-metadata BUILD_METADATA - Add additional build-metadata to the version-number - --get-next Determine the next version and write to stdout - --allow-no-commit bump version without eligible commits + Add additional build-metadata to the version-number. + --get-next Determine the next version and write to stdout. + --allow-no-commit Bump version without eligible commits. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt index f4aa1ca2a6..2d1135af74 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_changelog_.txt @@ -6,37 +6,37 @@ usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--extra EXTRA] [--tag-format TAG_FORMAT] [rev_range] -generate changelog (note that it will overwrite existing file) +Generate changelog (note that it will overwrite existing files) positional arguments: - rev_range generates changelog for the given version (e.g: 1.5.3) - or version range (e.g: 1.5.3..1.7.9) + rev_range Generate changelog for the given version (e.g., 1.5.3) + or version range (e.g., 1.5.3..1.7.9). options: -h, --help show this help message and exit - --dry-run show changelog to stdout + --dry-run Show changelog to stdout. --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --unreleased-version UNRELEASED_VERSION - set the value for the new version (use the tag value), - instead of using unreleased - --incremental generates changelog from last created version, useful - if the changelog has been manually modified + Set the value for the new version (use the tag value), + instead of using unreleased versions. + --incremental Generate changelog from the last created version, + useful if the changelog has been manually modified. --start-rev START_REV - start rev of the changelog. If not set, it will - generate changelog from the start - --merge-prerelease collect all changes from prereleases into next non- - prerelease. If not set, it will include prereleases in - the changelog + Start rev of the changelog. If not set, it will + generate changelog from the beginning. + --merge-prerelease Collect all changes from prereleases into the next + non-prerelease. If not set, it will include + prereleases in the changelog. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --export-template EXPORT_TEMPLATE Export the changelog template into this file instead - of rendering it + of rendering it. --template TEMPLATE, -t TEMPLATE - changelog template file name (relative to the current - working directory) + Changelog template file name (relative to the current + working directory). --extra EXTRA, -e EXTRA - a changelog extra variable (in the form 'key=value') + Changelog extra variables (in the form 'key=value'). --tag-format TAG_FORMAT - The format of the tag, wrap around simple quotes + The format of the tag, wrap around simple quotes. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt index 53c4e7ed10..144e91b61a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_check_.txt @@ -3,26 +3,27 @@ usage: cz check [-h] [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] [-l MESSAGE_LENGTH_LIMIT] -validates that a commit message matches the commitizen schema +Validate that a commit message matches the commitizen schema options: -h, --help show this help message and exit --commit-msg-file COMMIT_MSG_FILE - ask for the name of the temporal file that contains - the commit message. Using it in a git hook script: - MSG_FILE=$1 + Ask for the name of the temporary file that contains + the commit message. Use it in a git hook script: + MSG_FILE=$1. --rev-range REV_RANGE - a range of git rev to check. e.g, master..HEAD + Validate the commits in the given range of git rev, + e.g., master..HEAD. -d, --use-default-range - check from the default branch to HEAD. e.g, - refs/remotes/origin/master..HEAD + Validate the commits from the default branch to HEAD, + e.g., refs/remotes/origin/master..HEAD. -m MESSAGE, --message MESSAGE - commit message that needs to be checked - --allow-abort allow empty commit messages, which typically abort a - commit + Validate the given commit message. + --allow-abort Allow empty commit messages, which typically abort a + commit. --allowed-prefixes [ALLOWED_PREFIXES ...] - allowed commit message prefixes. If the message starts - by one of these prefixes, the message won't be checked - against the regex + Skip validation for commit messages that start with + the specified prefixes. -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit + Restrict the length of the **first line** of the + commit message; 0 for no limit. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt index c842433427..bd256ccf8c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_commit_.txt @@ -2,21 +2,24 @@ usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] [--write-message-to-file FILE_PATH] [-s] [-a] [-e] [-l MESSAGE_LENGTH_LIMIT] [--] -create new commit +Create new commit options: -h, --help show this help message and exit - --retry retry last commit - --no-retry skip retry if retry_after_failure is set to true - --dry-run show output to stdout, no commit, no modified files + --retry Retry the last commit. + --no-retry Skip retry if --retry or `retry_after_failure` is set + to true. + --dry-run Perform a dry run, without committing or modifying + files. --write-message-to-file FILE_PATH - write message to file before committing (can be - combined with --dry-run) - -s, --signoff Deprecated, use 'cz commit -- -s' instead - -a, --all Tell the command to automatically stage files that - have been modified and deleted, but new files you have - not told Git about are not affected. - -e, --edit edit the commit message before committing + Write message to FILE_PATH before committing (can be + used with --dry-run). + -s, --signoff Deprecated, use `cz commit -- -s` instead. + -a, --all Automatically stage files that have been modified and + deleted, but new files you have not told Git about are + not affected. + -e, --edit Edit the commit message before committing. -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit - -- Positional arguments separator (recommended) + Set the length limit of the commit message; 0 for no + limit. + -- Positional arguments separator (recommended). diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_example_.txt index b9bf7f84fc..8a0f1c9d94 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_example_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_example_.txt @@ -1,6 +1,6 @@ usage: cz example [-h] -show commit example +Show commit example options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_info_.txt index 99b1ba8a4a..ed5ae2522e 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_info_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_info_.txt @@ -1,6 +1,6 @@ usage: cz info [-h] -show information about the cz +Show information about the cz options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_init_.txt index 0f72042f88..546ab51cb3 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_init_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_init_.txt @@ -1,6 +1,6 @@ usage: cz init [-h] -init commitizen configuration +Initialize commitizen configuration options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_ls_.txt index 5fa8fe1f79..253da1722c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_ls_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_ls_.txt @@ -1,6 +1,6 @@ usage: cz ls [-h] -show available commitizens +Show available Commitizens options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_schema_.txt index 6666db4d41..dd05ead81b 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_schema_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_schema_.txt @@ -1,6 +1,6 @@ usage: cz schema [-h] -show commit schema +Show commit schema options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt index a194615a98..0061a97514 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt @@ -1,16 +1,16 @@ usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] -get the version of the installed commitizen or the current project (default: +Get the version of the installed commitizen or the current project (default: installed commitizen) options: -h, --help show this help message and exit - -r, --report get system information for reporting bugs - -p, --project get the version of the current project - -c, --commitizen get the version of the installed commitizen - -v, --verbose get the version of both the installed commitizen and the - current project - --major get just the major version. Need to be used with --project + -r, --report Output the system information for reporting bugs. + -p, --project Output the version of the current project. + -c, --commitizen Output the version of the installed commitizen. + -v, --verbose Output the version of both the installed commitizen and + the current project. + --major Output just the major version. Must be used with --project or --verbose. - --minor get just the minor version. Need to be used with --project + --minor Output just the minor version. Must be used with --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt index ad0a693278..d56e739277 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt @@ -14,69 +14,71 @@ usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] [--allow-no-commit] [MANUAL_VERSION] -bump semantic version based on the git log +Bump semantic version based on the git log positional arguments: - MANUAL_VERSION bump to the given version (e.g: 1.5.3) + MANUAL_VERSION Bump to the given version (e.g., 1.5.3). options: -h, --help show this help message and exit - --dry-run show output to stdout, no commit, no modified files - --files-only bump version in the files from the config - --local-version bump only the local version portion - --changelog, -ch generate the changelog for the newest version - --no-verify this option bypasses the pre-commit and commit-msg - hooks - --yes accept automatically questions done + --dry-run Perform a dry run, without committing or modifying + files. + --files-only Bump version in the `version_files` specified in the + configuration file only. + --local-version Bump version only the local version portion (ignoring + the public version). + --changelog, -ch Generate the changelog for the latest version. + --no-verify Bypass the pre-commit and commit-msg hooks. + --yes Accept automatically answered questions. --tag-format TAG_FORMAT - the format used to tag the commit and read it, use it - in existing projects, wrap around simple quotes + The format used to tag the commit and read it. Use it + in existing projects, and wrap around simple quotes. --bump-message BUMP_MESSAGE - template used to create the release commit, useful - when working with CI + Template used to create the release commit, useful + when working with CI. --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc} - choose type of prerelease + Type of prerelease. --devrelease DEVRELEASE, -d DEVRELEASE - specify non-negative integer for dev. release + Specify non-negative integer for dev release. --increment {MAJOR,MINOR,PATCH} - manually specify the desired increment + Specify the desired increment. --increment-mode {linear,exact} - set the method by which the new version is chosen. - 'linear' (default) guesses the next version based on - typical linear version progression, such that bumping - of a pre-release with lower precedence than the - current pre-release phase maintains the current phase - of higher precedence. 'exact' applies the changes that + Set the method by which the new version is chosen. + 'linear' (default) resolves the next version based on + typical linear version progression, where bumping of a + pre-release with lower precedence than the current + pre-release phase maintains the current phase of + higher precedence. 'exact' applies the changes that have been specified (or determined from the commit - log) without interpretation, such that the increment - and pre-release are always honored + log) without interpretation, ensuring the increment + and pre-release are always honored. --check-consistency, -cc - check consistency among versions defined in commitizen - configuration and version_files - --annotated-tag, -at create annotated tag instead of lightweight one + Check consistency among versions defined in Commitizen + configuration file and `version_files`. + --annotated-tag, -at Create annotated tag instead of lightweight one. --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE - create annotated tag message - --gpg-sign, -s sign tag instead of lightweight one + Create annotated tag message. + --gpg-sign, -s Sign tag instead of lightweight one. --changelog-to-stdout - Output changelog to the stdout + Output changelog to stdout. --git-output-to-stderr - Redirect git output to stderr - --retry retry commit if it fails the 1st time - --major-version-zero keep major version at zero, even for breaking changes + Redirect git output to stderr. + --retry Retry commit if it fails for the first time. + --major-version-zero Keep major version at zero, even for breaking changes. --template TEMPLATE, -t TEMPLATE - changelog template file name (relative to the current - working directory) + Changelog template file name (relative to the current + working directory). --extra EXTRA, -e EXTRA - a changelog extra variable (in the form 'key=value') + Changelog extra variables (in the form 'key=value'). --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --prerelease-offset PRERELEASE_OFFSET - start pre-releases with this offset + Start pre-releases with this offset. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --version-type {pep440,semver,semver2} - Deprecated, use --version-scheme instead + Deprecated, use `--version-scheme` instead. --build-metadata BUILD_METADATA - Add additional build-metadata to the version-number - --get-next Determine the next version and write to stdout - --allow-no-commit bump version without eligible commits + Add additional build-metadata to the version-number. + --get-next Determine the next version and write to stdout. + --allow-no-commit Bump version without eligible commits. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt index f4aa1ca2a6..2d1135af74 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_changelog_.txt @@ -6,37 +6,37 @@ usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--extra EXTRA] [--tag-format TAG_FORMAT] [rev_range] -generate changelog (note that it will overwrite existing file) +Generate changelog (note that it will overwrite existing files) positional arguments: - rev_range generates changelog for the given version (e.g: 1.5.3) - or version range (e.g: 1.5.3..1.7.9) + rev_range Generate changelog for the given version (e.g., 1.5.3) + or version range (e.g., 1.5.3..1.7.9). options: -h, --help show this help message and exit - --dry-run show changelog to stdout + --dry-run Show changelog to stdout. --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --unreleased-version UNRELEASED_VERSION - set the value for the new version (use the tag value), - instead of using unreleased - --incremental generates changelog from last created version, useful - if the changelog has been manually modified + Set the value for the new version (use the tag value), + instead of using unreleased versions. + --incremental Generate changelog from the last created version, + useful if the changelog has been manually modified. --start-rev START_REV - start rev of the changelog. If not set, it will - generate changelog from the start - --merge-prerelease collect all changes from prereleases into next non- - prerelease. If not set, it will include prereleases in - the changelog + Start rev of the changelog. If not set, it will + generate changelog from the beginning. + --merge-prerelease Collect all changes from prereleases into the next + non-prerelease. If not set, it will include + prereleases in the changelog. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --export-template EXPORT_TEMPLATE Export the changelog template into this file instead - of rendering it + of rendering it. --template TEMPLATE, -t TEMPLATE - changelog template file name (relative to the current - working directory) + Changelog template file name (relative to the current + working directory). --extra EXTRA, -e EXTRA - a changelog extra variable (in the form 'key=value') + Changelog extra variables (in the form 'key=value'). --tag-format TAG_FORMAT - The format of the tag, wrap around simple quotes + The format of the tag, wrap around simple quotes. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt index 53c4e7ed10..144e91b61a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_check_.txt @@ -3,26 +3,27 @@ usage: cz check [-h] [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] [-l MESSAGE_LENGTH_LIMIT] -validates that a commit message matches the commitizen schema +Validate that a commit message matches the commitizen schema options: -h, --help show this help message and exit --commit-msg-file COMMIT_MSG_FILE - ask for the name of the temporal file that contains - the commit message. Using it in a git hook script: - MSG_FILE=$1 + Ask for the name of the temporary file that contains + the commit message. Use it in a git hook script: + MSG_FILE=$1. --rev-range REV_RANGE - a range of git rev to check. e.g, master..HEAD + Validate the commits in the given range of git rev, + e.g., master..HEAD. -d, --use-default-range - check from the default branch to HEAD. e.g, - refs/remotes/origin/master..HEAD + Validate the commits from the default branch to HEAD, + e.g., refs/remotes/origin/master..HEAD. -m MESSAGE, --message MESSAGE - commit message that needs to be checked - --allow-abort allow empty commit messages, which typically abort a - commit + Validate the given commit message. + --allow-abort Allow empty commit messages, which typically abort a + commit. --allowed-prefixes [ALLOWED_PREFIXES ...] - allowed commit message prefixes. If the message starts - by one of these prefixes, the message won't be checked - against the regex + Skip validation for commit messages that start with + the specified prefixes. -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit + Restrict the length of the **first line** of the + commit message; 0 for no limit. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt index c842433427..bd256ccf8c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_commit_.txt @@ -2,21 +2,24 @@ usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] [--write-message-to-file FILE_PATH] [-s] [-a] [-e] [-l MESSAGE_LENGTH_LIMIT] [--] -create new commit +Create new commit options: -h, --help show this help message and exit - --retry retry last commit - --no-retry skip retry if retry_after_failure is set to true - --dry-run show output to stdout, no commit, no modified files + --retry Retry the last commit. + --no-retry Skip retry if --retry or `retry_after_failure` is set + to true. + --dry-run Perform a dry run, without committing or modifying + files. --write-message-to-file FILE_PATH - write message to file before committing (can be - combined with --dry-run) - -s, --signoff Deprecated, use 'cz commit -- -s' instead - -a, --all Tell the command to automatically stage files that - have been modified and deleted, but new files you have - not told Git about are not affected. - -e, --edit edit the commit message before committing + Write message to FILE_PATH before committing (can be + used with --dry-run). + -s, --signoff Deprecated, use `cz commit -- -s` instead. + -a, --all Automatically stage files that have been modified and + deleted, but new files you have not told Git about are + not affected. + -e, --edit Edit the commit message before committing. -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit - -- Positional arguments separator (recommended) + Set the length limit of the commit message; 0 for no + limit. + -- Positional arguments separator (recommended). diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt index b9bf7f84fc..8a0f1c9d94 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_example_.txt @@ -1,6 +1,6 @@ usage: cz example [-h] -show commit example +Show commit example options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt index 99b1ba8a4a..ed5ae2522e 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_info_.txt @@ -1,6 +1,6 @@ usage: cz info [-h] -show information about the cz +Show information about the cz options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt index 0f72042f88..546ab51cb3 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_init_.txt @@ -1,6 +1,6 @@ usage: cz init [-h] -init commitizen configuration +Initialize commitizen configuration options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt index 5fa8fe1f79..253da1722c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_ls_.txt @@ -1,6 +1,6 @@ usage: cz ls [-h] -show available commitizens +Show available Commitizens options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt index 6666db4d41..dd05ead81b 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_schema_.txt @@ -1,6 +1,6 @@ usage: cz schema [-h] -show commit schema +Show commit schema options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt index a194615a98..0061a97514 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt @@ -1,16 +1,16 @@ usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] -get the version of the installed commitizen or the current project (default: +Get the version of the installed commitizen or the current project (default: installed commitizen) options: -h, --help show this help message and exit - -r, --report get system information for reporting bugs - -p, --project get the version of the current project - -c, --commitizen get the version of the installed commitizen - -v, --verbose get the version of both the installed commitizen and the - current project - --major get just the major version. Need to be used with --project + -r, --report Output the system information for reporting bugs. + -p, --project Output the version of the current project. + -c, --commitizen Output the version of the installed commitizen. + -v, --verbose Output the version of both the installed commitizen and + the current project. + --major Output just the major version. Must be used with --project or --verbose. - --minor get just the minor version. Need to be used with --project + --minor Output just the minor version. Must be used with --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt index ad0a693278..d56e739277 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt @@ -14,69 +14,71 @@ usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] [--allow-no-commit] [MANUAL_VERSION] -bump semantic version based on the git log +Bump semantic version based on the git log positional arguments: - MANUAL_VERSION bump to the given version (e.g: 1.5.3) + MANUAL_VERSION Bump to the given version (e.g., 1.5.3). options: -h, --help show this help message and exit - --dry-run show output to stdout, no commit, no modified files - --files-only bump version in the files from the config - --local-version bump only the local version portion - --changelog, -ch generate the changelog for the newest version - --no-verify this option bypasses the pre-commit and commit-msg - hooks - --yes accept automatically questions done + --dry-run Perform a dry run, without committing or modifying + files. + --files-only Bump version in the `version_files` specified in the + configuration file only. + --local-version Bump version only the local version portion (ignoring + the public version). + --changelog, -ch Generate the changelog for the latest version. + --no-verify Bypass the pre-commit and commit-msg hooks. + --yes Accept automatically answered questions. --tag-format TAG_FORMAT - the format used to tag the commit and read it, use it - in existing projects, wrap around simple quotes + The format used to tag the commit and read it. Use it + in existing projects, and wrap around simple quotes. --bump-message BUMP_MESSAGE - template used to create the release commit, useful - when working with CI + Template used to create the release commit, useful + when working with CI. --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc} - choose type of prerelease + Type of prerelease. --devrelease DEVRELEASE, -d DEVRELEASE - specify non-negative integer for dev. release + Specify non-negative integer for dev release. --increment {MAJOR,MINOR,PATCH} - manually specify the desired increment + Specify the desired increment. --increment-mode {linear,exact} - set the method by which the new version is chosen. - 'linear' (default) guesses the next version based on - typical linear version progression, such that bumping - of a pre-release with lower precedence than the - current pre-release phase maintains the current phase - of higher precedence. 'exact' applies the changes that + Set the method by which the new version is chosen. + 'linear' (default) resolves the next version based on + typical linear version progression, where bumping of a + pre-release with lower precedence than the current + pre-release phase maintains the current phase of + higher precedence. 'exact' applies the changes that have been specified (or determined from the commit - log) without interpretation, such that the increment - and pre-release are always honored + log) without interpretation, ensuring the increment + and pre-release are always honored. --check-consistency, -cc - check consistency among versions defined in commitizen - configuration and version_files - --annotated-tag, -at create annotated tag instead of lightweight one + Check consistency among versions defined in Commitizen + configuration file and `version_files`. + --annotated-tag, -at Create annotated tag instead of lightweight one. --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE - create annotated tag message - --gpg-sign, -s sign tag instead of lightweight one + Create annotated tag message. + --gpg-sign, -s Sign tag instead of lightweight one. --changelog-to-stdout - Output changelog to the stdout + Output changelog to stdout. --git-output-to-stderr - Redirect git output to stderr - --retry retry commit if it fails the 1st time - --major-version-zero keep major version at zero, even for breaking changes + Redirect git output to stderr. + --retry Retry commit if it fails for the first time. + --major-version-zero Keep major version at zero, even for breaking changes. --template TEMPLATE, -t TEMPLATE - changelog template file name (relative to the current - working directory) + Changelog template file name (relative to the current + working directory). --extra EXTRA, -e EXTRA - a changelog extra variable (in the form 'key=value') + Changelog extra variables (in the form 'key=value'). --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --prerelease-offset PRERELEASE_OFFSET - start pre-releases with this offset + Start pre-releases with this offset. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --version-type {pep440,semver,semver2} - Deprecated, use --version-scheme instead + Deprecated, use `--version-scheme` instead. --build-metadata BUILD_METADATA - Add additional build-metadata to the version-number - --get-next Determine the next version and write to stdout - --allow-no-commit bump version without eligible commits + Add additional build-metadata to the version-number. + --get-next Determine the next version and write to stdout. + --allow-no-commit Bump version without eligible commits. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt index f4aa1ca2a6..2d1135af74 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_changelog_.txt @@ -6,37 +6,37 @@ usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--extra EXTRA] [--tag-format TAG_FORMAT] [rev_range] -generate changelog (note that it will overwrite existing file) +Generate changelog (note that it will overwrite existing files) positional arguments: - rev_range generates changelog for the given version (e.g: 1.5.3) - or version range (e.g: 1.5.3..1.7.9) + rev_range Generate changelog for the given version (e.g., 1.5.3) + or version range (e.g., 1.5.3..1.7.9). options: -h, --help show this help message and exit - --dry-run show changelog to stdout + --dry-run Show changelog to stdout. --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --unreleased-version UNRELEASED_VERSION - set the value for the new version (use the tag value), - instead of using unreleased - --incremental generates changelog from last created version, useful - if the changelog has been manually modified + Set the value for the new version (use the tag value), + instead of using unreleased versions. + --incremental Generate changelog from the last created version, + useful if the changelog has been manually modified. --start-rev START_REV - start rev of the changelog. If not set, it will - generate changelog from the start - --merge-prerelease collect all changes from prereleases into next non- - prerelease. If not set, it will include prereleases in - the changelog + Start rev of the changelog. If not set, it will + generate changelog from the beginning. + --merge-prerelease Collect all changes from prereleases into the next + non-prerelease. If not set, it will include + prereleases in the changelog. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --export-template EXPORT_TEMPLATE Export the changelog template into this file instead - of rendering it + of rendering it. --template TEMPLATE, -t TEMPLATE - changelog template file name (relative to the current - working directory) + Changelog template file name (relative to the current + working directory). --extra EXTRA, -e EXTRA - a changelog extra variable (in the form 'key=value') + Changelog extra variables (in the form 'key=value'). --tag-format TAG_FORMAT - The format of the tag, wrap around simple quotes + The format of the tag, wrap around simple quotes. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt index 53c4e7ed10..144e91b61a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_check_.txt @@ -3,26 +3,27 @@ usage: cz check [-h] [--allow-abort] [--allowed-prefixes [ALLOWED_PREFIXES ...]] [-l MESSAGE_LENGTH_LIMIT] -validates that a commit message matches the commitizen schema +Validate that a commit message matches the commitizen schema options: -h, --help show this help message and exit --commit-msg-file COMMIT_MSG_FILE - ask for the name of the temporal file that contains - the commit message. Using it in a git hook script: - MSG_FILE=$1 + Ask for the name of the temporary file that contains + the commit message. Use it in a git hook script: + MSG_FILE=$1. --rev-range REV_RANGE - a range of git rev to check. e.g, master..HEAD + Validate the commits in the given range of git rev, + e.g., master..HEAD. -d, --use-default-range - check from the default branch to HEAD. e.g, - refs/remotes/origin/master..HEAD + Validate the commits from the default branch to HEAD, + e.g., refs/remotes/origin/master..HEAD. -m MESSAGE, --message MESSAGE - commit message that needs to be checked - --allow-abort allow empty commit messages, which typically abort a - commit + Validate the given commit message. + --allow-abort Allow empty commit messages, which typically abort a + commit. --allowed-prefixes [ALLOWED_PREFIXES ...] - allowed commit message prefixes. If the message starts - by one of these prefixes, the message won't be checked - against the regex + Skip validation for commit messages that start with + the specified prefixes. -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit + Restrict the length of the **first line** of the + commit message; 0 for no limit. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt index c842433427..bd256ccf8c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_commit_.txt @@ -2,21 +2,24 @@ usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] [--write-message-to-file FILE_PATH] [-s] [-a] [-e] [-l MESSAGE_LENGTH_LIMIT] [--] -create new commit +Create new commit options: -h, --help show this help message and exit - --retry retry last commit - --no-retry skip retry if retry_after_failure is set to true - --dry-run show output to stdout, no commit, no modified files + --retry Retry the last commit. + --no-retry Skip retry if --retry or `retry_after_failure` is set + to true. + --dry-run Perform a dry run, without committing or modifying + files. --write-message-to-file FILE_PATH - write message to file before committing (can be - combined with --dry-run) - -s, --signoff Deprecated, use 'cz commit -- -s' instead - -a, --all Tell the command to automatically stage files that - have been modified and deleted, but new files you have - not told Git about are not affected. - -e, --edit edit the commit message before committing + Write message to FILE_PATH before committing (can be + used with --dry-run). + -s, --signoff Deprecated, use `cz commit -- -s` instead. + -a, --all Automatically stage files that have been modified and + deleted, but new files you have not told Git about are + not affected. + -e, --edit Edit the commit message before committing. -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit - -- Positional arguments separator (recommended) + Set the length limit of the commit message; 0 for no + limit. + -- Positional arguments separator (recommended). diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt index b9bf7f84fc..8a0f1c9d94 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_example_.txt @@ -1,6 +1,6 @@ usage: cz example [-h] -show commit example +Show commit example options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt index 99b1ba8a4a..ed5ae2522e 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_info_.txt @@ -1,6 +1,6 @@ usage: cz info [-h] -show information about the cz +Show information about the cz options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt index 0f72042f88..546ab51cb3 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_init_.txt @@ -1,6 +1,6 @@ usage: cz init [-h] -init commitizen configuration +Initialize commitizen configuration options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt index 5fa8fe1f79..253da1722c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_ls_.txt @@ -1,6 +1,6 @@ usage: cz ls [-h] -show available commitizens +Show available Commitizens options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt index 6666db4d41..dd05ead81b 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_schema_.txt @@ -1,6 +1,6 @@ usage: cz schema [-h] -show commit schema +Show commit schema options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt index a194615a98..0061a97514 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt @@ -1,16 +1,16 @@ usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] -get the version of the installed commitizen or the current project (default: +Get the version of the installed commitizen or the current project (default: installed commitizen) options: -h, --help show this help message and exit - -r, --report get system information for reporting bugs - -p, --project get the version of the current project - -c, --commitizen get the version of the installed commitizen - -v, --verbose get the version of both the installed commitizen and the - current project - --major get just the major version. Need to be used with --project + -r, --report Output the system information for reporting bugs. + -p, --project Output the version of the current project. + -c, --commitizen Output the version of the installed commitizen. + -v, --verbose Output the version of both the installed commitizen and + the current project. + --major Output just the major version. Must be used with --project or --verbose. - --minor get just the minor version. Need to be used with --project + --minor Output just the minor version. Must be used with --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt index 4cf8e6c91b..c472a040e9 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt @@ -14,68 +14,70 @@ usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] [--allow-no-commit] [MANUAL_VERSION] -bump semantic version based on the git log +Bump semantic version based on the git log positional arguments: - MANUAL_VERSION bump to the given version (e.g: 1.5.3) + MANUAL_VERSION Bump to the given version (e.g., 1.5.3). options: -h, --help show this help message and exit - --dry-run show output to stdout, no commit, no modified files - --files-only bump version in the files from the config - --local-version bump only the local version portion - --changelog, -ch generate the changelog for the newest version - --no-verify this option bypasses the pre-commit and commit-msg - hooks - --yes accept automatically questions done + --dry-run Perform a dry run, without committing or modifying + files. + --files-only Bump version in the `version_files` specified in the + configuration file only. + --local-version Bump version only the local version portion (ignoring + the public version). + --changelog, -ch Generate the changelog for the latest version. + --no-verify Bypass the pre-commit and commit-msg hooks. + --yes Accept automatically answered questions. --tag-format TAG_FORMAT - the format used to tag the commit and read it, use it - in existing projects, wrap around simple quotes + The format used to tag the commit and read it. Use it + in existing projects, and wrap around simple quotes. --bump-message BUMP_MESSAGE - template used to create the release commit, useful - when working with CI + Template used to create the release commit, useful + when working with CI. --prerelease, -pr {alpha,beta,rc} - choose type of prerelease + Type of prerelease. --devrelease, -d DEVRELEASE - specify non-negative integer for dev. release + Specify non-negative integer for dev release. --increment {MAJOR,MINOR,PATCH} - manually specify the desired increment + Specify the desired increment. --increment-mode {linear,exact} - set the method by which the new version is chosen. - 'linear' (default) guesses the next version based on - typical linear version progression, such that bumping - of a pre-release with lower precedence than the - current pre-release phase maintains the current phase - of higher precedence. 'exact' applies the changes that + Set the method by which the new version is chosen. + 'linear' (default) resolves the next version based on + typical linear version progression, where bumping of a + pre-release with lower precedence than the current + pre-release phase maintains the current phase of + higher precedence. 'exact' applies the changes that have been specified (or determined from the commit - log) without interpretation, such that the increment - and pre-release are always honored + log) without interpretation, ensuring the increment + and pre-release are always honored. --check-consistency, -cc - check consistency among versions defined in commitizen - configuration and version_files - --annotated-tag, -at create annotated tag instead of lightweight one + Check consistency among versions defined in Commitizen + configuration file and `version_files`. + --annotated-tag, -at Create annotated tag instead of lightweight one. --annotated-tag-message, -atm ANNOTATED_TAG_MESSAGE - create annotated tag message - --gpg-sign, -s sign tag instead of lightweight one + Create annotated tag message. + --gpg-sign, -s Sign tag instead of lightweight one. --changelog-to-stdout - Output changelog to the stdout + Output changelog to stdout. --git-output-to-stderr - Redirect git output to stderr - --retry retry commit if it fails the 1st time - --major-version-zero keep major version at zero, even for breaking changes + Redirect git output to stderr. + --retry Retry commit if it fails for the first time. + --major-version-zero Keep major version at zero, even for breaking changes. --template, -t TEMPLATE - changelog template file name (relative to the current - working directory) - --extra, -e EXTRA a changelog extra variable (in the form 'key=value') + Changelog template file name (relative to the current + working directory). + --extra, -e EXTRA Changelog extra variables (in the form 'key=value'). --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --prerelease-offset PRERELEASE_OFFSET - start pre-releases with this offset + Start pre-releases with this offset. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --version-type {pep440,semver,semver2} - Deprecated, use --version-scheme instead + Deprecated, use `--version-scheme` instead. --build-metadata BUILD_METADATA - Add additional build-metadata to the version-number - --get-next Determine the next version and write to stdout - --allow-no-commit bump version without eligible commits + Add additional build-metadata to the version-number. + --get-next Determine the next version and write to stdout. + --allow-no-commit Bump version without eligible commits. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt index 91b7f389b5..50ab468d64 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_changelog_.txt @@ -6,36 +6,36 @@ usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--extra EXTRA] [--tag-format TAG_FORMAT] [rev_range] -generate changelog (note that it will overwrite existing file) +Generate changelog (note that it will overwrite existing files) positional arguments: - rev_range generates changelog for the given version (e.g: 1.5.3) - or version range (e.g: 1.5.3..1.7.9) + rev_range Generate changelog for the given version (e.g., 1.5.3) + or version range (e.g., 1.5.3..1.7.9). options: -h, --help show this help message and exit - --dry-run show changelog to stdout + --dry-run Show changelog to stdout. --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --unreleased-version UNRELEASED_VERSION - set the value for the new version (use the tag value), - instead of using unreleased - --incremental generates changelog from last created version, useful - if the changelog has been manually modified + Set the value for the new version (use the tag value), + instead of using unreleased versions. + --incremental Generate changelog from the last created version, + useful if the changelog has been manually modified. --start-rev START_REV - start rev of the changelog. If not set, it will - generate changelog from the start - --merge-prerelease collect all changes from prereleases into next non- - prerelease. If not set, it will include prereleases in - the changelog + Start rev of the changelog. If not set, it will + generate changelog from the beginning. + --merge-prerelease Collect all changes from prereleases into the next + non-prerelease. If not set, it will include + prereleases in the changelog. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --export-template EXPORT_TEMPLATE Export the changelog template into this file instead - of rendering it + of rendering it. --template, -t TEMPLATE - changelog template file name (relative to the current - working directory) - --extra, -e EXTRA a changelog extra variable (in the form 'key=value') + Changelog template file name (relative to the current + working directory). + --extra, -e EXTRA Changelog extra variables (in the form 'key=value'). --tag-format TAG_FORMAT - The format of the tag, wrap around simple quotes + The format of the tag, wrap around simple quotes. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_check_.txt index 4066748557..6f8297e1ee 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_check_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_check_.txt @@ -3,26 +3,27 @@ usage: cz check [-h] [--commit-msg-file COMMIT_MSG_FILE | [--allowed-prefixes [ALLOWED_PREFIXES ...]] [-l MESSAGE_LENGTH_LIMIT] -validates that a commit message matches the commitizen schema +Validate that a commit message matches the commitizen schema options: -h, --help show this help message and exit --commit-msg-file COMMIT_MSG_FILE - ask for the name of the temporal file that contains - the commit message. Using it in a git hook script: - MSG_FILE=$1 + Ask for the name of the temporary file that contains + the commit message. Use it in a git hook script: + MSG_FILE=$1. --rev-range REV_RANGE - a range of git rev to check. e.g, master..HEAD + Validate the commits in the given range of git rev, + e.g., master..HEAD. -d, --use-default-range - check from the default branch to HEAD. e.g, - refs/remotes/origin/master..HEAD + Validate the commits from the default branch to HEAD, + e.g., refs/remotes/origin/master..HEAD. -m, --message MESSAGE - commit message that needs to be checked - --allow-abort allow empty commit messages, which typically abort a - commit + Validate the given commit message. + --allow-abort Allow empty commit messages, which typically abort a + commit. --allowed-prefixes [ALLOWED_PREFIXES ...] - allowed commit message prefixes. If the message starts - by one of these prefixes, the message won't be checked - against the regex + Skip validation for commit messages that start with + the specified prefixes. -l, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit + Restrict the length of the **first line** of the + commit message; 0 for no limit. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_commit_.txt index ba531042aa..cbd5780f6d 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_commit_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_commit_.txt @@ -2,21 +2,24 @@ usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] [--write-message-to-file FILE_PATH] [-s] [-a] [-e] [-l MESSAGE_LENGTH_LIMIT] [--] -create new commit +Create new commit options: -h, --help show this help message and exit - --retry retry last commit - --no-retry skip retry if retry_after_failure is set to true - --dry-run show output to stdout, no commit, no modified files + --retry Retry the last commit. + --no-retry Skip retry if --retry or `retry_after_failure` is set + to true. + --dry-run Perform a dry run, without committing or modifying + files. --write-message-to-file FILE_PATH - write message to file before committing (can be - combined with --dry-run) - -s, --signoff Deprecated, use 'cz commit -- -s' instead - -a, --all Tell the command to automatically stage files that - have been modified and deleted, but new files you have - not told Git about are not affected. - -e, --edit edit the commit message before committing + Write message to FILE_PATH before committing (can be + used with --dry-run). + -s, --signoff Deprecated, use `cz commit -- -s` instead. + -a, --all Automatically stage files that have been modified and + deleted, but new files you have not told Git about are + not affected. + -e, --edit Edit the commit message before committing. -l, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit - -- Positional arguments separator (recommended) + Set the length limit of the commit message; 0 for no + limit. + -- Positional arguments separator (recommended). diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt index b9bf7f84fc..8a0f1c9d94 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_example_.txt @@ -1,6 +1,6 @@ usage: cz example [-h] -show commit example +Show commit example options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt index 99b1ba8a4a..ed5ae2522e 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_info_.txt @@ -1,6 +1,6 @@ usage: cz info [-h] -show information about the cz +Show information about the cz options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt index 0f72042f88..546ab51cb3 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_init_.txt @@ -1,6 +1,6 @@ usage: cz init [-h] -init commitizen configuration +Initialize commitizen configuration options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt index 5fa8fe1f79..253da1722c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_ls_.txt @@ -1,6 +1,6 @@ usage: cz ls [-h] -show available commitizens +Show available Commitizens options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt index 6666db4d41..dd05ead81b 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_schema_.txt @@ -1,6 +1,6 @@ usage: cz schema [-h] -show commit schema +Show commit schema options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt index a194615a98..0061a97514 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt @@ -1,16 +1,16 @@ usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] -get the version of the installed commitizen or the current project (default: +Get the version of the installed commitizen or the current project (default: installed commitizen) options: -h, --help show this help message and exit - -r, --report get system information for reporting bugs - -p, --project get the version of the current project - -c, --commitizen get the version of the installed commitizen - -v, --verbose get the version of both the installed commitizen and the - current project - --major get just the major version. Need to be used with --project + -r, --report Output the system information for reporting bugs. + -p, --project Output the version of the current project. + -c, --commitizen Output the version of the installed commitizen. + -v, --verbose Output the version of both the installed commitizen and + the current project. + --major Output just the major version. Must be used with --project or --verbose. - --minor get just the minor version. Need to be used with --project + --minor Output just the minor version. Must be used with --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt index 4cf8e6c91b..c472a040e9 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt @@ -14,68 +14,70 @@ usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] [--allow-no-commit] [MANUAL_VERSION] -bump semantic version based on the git log +Bump semantic version based on the git log positional arguments: - MANUAL_VERSION bump to the given version (e.g: 1.5.3) + MANUAL_VERSION Bump to the given version (e.g., 1.5.3). options: -h, --help show this help message and exit - --dry-run show output to stdout, no commit, no modified files - --files-only bump version in the files from the config - --local-version bump only the local version portion - --changelog, -ch generate the changelog for the newest version - --no-verify this option bypasses the pre-commit and commit-msg - hooks - --yes accept automatically questions done + --dry-run Perform a dry run, without committing or modifying + files. + --files-only Bump version in the `version_files` specified in the + configuration file only. + --local-version Bump version only the local version portion (ignoring + the public version). + --changelog, -ch Generate the changelog for the latest version. + --no-verify Bypass the pre-commit and commit-msg hooks. + --yes Accept automatically answered questions. --tag-format TAG_FORMAT - the format used to tag the commit and read it, use it - in existing projects, wrap around simple quotes + The format used to tag the commit and read it. Use it + in existing projects, and wrap around simple quotes. --bump-message BUMP_MESSAGE - template used to create the release commit, useful - when working with CI + Template used to create the release commit, useful + when working with CI. --prerelease, -pr {alpha,beta,rc} - choose type of prerelease + Type of prerelease. --devrelease, -d DEVRELEASE - specify non-negative integer for dev. release + Specify non-negative integer for dev release. --increment {MAJOR,MINOR,PATCH} - manually specify the desired increment + Specify the desired increment. --increment-mode {linear,exact} - set the method by which the new version is chosen. - 'linear' (default) guesses the next version based on - typical linear version progression, such that bumping - of a pre-release with lower precedence than the - current pre-release phase maintains the current phase - of higher precedence. 'exact' applies the changes that + Set the method by which the new version is chosen. + 'linear' (default) resolves the next version based on + typical linear version progression, where bumping of a + pre-release with lower precedence than the current + pre-release phase maintains the current phase of + higher precedence. 'exact' applies the changes that have been specified (or determined from the commit - log) without interpretation, such that the increment - and pre-release are always honored + log) without interpretation, ensuring the increment + and pre-release are always honored. --check-consistency, -cc - check consistency among versions defined in commitizen - configuration and version_files - --annotated-tag, -at create annotated tag instead of lightweight one + Check consistency among versions defined in Commitizen + configuration file and `version_files`. + --annotated-tag, -at Create annotated tag instead of lightweight one. --annotated-tag-message, -atm ANNOTATED_TAG_MESSAGE - create annotated tag message - --gpg-sign, -s sign tag instead of lightweight one + Create annotated tag message. + --gpg-sign, -s Sign tag instead of lightweight one. --changelog-to-stdout - Output changelog to the stdout + Output changelog to stdout. --git-output-to-stderr - Redirect git output to stderr - --retry retry commit if it fails the 1st time - --major-version-zero keep major version at zero, even for breaking changes + Redirect git output to stderr. + --retry Retry commit if it fails for the first time. + --major-version-zero Keep major version at zero, even for breaking changes. --template, -t TEMPLATE - changelog template file name (relative to the current - working directory) - --extra, -e EXTRA a changelog extra variable (in the form 'key=value') + Changelog template file name (relative to the current + working directory). + --extra, -e EXTRA Changelog extra variables (in the form 'key=value'). --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --prerelease-offset PRERELEASE_OFFSET - start pre-releases with this offset + Start pre-releases with this offset. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --version-type {pep440,semver,semver2} - Deprecated, use --version-scheme instead + Deprecated, use `--version-scheme` instead. --build-metadata BUILD_METADATA - Add additional build-metadata to the version-number - --get-next Determine the next version and write to stdout - --allow-no-commit bump version without eligible commits + Add additional build-metadata to the version-number. + --get-next Determine the next version and write to stdout. + --allow-no-commit Bump version without eligible commits. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt index 91b7f389b5..50ab468d64 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_changelog_.txt @@ -6,36 +6,36 @@ usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--extra EXTRA] [--tag-format TAG_FORMAT] [rev_range] -generate changelog (note that it will overwrite existing file) +Generate changelog (note that it will overwrite existing files) positional arguments: - rev_range generates changelog for the given version (e.g: 1.5.3) - or version range (e.g: 1.5.3..1.7.9) + rev_range Generate changelog for the given version (e.g., 1.5.3) + or version range (e.g., 1.5.3..1.7.9). options: -h, --help show this help message and exit - --dry-run show changelog to stdout + --dry-run Show changelog to stdout. --file-name FILE_NAME - file name of changelog (default: 'CHANGELOG.md') + File name of changelog (default: 'CHANGELOG.md'). --unreleased-version UNRELEASED_VERSION - set the value for the new version (use the tag value), - instead of using unreleased - --incremental generates changelog from last created version, useful - if the changelog has been manually modified + Set the value for the new version (use the tag value), + instead of using unreleased versions. + --incremental Generate changelog from the last created version, + useful if the changelog has been manually modified. --start-rev START_REV - start rev of the changelog. If not set, it will - generate changelog from the start - --merge-prerelease collect all changes from prereleases into next non- - prerelease. If not set, it will include prereleases in - the changelog + Start rev of the changelog. If not set, it will + generate changelog from the beginning. + --merge-prerelease Collect all changes from prereleases into the next + non-prerelease. If not set, it will include + prereleases in the changelog. --version-scheme {pep440,semver,semver2} - choose version scheme + Choose version scheme. --export-template EXPORT_TEMPLATE Export the changelog template into this file instead - of rendering it + of rendering it. --template, -t TEMPLATE - changelog template file name (relative to the current - working directory) - --extra, -e EXTRA a changelog extra variable (in the form 'key=value') + Changelog template file name (relative to the current + working directory). + --extra, -e EXTRA Changelog extra variables (in the form 'key=value'). --tag-format TAG_FORMAT - The format of the tag, wrap around simple quotes + The format of the tag, wrap around simple quotes. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt index 4066748557..6f8297e1ee 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_check_.txt @@ -3,26 +3,27 @@ usage: cz check [-h] [--commit-msg-file COMMIT_MSG_FILE | [--allowed-prefixes [ALLOWED_PREFIXES ...]] [-l MESSAGE_LENGTH_LIMIT] -validates that a commit message matches the commitizen schema +Validate that a commit message matches the commitizen schema options: -h, --help show this help message and exit --commit-msg-file COMMIT_MSG_FILE - ask for the name of the temporal file that contains - the commit message. Using it in a git hook script: - MSG_FILE=$1 + Ask for the name of the temporary file that contains + the commit message. Use it in a git hook script: + MSG_FILE=$1. --rev-range REV_RANGE - a range of git rev to check. e.g, master..HEAD + Validate the commits in the given range of git rev, + e.g., master..HEAD. -d, --use-default-range - check from the default branch to HEAD. e.g, - refs/remotes/origin/master..HEAD + Validate the commits from the default branch to HEAD, + e.g., refs/remotes/origin/master..HEAD. -m, --message MESSAGE - commit message that needs to be checked - --allow-abort allow empty commit messages, which typically abort a - commit + Validate the given commit message. + --allow-abort Allow empty commit messages, which typically abort a + commit. --allowed-prefixes [ALLOWED_PREFIXES ...] - allowed commit message prefixes. If the message starts - by one of these prefixes, the message won't be checked - against the regex + Skip validation for commit messages that start with + the specified prefixes. -l, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit + Restrict the length of the **first line** of the + commit message; 0 for no limit. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt index ba531042aa..cbd5780f6d 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_commit_.txt @@ -2,21 +2,24 @@ usage: cz commit [-h] [--retry] [--no-retry] [--dry-run] [--write-message-to-file FILE_PATH] [-s] [-a] [-e] [-l MESSAGE_LENGTH_LIMIT] [--] -create new commit +Create new commit options: -h, --help show this help message and exit - --retry retry last commit - --no-retry skip retry if retry_after_failure is set to true - --dry-run show output to stdout, no commit, no modified files + --retry Retry the last commit. + --no-retry Skip retry if --retry or `retry_after_failure` is set + to true. + --dry-run Perform a dry run, without committing or modifying + files. --write-message-to-file FILE_PATH - write message to file before committing (can be - combined with --dry-run) - -s, --signoff Deprecated, use 'cz commit -- -s' instead - -a, --all Tell the command to automatically stage files that - have been modified and deleted, but new files you have - not told Git about are not affected. - -e, --edit edit the commit message before committing + Write message to FILE_PATH before committing (can be + used with --dry-run). + -s, --signoff Deprecated, use `cz commit -- -s` instead. + -a, --all Automatically stage files that have been modified and + deleted, but new files you have not told Git about are + not affected. + -e, --edit Edit the commit message before committing. -l, --message-length-limit MESSAGE_LENGTH_LIMIT - length limit of the commit message; 0 for no limit - -- Positional arguments separator (recommended) + Set the length limit of the commit message; 0 for no + limit. + -- Positional arguments separator (recommended). diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt index b9bf7f84fc..8a0f1c9d94 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_example_.txt @@ -1,6 +1,6 @@ usage: cz example [-h] -show commit example +Show commit example options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt index 99b1ba8a4a..ed5ae2522e 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_info_.txt @@ -1,6 +1,6 @@ usage: cz info [-h] -show information about the cz +Show information about the cz options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt index 0f72042f88..546ab51cb3 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_init_.txt @@ -1,6 +1,6 @@ usage: cz init [-h] -init commitizen configuration +Initialize commitizen configuration options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt index 5fa8fe1f79..253da1722c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_ls_.txt @@ -1,6 +1,6 @@ usage: cz ls [-h] -show available commitizens +Show available Commitizens options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt index 6666db4d41..dd05ead81b 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_schema_.txt @@ -1,6 +1,6 @@ usage: cz schema [-h] -show commit schema +Show commit schema options: -h, --help show this help message and exit diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt index a194615a98..0061a97514 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt @@ -1,16 +1,16 @@ usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] -get the version of the installed commitizen or the current project (default: +Get the version of the installed commitizen or the current project (default: installed commitizen) options: -h, --help show this help message and exit - -r, --report get system information for reporting bugs - -p, --project get the version of the current project - -c, --commitizen get the version of the installed commitizen - -v, --verbose get the version of both the installed commitizen and the - current project - --major get just the major version. Need to be used with --project + -r, --report Output the system information for reporting bugs. + -p, --project Output the version of the current project. + -c, --commitizen Output the version of the installed commitizen. + -v, --verbose Output the version of both the installed commitizen and + the current project. + --major Output just the major version. Must be used with --project or --verbose. - --minor get just the minor version. Need to be used with --project + --minor Output just the minor version. Must be used with --project or --verbose. From ac2b31d769d8c46d37a72bbc8b1432d0513fa37e Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 14:40:52 +0800 Subject: [PATCH 209/221] fix(message_length_limit): align the behavior of message_length_limit (#1813) --- commitizen/commands/check.py | 4 +- commitizen/commands/commit.py | 22 ++++++---- commitizen/cz/base.py | 2 +- commitizen/defaults.py | 4 +- tests/commands/test_check_command.py | 59 +-------------------------- tests/commands/test_commit_command.py | 2 +- tests/test_conf.py | 4 +- 7 files changed, 23 insertions(+), 74 deletions(-) diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index 8ec5b47f8d..182839910d 100644 --- a/commitizen/commands/check.py +++ b/commitizen/commands/check.py @@ -20,7 +20,7 @@ class CheckArgs(TypedDict, total=False): commit_msg: str rev_range: str allow_abort: bool - message_length_limit: int | None + message_length_limit: int allowed_prefixes: list[str] message: str use_default_range: bool @@ -46,7 +46,7 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N self.use_default_range = bool(arguments.get("use_default_range")) self.max_msg_length = arguments.get( - "message_length_limit", config.settings.get("message_length_limit", None) + "message_length_limit", config.settings.get("message_length_limit", 0) ) # we need to distinguish between None and [], which is a valid value diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 3894d0b77e..5776af4201 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -36,7 +36,7 @@ class CommitArgs(TypedDict, total=False): dry_run: bool edit: bool extra_cli_args: str - message_length_limit: int | None + message_length_limit: int no_retry: bool signoff: bool write_message_to_file: Path | None @@ -83,19 +83,23 @@ def _get_message_by_prompt_commit_questions(self) -> str: raise NoAnswersError() message = self.cz.message(answers) - if limit := self.arguments.get( - "message_length_limit", self.config.settings.get("message_length_limit", 0) - ): - self._validate_subject_length(message=message, length_limit=limit) - + self._validate_subject_length(message) return message - def _validate_subject_length(self, *, message: str, length_limit: int) -> None: + def _validate_subject_length(self, message: str) -> None: + message_length_limit = self.arguments.get( + "message_length_limit", self.config.settings.get("message_length_limit", 0) + ) # By the contract, message_length_limit is set to 0 for no limit + if ( + message_length_limit is None or message_length_limit <= 0 + ): # do nothing for no limit + return + subject = message.partition("\n")[0].strip() - if len(subject) > length_limit: + if len(subject) > message_length_limit: raise CommitMessageLengthExceededError( - f"Length of commit message exceeds limit ({len(subject)}/{length_limit}), subject: '{subject}'" + f"Length of commit message exceeds limit ({len(subject)}/{message_length_limit}), subject: '{subject}'" ) def manual_edit(self, message: str) -> str: diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index 90633c42e6..5e7f2663ca 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -130,7 +130,7 @@ def validate_commit_message( if any(map(commit_msg.startswith, allowed_prefixes)): return ValidationResult(True, []) - if max_msg_length is not None: + if max_msg_length is not None and max_msg_length > 0: msg_len = len(commit_msg.partition("\n")[0].strip()) if msg_len > max_msg_length: # TODO: capitalize the first letter of the error message for consistency in v5 diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 6de41f63d1..4865ccc188 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -48,7 +48,7 @@ class Settings(TypedDict, total=False): ignored_tag_formats: Sequence[str] legacy_tag_formats: Sequence[str] major_version_zero: bool - message_length_limit: int | None + message_length_limit: int name: str post_bump_hooks: list[str] | None pre_bump_hooks: list[str] | None @@ -114,7 +114,7 @@ class Settings(TypedDict, total=False): "template": None, # default provided by plugin "extras": {}, "breaking_change_exclamation_in_title": False, - "message_length_limit": None, # None for no limit + "message_length_limit": 0, # 0 for no limit } MAJOR = "MAJOR" diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py index b5e3fd2b08..f225e912ea 100644 --- a/tests/commands/test_check_command.py +++ b/tests/commands/test_check_command.py @@ -7,7 +7,7 @@ from commitizen import commands, git from commitizen.cz import registry -from commitizen.cz.base import BaseCommitizen, ValidationResult +from commitizen.cz.base import BaseCommitizen from commitizen.exceptions import ( CommitMessageLengthExceededError, InvalidCommandArgumentError, @@ -16,7 +16,6 @@ ) if TYPE_CHECKING: - import re from collections.abc import Mapping from pytest_mock import MockFixture, MockType @@ -385,7 +384,7 @@ def test_check_command_cli_overrides_config_message_length_limit( ): message = "fix(scope): some commit message" config.settings["message_length_limit"] = len(message) - 1 - for message_length_limit in [len(message) + 1, None]: + for message_length_limit in [len(message) + 1, 0]: success_mock.reset_mock() commands.Check( config=config, @@ -419,60 +418,6 @@ def example(self) -> str: def info(self) -> str: return "Commit message must start with an issue number like ABC-123" - def validate_commit_message( - self, - *, - commit_msg: str, - pattern: re.Pattern[str], - allow_abort: bool, - allowed_prefixes: list[str], - max_msg_length: int | None, - commit_hash: str, - ) -> ValidationResult: - """Validate commit message against the pattern.""" - if not commit_msg: - return ValidationResult( - allow_abort, [] if allow_abort else ["commit message is empty"] - ) - - if any(map(commit_msg.startswith, allowed_prefixes)): - return ValidationResult(True, []) - - if max_msg_length: - msg_len = len(commit_msg.partition("\n")[0].strip()) - if msg_len > max_msg_length: - # TODO: capitalize the first letter of the error message for consistency in v5 - raise CommitMessageLengthExceededError( - f"commit validation: failed!\n" - f"commit message length exceeds the limit.\n" - f'commit "{commit_hash}": "{commit_msg}"\n' - f"message length limit: {max_msg_length} (actual: {msg_len})" - ) - - return ValidationResult( - bool(pattern.match(commit_msg)), [f"pattern: {pattern.pattern}"] - ) - - def format_exception_message( - self, invalid_commits: list[tuple[git.GitCommit, list]] - ) -> str: - """Format commit errors.""" - displayed_msgs_content = "\n".join( - [ - ( - f'commit "{commit.rev}": "{commit.message}"\nerrors:\n\n'.join( - f"- {error}" for error in errors - ) - ) - for (commit, errors) in invalid_commits - ] - ) - return ( - "commit validation: failed!\n" - "please enter a commit message in the commitizen format.\n" - f"{displayed_msgs_content}" - ) - @pytest.fixture def use_cz_custom_validator(mocker): diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index 87c7aca42c..89a9224b85 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -363,5 +363,5 @@ def test_commit_command_with_config_message_length_limit( success_mock.assert_called_once() success_mock.reset_mock() - commands.Commit(config, {"message_length_limit": None})() + commands.Commit(config, {"message_length_limit": 0})() success_mock.assert_called_once() diff --git a/tests/test_conf.py b/tests/test_conf.py index 6e4256f162..ee5eba5b3c 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -106,7 +106,7 @@ "template": None, "extras": {}, "breaking_change_exclamation_in_title": False, - "message_length_limit": None, + "message_length_limit": 0, } _new_settings: dict[str, Any] = { @@ -146,7 +146,7 @@ "template": None, "extras": {}, "breaking_change_exclamation_in_title": False, - "message_length_limit": None, + "message_length_limit": 0, } From 215fe364ac2f085af39a67d1e0f6fdecd285498d Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 14:48:33 +0800 Subject: [PATCH 210/221] test: update test files --- tests/test_cli/test_no_argv_py_3_10_.txt | 38 ++++++++++++------------ tests/test_cli/test_no_argv_py_3_11_.txt | 38 ++++++++++++------------ tests/test_cli/test_no_argv_py_3_12_.txt | 38 ++++++++++++------------ tests/test_cli/test_no_argv_py_3_13_.txt | 38 ++++++++++++------------ tests/test_cli/test_no_argv_py_3_14_.txt | 38 ++++++++++++------------ 5 files changed, 95 insertions(+), 95 deletions(-) diff --git a/tests/test_cli/test_no_argv_py_3_10_.txt b/tests/test_cli/test_no_argv_py_3_10_.txt index 691c75a86f..69f410e96d 100644 --- a/tests/test_cli/test_no_argv_py_3_10_.txt +++ b/tests/test_cli/test_no_argv_py_3_10_.txt @@ -7,28 +7,28 @@ For more information, please visit https://commitizen-tools.github.io/commitizen options: -h, --help show this help message and exit - --config CONFIG the path of configuration file - --debug use debug mode - -n NAME, --name NAME use the given commitizen (default: - cz_conventional_commits) + --config CONFIG The path to the configuration file. + --debug Use debug mode. + -n NAME, --name NAME Use the given commitizen (default: + cz_conventional_commits). -nr NO_RAISE, --no-raise NO_RAISE - comma separated error codes that won't raise error, - e.g: cz -nr 1,2,3 bump. See codes at + Comma-separated error codes that won't raise error, + e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - init init commitizen configuration - commit (c) create new commit - ls show available commitizens - example show commit example - info show information about the cz - schema show commit schema - bump bump semantic version based on the git log - changelog (ch) generate changelog (note that it will overwrite - existing file) - check validates that a commit message matches the commitizen - schema - version get the version of the installed commitizen or the - current project (default: installed commitizen) + init Initialize commitizen configuration. + commit (c) Create new commit. + ls Show available Commitizens. + example Show commit example. + info Show information about the cz. + schema Show commit schema. + bump Bump semantic version based on the git log. + changelog (ch) Generate changelog (note that it will overwrite + existing files). + check Validate that a commit message matches the commitizen + schema. + version Get the version of the installed commitizen or the + current project (default: installed commitizen). diff --git a/tests/test_cli/test_no_argv_py_3_11_.txt b/tests/test_cli/test_no_argv_py_3_11_.txt index 691c75a86f..69f410e96d 100644 --- a/tests/test_cli/test_no_argv_py_3_11_.txt +++ b/tests/test_cli/test_no_argv_py_3_11_.txt @@ -7,28 +7,28 @@ For more information, please visit https://commitizen-tools.github.io/commitizen options: -h, --help show this help message and exit - --config CONFIG the path of configuration file - --debug use debug mode - -n NAME, --name NAME use the given commitizen (default: - cz_conventional_commits) + --config CONFIG The path to the configuration file. + --debug Use debug mode. + -n NAME, --name NAME Use the given commitizen (default: + cz_conventional_commits). -nr NO_RAISE, --no-raise NO_RAISE - comma separated error codes that won't raise error, - e.g: cz -nr 1,2,3 bump. See codes at + Comma-separated error codes that won't raise error, + e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - init init commitizen configuration - commit (c) create new commit - ls show available commitizens - example show commit example - info show information about the cz - schema show commit schema - bump bump semantic version based on the git log - changelog (ch) generate changelog (note that it will overwrite - existing file) - check validates that a commit message matches the commitizen - schema - version get the version of the installed commitizen or the - current project (default: installed commitizen) + init Initialize commitizen configuration. + commit (c) Create new commit. + ls Show available Commitizens. + example Show commit example. + info Show information about the cz. + schema Show commit schema. + bump Bump semantic version based on the git log. + changelog (ch) Generate changelog (note that it will overwrite + existing files). + check Validate that a commit message matches the commitizen + schema. + version Get the version of the installed commitizen or the + current project (default: installed commitizen). diff --git a/tests/test_cli/test_no_argv_py_3_12_.txt b/tests/test_cli/test_no_argv_py_3_12_.txt index 691c75a86f..69f410e96d 100644 --- a/tests/test_cli/test_no_argv_py_3_12_.txt +++ b/tests/test_cli/test_no_argv_py_3_12_.txt @@ -7,28 +7,28 @@ For more information, please visit https://commitizen-tools.github.io/commitizen options: -h, --help show this help message and exit - --config CONFIG the path of configuration file - --debug use debug mode - -n NAME, --name NAME use the given commitizen (default: - cz_conventional_commits) + --config CONFIG The path to the configuration file. + --debug Use debug mode. + -n NAME, --name NAME Use the given commitizen (default: + cz_conventional_commits). -nr NO_RAISE, --no-raise NO_RAISE - comma separated error codes that won't raise error, - e.g: cz -nr 1,2,3 bump. See codes at + Comma-separated error codes that won't raise error, + e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - init init commitizen configuration - commit (c) create new commit - ls show available commitizens - example show commit example - info show information about the cz - schema show commit schema - bump bump semantic version based on the git log - changelog (ch) generate changelog (note that it will overwrite - existing file) - check validates that a commit message matches the commitizen - schema - version get the version of the installed commitizen or the - current project (default: installed commitizen) + init Initialize commitizen configuration. + commit (c) Create new commit. + ls Show available Commitizens. + example Show commit example. + info Show information about the cz. + schema Show commit schema. + bump Bump semantic version based on the git log. + changelog (ch) Generate changelog (note that it will overwrite + existing files). + check Validate that a commit message matches the commitizen + schema. + version Get the version of the installed commitizen or the + current project (default: installed commitizen). diff --git a/tests/test_cli/test_no_argv_py_3_13_.txt b/tests/test_cli/test_no_argv_py_3_13_.txt index f880f99772..b47528ec3e 100644 --- a/tests/test_cli/test_no_argv_py_3_13_.txt +++ b/tests/test_cli/test_no_argv_py_3_13_.txt @@ -6,28 +6,28 @@ For more information, please visit https://commitizen-tools.github.io/commitizen options: -h, --help show this help message and exit - --config CONFIG the path of configuration file - --debug use debug mode - -n, --name NAME use the given commitizen (default: - cz_conventional_commits) + --config CONFIG The path to the configuration file. + --debug Use debug mode. + -n, --name NAME Use the given commitizen (default: + cz_conventional_commits). -nr, --no-raise NO_RAISE - comma separated error codes that won't raise error, - e.g: cz -nr 1,2,3 bump. See codes at + Comma-separated error codes that won't raise error, + e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - init init commitizen configuration - commit (c) create new commit - ls show available commitizens - example show commit example - info show information about the cz - schema show commit schema - bump bump semantic version based on the git log - changelog (ch) generate changelog (note that it will overwrite - existing file) - check validates that a commit message matches the commitizen - schema - version get the version of the installed commitizen or the - current project (default: installed commitizen) + init Initialize commitizen configuration. + commit (c) Create new commit. + ls Show available Commitizens. + example Show commit example. + info Show information about the cz. + schema Show commit schema. + bump Bump semantic version based on the git log. + changelog (ch) Generate changelog (note that it will overwrite + existing files). + check Validate that a commit message matches the commitizen + schema. + version Get the version of the installed commitizen or the + current project (default: installed commitizen). diff --git a/tests/test_cli/test_no_argv_py_3_14_.txt b/tests/test_cli/test_no_argv_py_3_14_.txt index f880f99772..b47528ec3e 100644 --- a/tests/test_cli/test_no_argv_py_3_14_.txt +++ b/tests/test_cli/test_no_argv_py_3_14_.txt @@ -6,28 +6,28 @@ For more information, please visit https://commitizen-tools.github.io/commitizen options: -h, --help show this help message and exit - --config CONFIG the path of configuration file - --debug use debug mode - -n, --name NAME use the given commitizen (default: - cz_conventional_commits) + --config CONFIG The path to the configuration file. + --debug Use debug mode. + -n, --name NAME Use the given commitizen (default: + cz_conventional_commits). -nr, --no-raise NO_RAISE - comma separated error codes that won't raise error, - e.g: cz -nr 1,2,3 bump. See codes at + Comma-separated error codes that won't raise error, + e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - init init commitizen configuration - commit (c) create new commit - ls show available commitizens - example show commit example - info show information about the cz - schema show commit schema - bump bump semantic version based on the git log - changelog (ch) generate changelog (note that it will overwrite - existing file) - check validates that a commit message matches the commitizen - schema - version get the version of the installed commitizen or the - current project (default: installed commitizen) + init Initialize commitizen configuration. + commit (c) Create new commit. + ls Show available Commitizens. + example Show commit example. + info Show information about the cz. + schema Show commit schema. + bump Bump semantic version based on the git log. + changelog (ch) Generate changelog (note that it will overwrite + existing files). + check Validate that a commit message matches the commitizen + schema. + version Get the version of the installed commitizen or the + current project (default: installed commitizen). From 2cd841891c670ffba9befd8980cae395e284f75b Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 14:51:26 +0800 Subject: [PATCH 211/221] fix: add pytest ruff rule PT and fix missing deprecation warning (#1826) --- commitizen/changelog_formats/__init__.py | 7 ++++ pyproject.toml | 13 ++++++- tests/commands/test_init_command.py | 15 ++++---- tests/test_bump_hooks.py | 4 +-- tests/test_bump_update_version_in_files.py | 1 - tests/test_conf.py | 22 ++++++------ tests/test_deprecated.py | 14 ++++---- tests/test_factory.py | 9 +++-- tests/test_version_scheme_pep440.py | 41 ---------------------- tests/test_version_scheme_semver.py | 10 ------ tests/test_version_scheme_semver2.py | 40 --------------------- tests/test_version_schemes.py | 4 +-- 12 files changed, 54 insertions(+), 126 deletions(-) diff --git a/commitizen/changelog_formats/__init__.py b/commitizen/changelog_formats/__init__.py index c92a43087c..26e697cadd 100644 --- a/commitizen/changelog_formats/__init__.py +++ b/commitizen/changelog_formats/__init__.py @@ -1,5 +1,6 @@ from __future__ import annotations +import warnings from importlib import metadata from typing import TYPE_CHECKING, ClassVar, Protocol @@ -99,5 +100,11 @@ def _guess_changelog_format(filename: str | None) -> type[ChangelogFormat] | Non def __getattr__(name: str) -> Callable[[str], type[ChangelogFormat] | None]: if name == "guess_changelog_format": + warnings.warn( + "guess_changelog_format is deprecated and will be removed in v5. " + "Use _guess_changelog_format instead.", + DeprecationWarning, + stacklevel=2, + ) return _guess_changelog_format raise AttributeError(f"module {__name__} has no attribute {name}") diff --git a/pyproject.toml b/pyproject.toml index 855bfb6c72..18ebe46362 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -223,6 +223,8 @@ select = [ "RUF022", # unused-noqa "RUF100", + # flake8-pytest-style + "PT", # Checks for uses of the assert keyword. "S101", # flake8-type-checking (TC) @@ -233,7 +235,16 @@ select = [ "TC005", "TC006", ] -ignore = ["E501", "D1", "D415"] +ignore = [ + "E501", + "D1", + "D415", + "PT006", # TODO(bearomorphism): enable this rule + "PT007", # TODO(bearomorphism): enable this rule + "PT011", # TODO(bearomorphism): enable this rule + "PT022", # TODO(bearomorphism): enable this rule + "PT030", # TODO(bearomorphism): enable this rule +] extend-safe-fixes = [ "TC", # Move imports inside/outside TYPE_CHECKING blocks "UP", # Update syntaxes for current Python version recommendations diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 8398e784bc..4c7f3923a7 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -133,7 +133,7 @@ def pre_commit_installed(mocker: MockFixture): ) -@pytest.fixture(scope="function", params=["pyproject.toml", ".cz.json", ".cz.yaml"]) +@pytest.fixture(params=["pyproject.toml", ".cz.json", ".cz.yaml"]) def default_choice(request, mocker: MockFixture): mocker.patch( "questionary.select", @@ -150,7 +150,7 @@ def default_choice(request, mocker: MockFixture): "questionary.checkbox", return_value=FakeQuestion(["commit-msg", "pre-push"]), ) - yield request.param + return request.param def check_cz_config(config_filepath: str): @@ -179,7 +179,7 @@ def check_pre_commit_config(expected: list[dict[str, Any]]): @pytest.mark.usefixtures("pre_commit_installed") class TestPreCommitCases: def test_no_existing_pre_commit_config( - _, default_choice: str, tmpdir, config: BaseConfig + self, default_choice: str, tmpdir, config: BaseConfig ): with tmpdir.as_cwd(): commands.Init(config)() @@ -187,7 +187,7 @@ def test_no_existing_pre_commit_config( check_pre_commit_config([cz_hook_config]) def test_empty_pre_commit_config( - _, default_choice: str, tmpdir, config: BaseConfig + self, default_choice: str, tmpdir, config: BaseConfig ): with tmpdir.as_cwd(): p = tmpdir.join(pre_commit_config_filename) @@ -198,7 +198,7 @@ def test_empty_pre_commit_config( check_pre_commit_config([cz_hook_config]) def test_pre_commit_config_without_cz_hook( - _, default_choice: str, tmpdir, config: BaseConfig + self, default_choice: str, tmpdir, config: BaseConfig ): existing_hook_config = { "repo": "https://github.com/pre-commit/pre-commit-hooks", @@ -215,7 +215,7 @@ def test_pre_commit_config_without_cz_hook( check_pre_commit_config([existing_hook_config, cz_hook_config]) def test_cz_hook_exists_in_pre_commit_config( - _, default_choice: str, tmpdir, config: BaseConfig + self, default_choice: str, tmpdir, config: BaseConfig ): with tmpdir.as_cwd(): p = tmpdir.join(pre_commit_config_filename) @@ -228,8 +228,9 @@ def test_cz_hook_exists_in_pre_commit_config( class TestNoPreCommitInstalled: + @pytest.mark.usefixtures("default_choice") def test_pre_commit_not_installed( - _, mocker: MockFixture, config: BaseConfig, default_choice: str, tmpdir + self, mocker: MockFixture, config: BaseConfig, tmpdir ): # Assume `pre-commit` is not installed mocker.patch( diff --git a/tests/test_bump_hooks.py b/tests/test_bump_hooks.py index 70ed7fe0b1..739d1ce6ad 100644 --- a/tests/test_bump_hooks.py +++ b/tests/test_bump_hooks.py @@ -38,5 +38,5 @@ def test_run_error(mocker: MockFixture): def test_format_env(): result = hooks._format_env("TEST_", {"foo": "bar", "bar": "baz"}) - assert "TEST_FOO" in result and result["TEST_FOO"] == "bar" - assert "TEST_BAR" in result and result["TEST_BAR"] == "baz" + assert result["TEST_FOO"] == "bar" + assert result["TEST_BAR"] == "baz" diff --git a/tests/test_bump_update_version_in_files.py b/tests/test_bump_update_version_in_files.py index 2cc464e8f1..8fd4c465b8 100644 --- a/tests/test_bump_update_version_in_files.py +++ b/tests/test_bump_update_version_in_files.py @@ -57,7 +57,6 @@ def docker_compose_file(sample_file: SampleFileFixture) -> Path: @pytest.fixture( - scope="function", params=( "multiple_versions_to_update_pyproject.toml", "multiple_versions_to_update_pyproject_wo_eol.toml", diff --git a/tests/test_conf.py b/tests/test_conf.py index ee5eba5b3c..99d19793cd 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -184,16 +184,16 @@ class TestReadCfg: @pytest.mark.parametrize( "config_files_manager", defaults.CONFIG_FILES, indirect=True ) - def test_load_conf(_, config_files_manager): + def test_load_conf(self, config_files_manager): cfg = config.read_cfg() assert cfg.settings == _settings - def test_conf_returns_default_when_no_files(_, tmpdir): + def test_conf_returns_default_when_no_files(self, tmpdir): with tmpdir.as_cwd(): cfg = config.read_cfg() assert cfg.settings == defaults.DEFAULT_SETTINGS - def test_load_empty_pyproject_toml_and_cz_toml_with_config(_, tmpdir): + def test_load_empty_pyproject_toml_and_cz_toml_with_config(self, tmpdir): with tmpdir.as_cwd(): p = tmpdir.join("pyproject.toml") p.write("") @@ -203,7 +203,7 @@ def test_load_empty_pyproject_toml_and_cz_toml_with_config(_, tmpdir): cfg = config.read_cfg() assert cfg.settings == _settings - def test_load_pyproject_toml_from_config_argument(_, tmpdir): + def test_load_pyproject_toml_from_config_argument(self, tmpdir): with tmpdir.as_cwd(): _not_root_path = tmpdir.mkdir("not_in_root").join("pyproject.toml") _not_root_path.write(PYPROJECT) @@ -211,7 +211,7 @@ def test_load_pyproject_toml_from_config_argument(_, tmpdir): cfg = config.read_cfg(filepath="./not_in_root/pyproject.toml") assert cfg.settings == _settings - def test_load_cz_json_not_from_config_argument(_, tmpdir): + def test_load_cz_json_not_from_config_argument(self, tmpdir): with tmpdir.as_cwd(): _not_root_path = tmpdir.mkdir("not_in_root").join(".cz.json") _not_root_path.write(JSON_STR) @@ -220,7 +220,7 @@ def test_load_cz_json_not_from_config_argument(_, tmpdir): json_cfg_by_class = JsonConfig(data=JSON_STR, path=_not_root_path) assert cfg.settings == json_cfg_by_class.settings - def test_load_cz_yaml_not_from_config_argument(_, tmpdir): + def test_load_cz_yaml_not_from_config_argument(self, tmpdir): with tmpdir.as_cwd(): _not_root_path = tmpdir.mkdir("not_in_root").join(".cz.yaml") _not_root_path.write(YAML_STR) @@ -229,7 +229,7 @@ def test_load_cz_yaml_not_from_config_argument(_, tmpdir): yaml_cfg_by_class = YAMLConfig(data=YAML_STR, path=_not_root_path) assert cfg.settings == yaml_cfg_by_class._settings - def test_load_empty_pyproject_toml_from_config_argument(_, tmpdir): + def test_load_empty_pyproject_toml_from_config_argument(self, tmpdir): with tmpdir.as_cwd(): _not_root_path = tmpdir.mkdir("not_in_root").join("pyproject.toml") _not_root_path.write("") @@ -260,7 +260,7 @@ class TestWarnMultipleConfigFiles: ], ) def test_warn_multiple_config_files_same_dir( - _, tmpdir, capsys, files, expected_path, should_warn + self, tmpdir, capsys, files, expected_path, should_warn ): """Test warning when multiple config files exist in same directory.""" with tmpdir.as_cwd(): @@ -296,7 +296,7 @@ def test_warn_multiple_config_files_same_dir( ], ) def test_warn_same_filename_different_directories_with_git( - _, tmpdir, capsys, config_file, content + self, tmpdir, capsys, config_file, content ): """Test warning when same config filename exists in the current directory and in the git root.""" with tmpdir.as_cwd(): @@ -317,7 +317,7 @@ def test_warn_same_filename_different_directories_with_git( assert f"Using config file: '{config_file}'" in captured.err assert cfg.path == Path(config_file) - def test_no_warn_with_explicit_config_path(_, tmpdir, capsys): + def test_no_warn_with_explicit_config_path(self, tmpdir, capsys): """Test that no warning is issued when user explicitly specifies config.""" with tmpdir.as_cwd(): # Create multiple config files @@ -352,7 +352,7 @@ def test_no_warn_with_explicit_config_path(_, tmpdir, capsys): ], ) def test_no_warn_with_single_config_file( - _, tmpdir, capsys, config_file, content, with_git + self, tmpdir, capsys, config_file, content, with_git ): """Test that no warning is issued when user explicitly specifies config.""" with tmpdir.as_cwd(): diff --git a/tests/test_deprecated.py b/tests/test_deprecated.py index 41bea81a73..6e695c300c 100644 --- a/tests/test_deprecated.py +++ b/tests/test_deprecated.py @@ -5,26 +5,28 @@ def test_getattr_deprecated_vars(): # Test each deprecated variable - with pytest.warns(DeprecationWarning) as record: + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert defaults.bump_pattern == defaults.BUMP_PATTERN + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert defaults.bump_map == defaults.BUMP_MAP + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert ( defaults.bump_map_major_version_zero == defaults.BUMP_MAP_MAJOR_VERSION_ZERO ) + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert defaults.bump_message == defaults.BUMP_MESSAGE + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert defaults.change_type_order == defaults.CHANGE_TYPE_ORDER + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert defaults.encoding == defaults.ENCODING + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert defaults.name == defaults.DEFAULT_SETTINGS["name"] + with pytest.warns(DeprecationWarning, match="is deprecated and will be removed"): assert ( changelog_formats._guess_changelog_format == changelog_formats.guess_changelog_format ) - # Verify warning messages - assert len(record) == 7 - for warning in record: - assert "is deprecated and will be removed" in str(warning.message) - def test_getattr_non_existent(): # Test non-existent attribute diff --git a/tests/test_factory.py b/tests/test_factory.py index 20ce49d781..303ae4e728 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -52,14 +52,13 @@ class Plugin: pass ) sys.path.append(tmp_path.as_posix()) - with pytest.warns(UserWarning) as record: + with pytest.warns( + UserWarning, + match="Legacy plugin 'cz_legacy' has been ignored: please expose it the 'commitizen.plugin' entrypoint", + ): discovered_plugins = discover_plugins([tmp_path.as_posix()]) sys.path.pop() - assert ( - record[0].message.args[0] - == "Legacy plugin 'cz_legacy' has been ignored: please expose it the 'commitizen.plugin' entrypoint" - ) assert "cz_legacy" not in discovered_plugins diff --git a/tests/test_version_scheme_pep440.py b/tests/test_version_scheme_pep440.py index 0ce4f81545..3c15eeb4a9 100644 --- a/tests/test_version_scheme_pep440.py +++ b/tests/test_version_scheme_pep440.py @@ -249,16 +249,6 @@ ), "0.1.1.dev1", ), - ( - VersionSchemeTestArgs( - current_version="0.1.1", - increment="MINOR", - prerelease=None, - prerelease_offset=0, - devrelease=None, - ), - "0.2.0", - ), ( VersionSchemeTestArgs( current_version="0.2.0", @@ -733,26 +723,6 @@ ), "1.1.0a0", ), - ( - VersionSchemeTestArgs( - current_version="1.1.0a0", - increment="PATCH", - prerelease="alpha", - prerelease_offset=0, - devrelease=None, - ), - "1.1.0a1", - ), - ( - VersionSchemeTestArgs( - current_version="1.1.0a1", - increment="MINOR", - prerelease="alpha", - prerelease_offset=0, - devrelease=None, - ), - "1.1.0a2", - ), ( VersionSchemeTestArgs( current_version="1.1.0a2", @@ -1020,17 +990,6 @@ ), "3.1.4rc0", ), - # - ( - VersionSchemeTestArgs( - current_version="3.1.4", - increment=None, - prerelease="alpha", - prerelease_offset=0, - devrelease=None, - ), - "3.1.4a0", - ), ( VersionSchemeTestArgs( current_version="3.1.4a0", diff --git a/tests/test_version_scheme_semver.py b/tests/test_version_scheme_semver.py index 8a163d4f6b..1a75cd3eae 100644 --- a/tests/test_version_scheme_semver.py +++ b/tests/test_version_scheme_semver.py @@ -271,16 +271,6 @@ ), "0.1.1-dev1", ), - ( - VersionSchemeTestArgs( - current_version="0.1.1", - increment="MINOR", - prerelease=None, - prerelease_offset=0, - devrelease=None, - ), - "0.2.0", - ), ( VersionSchemeTestArgs( current_version="0.2.0", diff --git a/tests/test_version_scheme_semver2.py b/tests/test_version_scheme_semver2.py index 4a35e6470a..6ce00e06ed 100644 --- a/tests/test_version_scheme_semver2.py +++ b/tests/test_version_scheme_semver2.py @@ -220,16 +220,6 @@ ), "1.0.0-beta.1", ), - ( - VersionSchemeTestArgs( - current_version="1.0.0-alpha.1", - increment=None, - prerelease="alpha", - prerelease_offset=0, - devrelease=None, - ), - "1.0.0-alpha.2", - ), ( VersionSchemeTestArgs( current_version="1", @@ -271,16 +261,6 @@ ), "0.1.1-dev.1", ), - ( - VersionSchemeTestArgs( - current_version="0.1.1", - increment="MINOR", - prerelease=None, - prerelease_offset=0, - devrelease=None, - ), - "0.2.0", - ), ( VersionSchemeTestArgs( current_version="0.2.0", @@ -391,16 +371,6 @@ ), "1.0.0-alpha.1", ), - ( - VersionSchemeTestArgs( - current_version="1.0.0-alpha.1", - increment=None, - prerelease="alpha", - prerelease_offset=0, - devrelease=None, - ), - "1.0.0-alpha.2", - ), ( VersionSchemeTestArgs( current_version="1.0.0-alpha.1", @@ -451,16 +421,6 @@ ), "1.0.0-beta.1", ), - ( - VersionSchemeTestArgs( - current_version="1.0.0-beta.1", - increment=None, - prerelease="rc", - prerelease_offset=0, - devrelease=None, - ), - "1.0.0-rc.0", - ), ( VersionSchemeTestArgs( current_version="1.0.0-rc.0", diff --git a/tests/test_version_schemes.py b/tests/test_version_schemes.py index 7b1ec7579a..0f38f90d80 100644 --- a/tests/test_version_schemes.py +++ b/tests/test_version_schemes.py @@ -38,7 +38,7 @@ def test_raise_for_unknown_version_scheme(config: BaseConfig): def test_version_scheme_from_deprecated_config(config: BaseConfig): config.settings["version_type"] = "semver" - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, match="Please use `version_scheme` instead"): scheme = get_version_scheme(config.settings) assert scheme is SemVer @@ -46,7 +46,7 @@ def test_version_scheme_from_deprecated_config(config: BaseConfig): def test_version_scheme_from_config_priority(config: BaseConfig): config.settings["version_scheme"] = "pep440" config.settings["version_type"] = "semver" - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, match="Please use `version_scheme` instead"): scheme = get_version_scheme(config.settings) assert scheme is Pep440 From 908a10ec910a8c9dab36f4b9bb4e936f356769b5 Mon Sep 17 00:00:00 2001 From: Yazdan Ranjbar <yazdanra@icloud.com> Date: Sat, 31 Jan 2026 01:52:32 -0500 Subject: [PATCH 212/221] feat(tags): enable version schemes with less than 3 components (#1705) Co-authored-by: Wei Lee <weilee.rx@gmail.com> Co-authored-by: Benedikt Ziegler <benediktziegler@gmail.com> --- commitizen/tags.py | 21 +++++- docs/commands/bump.md | 13 ++++ tests/commands/test_bump_command.py | 29 ++++++++ tests/test_tags.py | 101 ++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 tests/test_tags.py diff --git a/commitizen/tags.py b/commitizen/tags.py index 68c74a72e6..dcddbd335f 100644 --- a/commitizen/tags.py +++ b/commitizen/tags.py @@ -228,7 +228,7 @@ def normalize_tag( version = self.scheme(version) if isinstance(version, str) else version tag_format = tag_format or self.tag_format - major, minor, patch = version.release + major, minor, patch = (list(version.release) + [0, 0, 0])[:3] prerelease = version.prerelease or "" t = Template(tag_format) @@ -245,6 +245,25 @@ def find_tag_for( ) -> GitTag | None: """Find the first matching tag for a given version.""" version = self.scheme(version) if isinstance(version, str) else version + release = version.release + + # If the requested version is incomplete (e.g., "1.2"), try to find the latest + # matching tag that shares the provided prefix. + if len(release) < 3: + matching_versions: list[tuple[Version, GitTag]] = [] + for tag in tags: + try: + tag_version = self.extract_version(tag) + except InvalidVersion: + continue + if tag_version.release[: len(release)] != release: + continue + matching_versions.append((tag_version, tag)) + + if matching_versions: + _, latest_tag = max(matching_versions, key=lambda vt: vt[0]) + return latest_tag + possible_tags = set(self.normalize_tag(version, f) for f in self.tag_formats) candidates = [t for t in tags if t.name in possible_tags] if len(candidates) > 1: diff --git a/docs/commands/bump.md b/docs/commands/bump.md index e7a7c04030..03fc83402c 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -65,6 +65,19 @@ You can also set this in the configuration file with `version_scheme = "semver"` | Devrelease | `0.1.1.dev1` | `0.1.1-dev1` | | Dev and pre | `1.0.0a3.dev1` | `1.0.0-a3-dev1` | + +!!! note "Incomplete Version Handling" + Commitizen treats a three-part version (major.minor.patch) as complete. + If your configured version is incomplete (for example, `1` or `1.2`), Commitizen pads missing parts with zeros when it needs `major/minor/patch` for tag formatting. + The tag output depends on your `tag_format`: formats using `${version}` keep `1`/`1.2`, while formats using `${major}.${minor}.${patch}` will render `1.0.0`/`1.2.0`. + + When bumping from an incomplete version, Commitizen looks for the latest existing tag that matches the provided release prefix. + For example, if the current version is `1.2` and the latest `1.2.x` tag is `1.2.3`, then a patch bump yields `1.2.4` and a minor bump yields `1.3.0`. + +!!! tip + To control the behaviour of bumping and version parsing, you may implement your own `version_scheme` by inheriting from `commitizen.version_schemes.BaseVersion` or use an existing plugin package. + + ### PEP440 Version Examples Commitizen supports the [PEP 440][pep440] version format, which includes several version types. Here are examples of each: diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index a1c70b9480..b9a6bf90f0 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -755,6 +755,8 @@ def test_bump_invalid_manual_version_raises_exception( "0.1.1", "0.2.0", "1.0.0", + "1.2", + "1", ], ) def test_bump_manual_version(util: UtilFixture, manual_version): @@ -775,6 +777,33 @@ def test_bump_manual_version_disallows_major_version_zero(util: UtilFixture): ) +@pytest.mark.parametrize( + "initial_version, expected_version_after_bump", + [ + ("1", "1.1.0"), + ("1.2", "1.3.0"), + ], +) +def test_bump_version_with_less_components_in_config( + tmp_commitizen_project_initial, + initial_version, + expected_version_after_bump, + util: UtilFixture, +): + tmp_commitizen_project = tmp_commitizen_project_initial(version=initial_version) + util.run_cli("bump", "--yes") + + tag_exists = git.tag_exist(expected_version_after_bump) + assert tag_exists is True + + for version_file in [ + tmp_commitizen_project.join("__version__.py"), + tmp_commitizen_project.join("pyproject.toml"), + ]: + with open(version_file) as f: + assert expected_version_after_bump in f.read() + + @pytest.mark.parametrize("commit_msg", ("feat: new file", "feat(user): new file")) def test_bump_with_pre_bump_hooks( commit_msg, mocker: MockFixture, tmp_commitizen_project, util: UtilFixture diff --git a/tests/test_tags.py b/tests/test_tags.py new file mode 100644 index 0000000000..2471b8461b --- /dev/null +++ b/tests/test_tags.py @@ -0,0 +1,101 @@ +from commitizen.git import GitTag +from commitizen.tags import TagRules + + +def _git_tag(name: str) -> GitTag: + return GitTag(name, "rev", "2024-01-01") + + +def test_find_tag_for_partial_version_returns_latest_match(): + tags = [ + _git_tag("1.2.0"), + _git_tag("1.2.2"), + _git_tag("1.2.1"), + _git_tag("1.3.0"), + ] + + rules = TagRules() + + found = rules.find_tag_for(tags, "1.2") + + assert found is not None + assert found.name == "1.2.2" + + +def test_find_tag_for_full_version_remains_exact(): + tags = [ + _git_tag("1.2.0"), + _git_tag("1.2.2"), + _git_tag("1.2.1"), + ] + + rules = TagRules() + + found = rules.find_tag_for(tags, "1.2.1") + + assert found is not None + assert found.name == "1.2.1" + + +def test_find_tag_for_partial_version_with_prereleases_prefers_latest_version(): + tags = [ + _git_tag("1.2.0b1"), + _git_tag("1.2.0"), + _git_tag("1.2.1b1"), + ] + + rules = TagRules() + + found = rules.find_tag_for(tags, "1.2") + + assert found is not None + # 1.2.1b1 > 1.2.0 so it should be selected + assert found.name == "1.2.1b1" + + +def test_find_tag_for_partial_version_respects_tag_format(): + tags = [ + _git_tag("v1.2.0"), + _git_tag("v1.2.1"), + _git_tag("v1.3.0"), + ] + + rules = TagRules(tag_format="v$version") + + found = rules.find_tag_for(tags, "1.2") + + assert found is not None + assert found.name == "v1.2.1" + + found = rules.find_tag_for(tags, "1") + + assert found is not None + assert found.name == "v1.3.0" + + +def test_find_tag_for_partial_version_returns_none_when_no_match(): + tags = [ + _git_tag("2.0.0"), + _git_tag("2.1.0"), + ] + + rules = TagRules() + + found = rules.find_tag_for(tags, "1.2") + + assert found is None + + +def test_find_tag_for_partial_version_ignores_invalid_tags(): + tags = [ + _git_tag("not-a-version"), + _git_tag("1.2.0"), + _git_tag("1.2.1"), + ] + + rules = TagRules() + + found = rules.find_tag_for(tags, "1.2") + + assert found is not None + assert found.name == "1.2.1" From 53c994985096d1fc6492535afb2ecfbf2c90c9ef Mon Sep 17 00:00:00 2001 From: "andre.liang" <54308739+namwoam@users.noreply.github.com> Date: Sat, 31 Jan 2026 15:14:48 +0800 Subject: [PATCH 213/221] feat(cli): add description when choosing a commit rule (#1825) --- commitizen/commands/init.py | 24 ++++++++++++++++++++++-- tests/commands/test_init_command.py | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 62678a2244..0773b71e42 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -11,7 +11,11 @@ from commitizen.config.factory import create_config from commitizen.cz import registry from commitizen.defaults import CONFIG_FILES, DEFAULT_SETTINGS -from commitizen.exceptions import InitFailedError, NoAnswersError +from commitizen.exceptions import ( + InitFailedError, + MissingCzCustomizeConfigError, + NoAnswersError, +) from commitizen.git import get_latest_tag_name, get_tag_names, smart_open from commitizen.version_schemes import KNOWN_SCHEMES, Version, get_version_scheme @@ -167,12 +171,28 @@ def _ask_config_path(self) -> Path: def _ask_name(self) -> str: name: str = questionary.select( "Please choose a cz (commit rule): (default: cz_conventional_commits)", - choices=list(registry.keys()), + choices=self._construct_name_choice_with_description(), default="cz_conventional_commits", style=self.cz.style, ).unsafe_ask() return name + def _construct_name_choice_with_description(self) -> list[questionary.Choice]: + choices = [] + for cz_name, cz_class in registry.items(): + try: + cz_obj = cz_class(self.config) + except MissingCzCustomizeConfigError: + choices.append(questionary.Choice(title=cz_name, value=cz_name)) + continue + first_example = cz_obj.schema().partition("\n")[0] + choices.append( + questionary.Choice( + title=cz_name, value=cz_name, description=first_example + ) + ) + return choices + def _ask_tag(self) -> str: latest_tag = get_latest_tag_name() if not latest_tag: diff --git a/tests/commands/test_init_command.py b/tests/commands/test_init_command.py index 4c7f3923a7..0cf6377ead 100644 --- a/tests/commands/test_init_command.py +++ b/tests/commands/test_init_command.py @@ -10,6 +10,7 @@ from commitizen import cmd, commands from commitizen.__version__ import __version__ +from commitizen.cz import registry from commitizen.exceptions import InitFailedError, NoAnswersError if TYPE_CHECKING: @@ -463,3 +464,22 @@ def test_init_configuration_with_version_provider( assert ( "version = " not in config_data ) # Version should not be set when using version_provider + + +def test_construct_name_choice_with_description( + config: BaseConfig, mocker: MockFixture +): + """Test the construction of cz name choices with descriptions.""" + init = commands.Init(config) + # mock the registry to have only one cz for testing + mocker.patch.dict( + "commitizen.cz.registry", + {"cz_conventional_commits": registry["cz_conventional_commits"]}, + clear=True, + ) + choices = init._construct_name_choice_with_description() + assert len(choices) == 1 + choice = choices[0] + assert choice.title == "cz_conventional_commits" + assert choice.value == "cz_conventional_commits" + assert choice.description == "<type>(<scope>): <subject>" From 68c7ba615f6d86a0e58c4d91a41259dce00a393f Mon Sep 17 00:00:00 2001 From: Finn <yjaw85@gmail.com> Date: Sat, 31 Jan 2026 01:40:34 -0600 Subject: [PATCH 214/221] feat(version): add --tag tag to version command (#1819) --- commitizen/cli.py | 6 +++ commitizen/commands/version.py | 9 +++++ ..._when_use_help_option_py_3_10_version_.txt | 4 +- ..._when_use_help_option_py_3_11_version_.txt | 4 +- ..._when_use_help_option_py_3_12_version_.txt | 4 +- ..._when_use_help_option_py_3_13_version_.txt | 4 +- ..._when_use_help_option_py_3_14_version_.txt | 4 +- tests/commands/test_version_command.py | 39 +++++++++++++++++++ 8 files changed, 69 insertions(+), 5 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 99c36f8e4c..d057bd97dc 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -546,6 +546,12 @@ def __call__( "action": "store_true", "exclusive_group": "group2", }, + { + "name": ["--tag"], + "help": "get the version with tag prefix. Need to be used with --project or --verbose.", + "action": "store_true", + "exclusive_group": "group2", + }, ], }, ], diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 9290e80b8f..c8a76fe27f 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -7,6 +7,7 @@ from commitizen.config import BaseConfig from commitizen.exceptions import NoVersionSpecifiedError, VersionSchemeUnknown from commitizen.providers import get_provider +from commitizen.tags import TagRules from commitizen.version_schemes import get_version_scheme @@ -17,6 +18,7 @@ class VersionArgs(TypedDict, total=False): verbose: bool major: bool minor: bool + tag: bool class Version: @@ -59,6 +61,9 @@ def __call__(self) -> None: version = f"{version_scheme.major}" elif self.arguments.get("minor"): version = f"{version_scheme.minor}" + elif self.arguments.get("tag"): + tag_rules = TagRules.from_settings(self.config.settings) + version = tag_rules.normalize_tag(version_scheme) out.write( f"Project Version: {version}" @@ -73,5 +78,9 @@ def __call__(self) -> None: ) return + if self.arguments.get("tag"): + out.error("Tag can only be used with --project or --verbose.") + return + # If no arguments are provided, just show the installed commitizen version out.write(__version__) diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt index 0061a97514..5085d0fd3c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor | --tag] Get the version of the installed commitizen or the current project (default: installed commitizen) @@ -14,3 +14,5 @@ options: or --verbose. --minor Output just the minor version. Must be used with --project or --verbose. + --tag get the version with tag prefix. Need to be used with + --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt index 0061a97514..5085d0fd3c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor | --tag] Get the version of the installed commitizen or the current project (default: installed commitizen) @@ -14,3 +14,5 @@ options: or --verbose. --minor Output just the minor version. Must be used with --project or --verbose. + --tag get the version with tag prefix. Need to be used with + --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt index 0061a97514..5085d0fd3c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor | --tag] Get the version of the installed commitizen or the current project (default: installed commitizen) @@ -14,3 +14,5 @@ options: or --verbose. --minor Output just the minor version. Must be used with --project or --verbose. + --tag get the version with tag prefix. Need to be used with + --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt index 0061a97514..5085d0fd3c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor | --tag] Get the version of the installed commitizen or the current project (default: installed commitizen) @@ -14,3 +14,5 @@ options: or --verbose. --minor Output just the minor version. Must be used with --project or --verbose. + --tag get the version with tag prefix. Need to be used with + --project or --verbose. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt index 0061a97514..5085d0fd3c 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor | --tag] Get the version of the installed commitizen or the current project (default: installed commitizen) @@ -14,3 +14,5 @@ options: or --verbose. --minor Output just the minor version. Must be used with --project or --verbose. + --tag get the version with tag prefix. Need to be used with + --project or --verbose. diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 17f7238403..af22ba7ad2 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -161,3 +161,42 @@ def test_version_just_major_error_no_project(config, capsys, argument: str): "Major or minor version can only be used with --project or --verbose." in captured.err ) + + +@pytest.mark.parametrize( + "version, tag_format, expected_output", + [ + ("1.2.3", "v$version", "v1.2.3\n"), + ("1.2.3", "$version", "1.2.3\n"), + ("2.0.0", "release-$version", "release-2.0.0\n"), + ("0.1.0", "ver$version", "ver0.1.0\n"), + ], +) +def test_version_with_tag_format( + config, capsys, version: str, tag_format: str, expected_output: str +): + """Test --tag option applies tag_format to version""" + config.settings["version"] = version + config.settings["tag_format"] = tag_format + commands.Version( + config, + { + "project": True, + "tag": True, + }, + )() + captured = capsys.readouterr() + assert captured.out == expected_output + + +def test_version_tag_without_project_error(config, capsys): + """Test --tag requires --project or --verbose""" + commands.Version( + config, + { + "tag": True, + }, + )() + captured = capsys.readouterr() + assert not captured.out + assert "Tag can only be used with --project or --verbose." in captured.err From f7fba4805a077c598ac859bd28db35a4669b5a83 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 16:08:21 +0800 Subject: [PATCH 215/221] fix(config): include pyproject.toml in multi config file warning (#1803) --- commitizen/config/__init__.py | 38 ++++++++++------------ tests/test_conf.py | 60 ++++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/commitizen/config/__init__.py b/commitizen/config/__init__.py index cce3a266cd..ae980af9c0 100644 --- a/commitizen/config/__init__.py +++ b/commitizen/config/__init__.py @@ -9,7 +9,7 @@ from .base_config import BaseConfig -def _resolve_config_paths() -> list[Path]: +def _resolve_config_candidates() -> list[BaseConfig]: git_project_root = git.find_git_project_root() cfg_search_paths = [Path(".")] @@ -18,12 +18,18 @@ def _resolve_config_paths() -> list[Path]: # The following algorithm is ugly, but we need to ensure that the order of the candidates are preserved before v5. # Also, the number of possible config files is limited, so the complexity is not a problem. - candidates: list[Path] = [] + candidates: list[BaseConfig] = [] for dir in cfg_search_paths: for filename in defaults.CONFIG_FILES: out_path = dir / Path(filename) - if out_path.exists() and all(not out_path.samefile(p) for p in candidates): - candidates.append(out_path) + if ( + out_path.exists() + and not any( + out_path.samefile(candidate.path) for candidate in candidates + ) + and not (conf := _create_config_from_path(out_path)).is_empty_config + ): + candidates.append(conf) return candidates @@ -44,21 +50,11 @@ def read_cfg(filepath: str | None = None) -> BaseConfig: raise ConfigFileIsEmpty() return conf - config_candidate_paths = _resolve_config_paths() - - # Check for multiple config files and warn the user - config_candidates_exclude_pyproject = [ - path for path in config_candidate_paths if path.name != "pyproject.toml" - ] - - for config_candidate_path in config_candidate_paths: - conf = _create_config_from_path(config_candidate_path) - if not conf.is_empty_config: - if len(config_candidates_exclude_pyproject) > 1: - out.warn( - f"Multiple config files detected: {', '.join(map(str, config_candidates_exclude_pyproject))}. " - f"Using config file: '{config_candidate_path}'." - ) - return conf + config_candidates = _resolve_config_candidates() + if len(config_candidates) > 1: + out.warn( + f"Multiple config files detected: {', '.join(str(conf.path) for conf in config_candidates)}. " + f"Using config file: '{config_candidates[0].path}'." + ) - return BaseConfig() + return config_candidates[0] if config_candidates else BaseConfig() diff --git a/tests/test_conf.py b/tests/test_conf.py index 99d19793cd..f1ff76ff88 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -14,7 +14,7 @@ from commitizen.config.yaml_config import YAMLConfig from commitizen.exceptions import ConfigFileIsEmpty, InvalidConfigurationError -PYPROJECT = """ +TOML_STR = """ [tool.commitizen] name = "cz_jira" version = "1.0.0" @@ -30,12 +30,17 @@ "scripts/generate_documentation.sh" ] post_bump_hooks = ["scripts/slack_notification.sh"] +""" + +PYPROJECT = f""" +{TOML_STR} [tool.black] line-length = 88 target-version = ['py36', 'py37', 'py38'] """ + DICT_CONFIG = { "commitizen": { "name": "cz_jira", @@ -198,7 +203,7 @@ def test_load_empty_pyproject_toml_and_cz_toml_with_config(self, tmpdir): p = tmpdir.join("pyproject.toml") p.write("") p = tmpdir.join(".cz.toml") - p.write(PYPROJECT) + p.write(TOML_STR) cfg = config.read_cfg() assert cfg.settings == _settings @@ -240,27 +245,25 @@ def test_load_empty_pyproject_toml_from_config_argument(self, tmpdir): class TestWarnMultipleConfigFiles: @pytest.mark.parametrize( - "files,expected_path,should_warn", + "files,expected_path", [ # Same directory, different file types - ([(".cz.toml", PYPROJECT), (".cz.json", JSON_STR)], ".cz.toml", True), - ([(".cz.json", JSON_STR), (".cz.yaml", YAML_STR)], ".cz.json", True), - ([(".cz.toml", PYPROJECT), (".cz.yaml", YAML_STR)], ".cz.toml", True), - # With pyproject.toml (excluded from warning) + ([(".cz.toml", TOML_STR), (".cz.json", JSON_STR)], ".cz.toml"), + ([(".cz.json", JSON_STR), (".cz.yaml", YAML_STR)], ".cz.json"), + ([(".cz.toml", TOML_STR), (".cz.yaml", YAML_STR)], ".cz.toml"), + # With pyproject.toml ( [("pyproject.toml", PYPROJECT), (".cz.json", JSON_STR)], ".cz.json", - False, ), ( - [("pyproject.toml", PYPROJECT), (".cz.toml", PYPROJECT)], + [("pyproject.toml", PYPROJECT), (".cz.toml", TOML_STR)], ".cz.toml", - False, ), ], ) def test_warn_multiple_config_files_same_dir( - self, tmpdir, capsys, files, expected_path, should_warn + self, tmpdir, capsys, files, expected_path ): """Test warning when multiple config files exist in same directory.""" with tmpdir.as_cwd(): @@ -270,27 +273,20 @@ def test_warn_multiple_config_files_same_dir( cfg = config.read_cfg() captured = capsys.readouterr() - if should_warn: - assert "Multiple config files detected" in captured.err - assert "Using" in captured.err - for filename, _ in files: - if filename != "pyproject.toml": - assert filename in captured.err - else: - assert "Multiple config files detected" not in captured.err + assert "Multiple config files detected" in captured.err + for filename, _ in files: + assert filename in captured.err + assert f"Using config file: '{expected_path}'" in captured.err assert cfg.path == Path(expected_path) - # Verify config loaded correctly (name and version match expected) - assert cfg.settings["name"] == "cz_jira" - assert cfg.settings["version"] == "1.0.0" @pytest.mark.parametrize( "config_file,content", [ (".cz.json", JSON_STR), - (".cz.toml", PYPROJECT), + (".cz.toml", TOML_STR), (".cz.yaml", YAML_STR), - ("cz.toml", PYPROJECT), + ("cz.toml", TOML_STR), ("cz.json", JSON_STR), ("cz.yaml", YAML_STR), ], @@ -340,11 +336,11 @@ def test_no_warn_with_explicit_config_path(self, tmpdir, capsys): [ (file, content, with_git) for file, content in [ - (".cz.toml", PYPROJECT), + (".cz.toml", TOML_STR), (".cz.json", JSON_STR), (".cz.yaml", YAML_STR), ("pyproject.toml", PYPROJECT), - ("cz.toml", PYPROJECT), + ("cz.toml", TOML_STR), ("cz.json", JSON_STR), ("cz.yaml", YAML_STR), ] @@ -368,6 +364,18 @@ def test_no_warn_with_single_config_file( assert "Multiple config files detected" not in captured.err assert cfg.path == Path(config_file) + def test_no_warn_with_no_commitizen_section_in_pyproject_toml_and_cz_toml( + self, tmpdir, capsys + ): + with tmpdir.as_cwd(): + tmpdir.join("pyproject.toml").write("[tool.foo]\nbar = 'baz'") + tmpdir.join(".cz.toml").write(TOML_STR) + + cfg = config.read_cfg() + captured = capsys.readouterr() + assert "Multiple config files detected" not in captured.err + assert cfg.path == Path(".cz.toml") + @pytest.mark.parametrize( "config_file", From 5ef1be5164256c2cb2106606e0a19580e1477f86 Mon Sep 17 00:00:00 2001 From: YU HAN-CHENG <boy19990222@gmail.com> Date: Sat, 31 Jan 2026 16:24:19 +0800 Subject: [PATCH 216/221] test: add match parameter to pytest.warns to resolve PT030 (#1828) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 余翰承 <hankyu@yuhanchengdeMacBook-Air.local> --- pyproject.toml | 1 - tests/commands/test_bump_command.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 18ebe46362..38cf5da23c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -243,7 +243,6 @@ ignore = [ "PT007", # TODO(bearomorphism): enable this rule "PT011", # TODO(bearomorphism): enable this rule "PT022", # TODO(bearomorphism): enable this rule - "PT030", # TODO(bearomorphism): enable this rule ] extend-safe-fixes = [ "TC", # Move imports inside/outside TYPE_CHECKING blocks diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index b9a6bf90f0..2c4bd269bc 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -1027,7 +1027,7 @@ def test_bump_with_major_version_zero_with_plugin( def test_bump_command_version_type_deprecation(util: UtilFixture): util.create_file_and_commit("feat: check deprecation on --version-type") - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, match=r".*--version-type.*deprecated"): util.run_cli( "bump", "--prerelease", @@ -1044,7 +1044,7 @@ def test_bump_command_version_type_deprecation(util: UtilFixture): def test_bump_command_version_scheme_priority_over_version_type(util: UtilFixture): util.create_file_and_commit("feat: check deprecation on --version-type") - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, match=r".*--version-type.*deprecated"): util.run_cli( "bump", "--prerelease", From 107680da73b7b126be33ff3b06a50e66ffa24fc6 Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sat, 31 Jan 2026 20:53:41 +0800 Subject: [PATCH 217/221] refactor: replace hard-coded string "cz_conventional_commits" with DEFAULT_SETTINGS (#1830) --- commitizen/cli.py | 3 ++- commitizen/commands/init.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index d057bd97dc..854238cc9b 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -13,6 +13,7 @@ from decli import cli from commitizen import commands, config, out, version_schemes +from commitizen.defaults import DEFAULT_SETTINGS from commitizen.exceptions import ( CommitizenException, ExitCode, @@ -672,7 +673,7 @@ def main() -> None: if args.name: conf.update({"name": args.name}) elif not conf.path: - conf.update({"name": "cz_conventional_commits"}) + conf.update({"name": DEFAULT_SETTINGS["name"]}) if args.debug: logging.getLogger("commitizen").setLevel(logging.DEBUG) diff --git a/commitizen/commands/init.py b/commitizen/commands/init.py index 0773b71e42..9d33e7081a 100644 --- a/commitizen/commands/init.py +++ b/commitizen/commands/init.py @@ -170,9 +170,9 @@ def _ask_config_path(self) -> Path: def _ask_name(self) -> str: name: str = questionary.select( - "Please choose a cz (commit rule): (default: cz_conventional_commits)", + f"Please choose a cz (commit rule): (default: {DEFAULT_SETTINGS['name']})", choices=self._construct_name_choice_with_description(), - default="cz_conventional_commits", + default=DEFAULT_SETTINGS["name"], style=self.cz.style, ).unsafe_ask() return name From ad35515244ee1bbb6005e0e807ef3b5e2eafdeae Mon Sep 17 00:00:00 2001 From: Tim Hsiung <bear890707@gmail.com> Date: Sun, 1 Feb 2026 18:53:42 +0800 Subject: [PATCH 218/221] feat(bump): add --version-files-only and deprecate --files-only (#1802) Co-authored-by: abhishek <abhishekbansal8948@gmail.com> --- commitizen/cli.py | 7 ++++++- commitizen/commands/bump.py | 10 +++++++++- docs/commands/bump.md | 4 ++-- tests/commands/test_bump_command.py | 15 +++++++++++++-- ...ription_when_use_help_option_py_3_10_bump_.txt | 13 ++++++++----- ...ription_when_use_help_option_py_3_11_bump_.txt | 13 ++++++++----- ...ription_when_use_help_option_py_3_12_bump_.txt | 13 ++++++++----- ...ription_when_use_help_option_py_3_13_bump_.txt | 13 ++++++++----- ...ription_when_use_help_option_py_3_14_bump_.txt | 13 ++++++++----- 9 files changed, 70 insertions(+), 31 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 854238cc9b..79988fb5cb 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -210,7 +210,12 @@ def __call__( { "name": "--files-only", # TODO: rename to --version-files-only "action": "store_true", - "help": "Bump version in the `version_files` specified in the configuration file only.", + "help": "Bump version in the `version_files` specified in the configuration file only(deprecated; use --version-files-only instead).", + }, + { + "name": "--version-files-only", + "action": "store_true", + "help": "Bump version in the files from the config", }, { "name": "--local-version", diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index affe2bd358..6084c8c151 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -49,6 +49,7 @@ class BumpArgs(Settings, total=False): dry_run: bool file_name: str files_only: bool | None + version_files_only: bool | None get_next: bool # TODO: maybe rename to `next_version_to_stdout` git_output_to_stderr: bool increment_mode: str @@ -365,7 +366,14 @@ def __call__(self) -> None: changelog_file_name=changelog_file_name, ) - if self.arguments["files_only"]: + if self.arguments.get("files_only"): + warnings.warn( + "--files-only is deprecated and will be removed in v5. Use --version-files-only instead.", + DeprecationWarning, + ) + raise ExpectedExit() + + if self.arguments.get("version_files_only"): raise ExpectedExit() # FIXME: check if any changes have been staged diff --git a/docs/commands/bump.md b/docs/commands/bump.md index 03fc83402c..cbd6d5452b 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -122,12 +122,12 @@ Commitizen supports the [PEP 440][pep440] version format, which includes several ![cz bump --help](../images/cli_help/cz_bump___help.svg) -### `--files-only` +### `--version-files-only` Bumps the version in the files defined in [`version_files`][version_files] without creating a commit and tag on the git repository. ```bash -cz bump --files-only +cz bump --version-files-only ``` ### `--changelog` diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index 2c4bd269bc..d458e34d8e 100644 --- a/tests/commands/test_bump_command.py +++ b/tests/commands/test_bump_command.py @@ -418,7 +418,8 @@ def test_bump_files_only(tmp_commitizen_project, util: UtilFixture): util.create_file_and_commit("feat: another new feature") with pytest.raises(ExpectedExit): - util.run_cli("bump", "--yes", "--files-only") + util.run_cli("bump", "--yes", "--version-files-only") + assert git.tag_exist("0.3.0") is False with open(tmp_version_file, encoding="utf-8") as f: @@ -1204,7 +1205,7 @@ def test_bump_changelog_contains_increment_only( # it should only include v3 changes util.create_file_and_commit("feat(next)!: next version") with pytest.raises(ExpectedExit): - util.run_cli("bump", "--yes", "--files-only", "--changelog-to-stdout") + util.run_cli("bump", "--yes", "--version-files-only", "--changelog-to-stdout") out, _ = capsys.readouterr() assert "3.0.0" in out @@ -1492,3 +1493,13 @@ def test_changelog_config_flag_merge_prerelease_only_prerelease_present( out = f.read() file_regression.check(out, extension=".md") + + +@pytest.mark.usefixtures("tmp_commitizen_project") +def test_bump_deprecate_files_only(util: UtilFixture): + util.create_file_and_commit("feat: new file") + with ( + pytest.warns(DeprecationWarning, match=r".*--files-only.*deprecated"), + pytest.raises(ExpectedExit), + ): + util.run_cli("bump", "--yes", "--files-only") diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt index d56e739277..fa696d063d 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_bump_.txt @@ -1,7 +1,8 @@ -usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] - [--no-verify] [--yes] [--tag-format TAG_FORMAT] - [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] - [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] +usage: cz bump [-h] [--dry-run] [--files-only] [--version-files-only] + [--local-version] [--changelog] [--no-verify] [--yes] + [--tag-format TAG_FORMAT] [--bump-message BUMP_MESSAGE] + [--prerelease {alpha,beta,rc}] [--devrelease DEVRELEASE] + [--increment {MAJOR,MINOR,PATCH}] [--increment-mode {linear,exact}] [--check-consistency] [--annotated-tag] [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] @@ -24,7 +25,9 @@ options: --dry-run Perform a dry run, without committing or modifying files. --files-only Bump version in the `version_files` specified in the - configuration file only. + configuration file only(deprecated; use --version- + files-only instead). + --version-files-only Bump version in the files from the config --local-version Bump version only the local version portion (ignoring the public version). --changelog, -ch Generate the changelog for the latest version. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt index d56e739277..fa696d063d 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_bump_.txt @@ -1,7 +1,8 @@ -usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] - [--no-verify] [--yes] [--tag-format TAG_FORMAT] - [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] - [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] +usage: cz bump [-h] [--dry-run] [--files-only] [--version-files-only] + [--local-version] [--changelog] [--no-verify] [--yes] + [--tag-format TAG_FORMAT] [--bump-message BUMP_MESSAGE] + [--prerelease {alpha,beta,rc}] [--devrelease DEVRELEASE] + [--increment {MAJOR,MINOR,PATCH}] [--increment-mode {linear,exact}] [--check-consistency] [--annotated-tag] [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] @@ -24,7 +25,9 @@ options: --dry-run Perform a dry run, without committing or modifying files. --files-only Bump version in the `version_files` specified in the - configuration file only. + configuration file only(deprecated; use --version- + files-only instead). + --version-files-only Bump version in the files from the config --local-version Bump version only the local version portion (ignoring the public version). --changelog, -ch Generate the changelog for the latest version. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt index d56e739277..fa696d063d 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_bump_.txt @@ -1,7 +1,8 @@ -usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] - [--no-verify] [--yes] [--tag-format TAG_FORMAT] - [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] - [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] +usage: cz bump [-h] [--dry-run] [--files-only] [--version-files-only] + [--local-version] [--changelog] [--no-verify] [--yes] + [--tag-format TAG_FORMAT] [--bump-message BUMP_MESSAGE] + [--prerelease {alpha,beta,rc}] [--devrelease DEVRELEASE] + [--increment {MAJOR,MINOR,PATCH}] [--increment-mode {linear,exact}] [--check-consistency] [--annotated-tag] [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] @@ -24,7 +25,9 @@ options: --dry-run Perform a dry run, without committing or modifying files. --files-only Bump version in the `version_files` specified in the - configuration file only. + configuration file only(deprecated; use --version- + files-only instead). + --version-files-only Bump version in the files from the config --local-version Bump version only the local version portion (ignoring the public version). --changelog, -ch Generate the changelog for the latest version. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt index c472a040e9..8e4c863585 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_bump_.txt @@ -1,7 +1,8 @@ -usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] - [--no-verify] [--yes] [--tag-format TAG_FORMAT] - [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] - [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] +usage: cz bump [-h] [--dry-run] [--files-only] [--version-files-only] + [--local-version] [--changelog] [--no-verify] [--yes] + [--tag-format TAG_FORMAT] [--bump-message BUMP_MESSAGE] + [--prerelease {alpha,beta,rc}] [--devrelease DEVRELEASE] + [--increment {MAJOR,MINOR,PATCH}] [--increment-mode {linear,exact}] [--check-consistency] [--annotated-tag] [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] @@ -24,7 +25,9 @@ options: --dry-run Perform a dry run, without committing or modifying files. --files-only Bump version in the `version_files` specified in the - configuration file only. + configuration file only(deprecated; use --version- + files-only instead). + --version-files-only Bump version in the files from the config --local-version Bump version only the local version portion (ignoring the public version). --changelog, -ch Generate the changelog for the latest version. diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt index c472a040e9..8e4c863585 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_bump_.txt @@ -1,7 +1,8 @@ -usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] - [--no-verify] [--yes] [--tag-format TAG_FORMAT] - [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}] - [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] +usage: cz bump [-h] [--dry-run] [--files-only] [--version-files-only] + [--local-version] [--changelog] [--no-verify] [--yes] + [--tag-format TAG_FORMAT] [--bump-message BUMP_MESSAGE] + [--prerelease {alpha,beta,rc}] [--devrelease DEVRELEASE] + [--increment {MAJOR,MINOR,PATCH}] [--increment-mode {linear,exact}] [--check-consistency] [--annotated-tag] [--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign] @@ -24,7 +25,9 @@ options: --dry-run Perform a dry run, without committing or modifying files. --files-only Bump version in the `version_files` specified in the - configuration file only. + configuration file only(deprecated; use --version- + files-only instead). + --version-files-only Bump version in the files from the config --local-version Bump version only the local version portion (ignoring the public version). --changelog, -ch Generate the changelog for the latest version. From d214704eaeae4c16b893f70b624f3bab477bc6a7 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung <bear890707@gmail.com> Date: Sun, 1 Feb 2026 18:54:56 +0800 Subject: [PATCH 219/221] Revert "fix(pre-commit-hooks): remove magic constants on pre-push hook (#1815)" This reverts commit 047c914f072a781c6daa1280f929f5a81a985690. --- .pre-commit-hooks.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 650f0acedb..c142634581 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -19,7 +19,7 @@ the fact (e.g., pre-push or in CI) without an expensive check of the entire repository history. entry: cz check - args: [--rev-range, "$PRE_COMMIT_TO_REF $PRE_COMMIT_FROM_REF"] + args: [--rev-range, origin/HEAD..HEAD] always_run: true pass_filenames: false language: python From 12bde08b5e301e8b918f18eb8abcc479bec00545 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Feb 2026 11:00:39 +0000 Subject: [PATCH 220/221] docs(cli/screenshots): update CLI screenshots [skip ci] --- docs/images/cli_help/cz___help.svg | 166 ++++---- docs/images/cli_help/cz_bump___help.svg | 379 ++++++++++--------- docs/images/cli_help/cz_changelog___help.svg | 192 +++++----- docs/images/cli_help/cz_check___help.svg | 150 ++++---- docs/images/cli_help/cz_commit___help.svg | 129 ++++--- docs/images/cli_help/cz_example___help.svg | 44 +-- docs/images/cli_help/cz_info___help.svg | 44 +-- docs/images/cli_help/cz_init___help.svg | 44 +-- docs/images/cli_help/cz_ls___help.svg | 44 +-- docs/images/cli_help/cz_schema___help.svg | 44 +-- docs/images/cli_help/cz_version___help.svg | 98 ++--- 11 files changed, 689 insertions(+), 645 deletions(-) diff --git a/docs/images/cli_help/cz___help.svg b/docs/images/cli_help/cz___help.svg index ae9a135743..64b79fc0bb 100644 --- a/docs/images/cli_help/cz___help.svg +++ b/docs/images/cli_help/cz___help.svg @@ -19,136 +19,136 @@ font-weight: 700; } - .terminal-1688774822-matrix { + .terminal-199999382-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1688774822-title { + .terminal-199999382-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1688774822-r1 { fill: #c5c8c6 } -.terminal-1688774822-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-1688774822-r3 { fill: #d0b344 } -.terminal-1688774822-r4 { fill: #1984e9;text-decoration: underline; } -.terminal-1688774822-r5 { fill: #68a0b3;font-weight: bold } + .terminal-199999382-r1 { fill: #c5c8c6 } +.terminal-199999382-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-199999382-r3 { fill: #d0b344 } +.terminal-199999382-r4 { fill: #1984e9;text-decoration: underline; } +.terminal-199999382-r5 { fill: #68a0b3;font-weight: bold } </style> <defs> - <clipPath id="terminal-1688774822-clip-terminal"> + <clipPath id="terminal-199999382-clip-terminal"> <rect x="0" y="0" width="975.0" height="901.8" /> </clipPath> - <clipPath id="terminal-1688774822-line-0"> + <clipPath id="terminal-199999382-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-1"> +<clipPath id="terminal-199999382-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-2"> +<clipPath id="terminal-199999382-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-3"> +<clipPath id="terminal-199999382-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-4"> +<clipPath id="terminal-199999382-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-5"> +<clipPath id="terminal-199999382-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-6"> +<clipPath id="terminal-199999382-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-7"> +<clipPath id="terminal-199999382-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-8"> +<clipPath id="terminal-199999382-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-9"> +<clipPath id="terminal-199999382-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-10"> +<clipPath id="terminal-199999382-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-11"> +<clipPath id="terminal-199999382-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-12"> +<clipPath id="terminal-199999382-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-13"> +<clipPath id="terminal-199999382-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-14"> +<clipPath id="terminal-199999382-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-15"> +<clipPath id="terminal-199999382-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-16"> +<clipPath id="terminal-199999382-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-17"> +<clipPath id="terminal-199999382-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-18"> +<clipPath id="terminal-199999382-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-19"> +<clipPath id="terminal-199999382-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-20"> +<clipPath id="terminal-199999382-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-21"> +<clipPath id="terminal-199999382-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-22"> +<clipPath id="terminal-199999382-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-23"> +<clipPath id="terminal-199999382-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-24"> +<clipPath id="terminal-199999382-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-25"> +<clipPath id="terminal-199999382-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-26"> +<clipPath id="terminal-199999382-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-27"> +<clipPath id="terminal-199999382-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-28"> +<clipPath id="terminal-199999382-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-29"> +<clipPath id="terminal-199999382-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-30"> +<clipPath id="terminal-199999382-line-30"> <rect x="0" y="733.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-31"> +<clipPath id="terminal-199999382-line-31"> <rect x="0" y="757.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-32"> +<clipPath id="terminal-199999382-line-32"> <rect x="0" y="782.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-33"> +<clipPath id="terminal-199999382-line-33"> <rect x="0" y="806.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-34"> +<clipPath id="terminal-199999382-line-34"> <rect x="0" y="831.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1688774822-line-35"> +<clipPath id="terminal-199999382-line-35"> <rect x="0" y="855.5" width="976" height="24.65"/> </clipPath> </defs> @@ -160,46 +160,46 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1688774822-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-199999382-clip-terminal)"> - <g class="terminal-1688774822-matrix"> - <text class="terminal-1688774822-r1" x="0" y="20" textLength="134.2" clip-path="url(#terminal-1688774822-line-0)">$ cz --help</text><text class="terminal-1688774822-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1688774822-line-0)"> -</text><text class="terminal-1688774822-r1" x="0" y="44.4" textLength="122" clip-path="url(#terminal-1688774822-line-1)">usage: cz </text><text class="terminal-1688774822-r2" x="122" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="134.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1688774822-line-1)">-h</text><text class="terminal-1688774822-r2" x="158.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="195.2" y="44.4" textLength="183" clip-path="url(#terminal-1688774822-line-1)">--config CONFIG</text><text class="terminal-1688774822-r2" x="378.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="402.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="414.8" y="44.4" textLength="85.4" clip-path="url(#terminal-1688774822-line-1)">--debug</text><text class="terminal-1688774822-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="536.8" y="44.4" textLength="85.4" clip-path="url(#terminal-1688774822-line-1)">-n NAME</text><text class="terminal-1688774822-r2" x="622.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r2" x="646.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">[</text><text class="terminal-1688774822-r1" x="658.8" y="44.4" textLength="146.4" clip-path="url(#terminal-1688774822-line-1)">-nr NO_RAISE</text><text class="terminal-1688774822-r2" x="805.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)">]</text><text class="terminal-1688774822-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-1)"> -</text><text class="terminal-1688774822-r2" x="122" y="68.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-2)">{</text><text class="terminal-1688774822-r1" x="134.2" y="68.8" textLength="829.6" clip-path="url(#terminal-1688774822-line-2)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-1688774822-r2" x="963.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-2)">}</text><text class="terminal-1688774822-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-2)"> -</text><text class="terminal-1688774822-r3" x="122" y="93.2" textLength="36.6" clip-path="url(#terminal-1688774822-line-3)">...</text><text class="terminal-1688774822-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-3)"> -</text><text class="terminal-1688774822-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-4)"> -</text><text class="terminal-1688774822-r1" x="0" y="142" textLength="915" clip-path="url(#terminal-1688774822-line-5)">Commitizen is a powerful release management tool that helps teams maintain </text><text class="terminal-1688774822-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1688774822-line-5)"> -</text><text class="terminal-1688774822-r1" x="0" y="166.4" textLength="951.6" clip-path="url(#terminal-1688774822-line-6)">consistent and meaningful commit messages while automating version management.</text><text class="terminal-1688774822-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-6)"> -</text><text class="terminal-1688774822-r1" x="0" y="190.8" textLength="427" clip-path="url(#terminal-1688774822-line-7)">For more information, please visit </text><text class="terminal-1688774822-r4" x="427" y="190.8" textLength="549" clip-path="url(#terminal-1688774822-line-7)">https://commitizen-tools.github.io/commitizen</text><text class="terminal-1688774822-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-7)"> -</text><text class="terminal-1688774822-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-8)"> -</text><text class="terminal-1688774822-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-1688774822-line-9)">options:</text><text class="terminal-1688774822-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-9)"> -</text><text class="terminal-1688774822-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-1688774822-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-1688774822-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1688774822-line-10)"> -</text><text class="terminal-1688774822-r1" x="0" y="288.4" textLength="658.8" clip-path="url(#terminal-1688774822-line-11)">  --config CONFIG       the path of configuration file</text><text class="terminal-1688774822-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-11)"> -</text><text class="terminal-1688774822-r1" x="0" y="312.8" textLength="463.6" clip-path="url(#terminal-1688774822-line-12)">  --debug               use debug mode</text><text class="terminal-1688774822-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-12)"> -</text><text class="terminal-1688774822-r1" x="0" y="337.2" textLength="597.8" clip-path="url(#terminal-1688774822-line-13)">  -n NAME, --name NAME  use the given commitizen </text><text class="terminal-1688774822-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-13)">(</text><text class="terminal-1688774822-r1" x="610" y="337.2" textLength="97.6" clip-path="url(#terminal-1688774822-line-13)">default:</text><text class="terminal-1688774822-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-13)"> -</text><text class="terminal-1688774822-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-1688774822-line-14)">                        cz_conventional_commits</text><text class="terminal-1688774822-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-14)">)</text><text class="terminal-1688774822-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-14)"> -</text><text class="terminal-1688774822-r1" x="0" y="386" textLength="427" clip-path="url(#terminal-1688774822-line-15)">  -nr NO_RAISE, --no-raise NO_RAISE</text><text class="terminal-1688774822-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1688774822-line-15)"> -</text><text class="terminal-1688774822-r1" x="0" y="410.4" textLength="915" clip-path="url(#terminal-1688774822-line-16)">                        comma separated error codes that won't raise error,</text><text class="terminal-1688774822-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-16)"> -</text><text class="terminal-1688774822-r1" x="0" y="434.8" textLength="439.2" clip-path="url(#terminal-1688774822-line-17)">                        e.g: cz -nr </text><text class="terminal-1688774822-r5" x="439.2" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">1</text><text class="terminal-1688774822-r1" x="451.4" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">,</text><text class="terminal-1688774822-r5" x="463.6" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">2</text><text class="terminal-1688774822-r1" x="475.8" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">,</text><text class="terminal-1688774822-r5" x="488" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)">3</text><text class="terminal-1688774822-r1" x="500.2" y="434.8" textLength="231.8" clip-path="url(#terminal-1688774822-line-17)"> bump. See codes at</text><text class="terminal-1688774822-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-17)"> -</text><text class="terminal-1688774822-r4" x="292.8" y="459.2" textLength="231.8" clip-path="url(#terminal-1688774822-line-18)">https://commitizen-</text><text class="terminal-1688774822-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-18)"> -</text><text class="terminal-1688774822-r1" x="0" y="483.6" textLength="756.4" clip-path="url(#terminal-1688774822-line-19)">                        tools.github.io/commitizen/exit_codes/</text><text class="terminal-1688774822-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-19)"> -</text><text class="terminal-1688774822-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1688774822-line-20)"> -</text><text class="terminal-1688774822-r1" x="0" y="532.4" textLength="109.8" clip-path="url(#terminal-1688774822-line-21)">commands:</text><text class="terminal-1688774822-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-21)"> -</text><text class="terminal-1688774822-r2" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-22)">{</text><text class="terminal-1688774822-r1" x="36.6" y="556.8" textLength="829.6" clip-path="url(#terminal-1688774822-line-22)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-1688774822-r2" x="866.2" y="556.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-22)">}</text><text class="terminal-1688774822-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-22)"> -</text><text class="terminal-1688774822-r1" x="0" y="581.2" textLength="646.6" clip-path="url(#terminal-1688774822-line-23)">    init                init commitizen configuration</text><text class="terminal-1688774822-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-23)"> -</text><text class="terminal-1688774822-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-1688774822-line-24)">    commit </text><text class="terminal-1688774822-r2" x="134.2" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)">(</text><text class="terminal-1688774822-r1" x="146.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)">c</text><text class="terminal-1688774822-r2" x="158.6" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)">)</text><text class="terminal-1688774822-r1" x="170.8" y="605.6" textLength="329.4" clip-path="url(#terminal-1688774822-line-24)">          create new commit</text><text class="terminal-1688774822-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-24)"> -</text><text class="terminal-1688774822-r1" x="0" y="630" textLength="610" clip-path="url(#terminal-1688774822-line-25)">    ls                  show available commitizens</text><text class="terminal-1688774822-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1688774822-line-25)"> -</text><text class="terminal-1688774822-r1" x="0" y="654.4" textLength="524.6" clip-path="url(#terminal-1688774822-line-26)">    example             show commit example</text><text class="terminal-1688774822-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-26)"> -</text><text class="terminal-1688774822-r1" x="0" y="678.8" textLength="646.6" clip-path="url(#terminal-1688774822-line-27)">    info                show information about the cz</text><text class="terminal-1688774822-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-27)"> -</text><text class="terminal-1688774822-r1" x="0" y="703.2" textLength="512.4" clip-path="url(#terminal-1688774822-line-28)">    schema              show commit schema</text><text class="terminal-1688774822-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-28)"> -</text><text class="terminal-1688774822-r1" x="0" y="727.6" textLength="805.2" clip-path="url(#terminal-1688774822-line-29)">    bump                bump semantic version based on the git log</text><text class="terminal-1688774822-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-29)"> -</text><text class="terminal-1688774822-r1" x="0" y="752" textLength="170.8" clip-path="url(#terminal-1688774822-line-30)">    changelog </text><text class="terminal-1688774822-r2" x="170.8" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)">(</text><text class="terminal-1688774822-r1" x="183" y="752" textLength="24.4" clip-path="url(#terminal-1688774822-line-30)">ch</text><text class="terminal-1688774822-r2" x="207.4" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)">)</text><text class="terminal-1688774822-r1" x="219.6" y="752" textLength="305" clip-path="url(#terminal-1688774822-line-30)">      generate changelog </text><text class="terminal-1688774822-r2" x="524.6" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)">(</text><text class="terminal-1688774822-r1" x="536.8" y="752" textLength="329.4" clip-path="url(#terminal-1688774822-line-30)">note that it will overwrite</text><text class="terminal-1688774822-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1688774822-line-30)"> -</text><text class="terminal-1688774822-r1" x="0" y="776.4" textLength="451.4" clip-path="url(#terminal-1688774822-line-31)">                        existing file</text><text class="terminal-1688774822-r2" x="451.4" y="776.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-31)">)</text><text class="terminal-1688774822-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-31)"> -</text><text class="terminal-1688774822-r1" x="0" y="800.8" textLength="951.6" clip-path="url(#terminal-1688774822-line-32)">    check               validates that a commit message matches the commitizen</text><text class="terminal-1688774822-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-1688774822-line-32)"> -</text><text class="terminal-1688774822-r1" x="0" y="825.2" textLength="366" clip-path="url(#terminal-1688774822-line-33)">                        schema</text><text class="terminal-1688774822-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-1688774822-line-33)"> -</text><text class="terminal-1688774822-r1" x="0" y="849.6" textLength="902.8" clip-path="url(#terminal-1688774822-line-34)">    version             get the version of the installed commitizen or the</text><text class="terminal-1688774822-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-1688774822-line-34)"> -</text><text class="terminal-1688774822-r1" x="0" y="874" textLength="488" clip-path="url(#terminal-1688774822-line-35)">                        current project </text><text class="terminal-1688774822-r2" x="488" y="874" textLength="12.2" clip-path="url(#terminal-1688774822-line-35)">(</text><text class="terminal-1688774822-r1" x="500.2" y="874" textLength="353.8" clip-path="url(#terminal-1688774822-line-35)">default: installed commitizen</text><text class="terminal-1688774822-r2" x="854" y="874" textLength="12.2" clip-path="url(#terminal-1688774822-line-35)">)</text><text class="terminal-1688774822-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-1688774822-line-35)"> -</text><text class="terminal-1688774822-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-1688774822-line-36)"> + <g class="terminal-199999382-matrix"> + <text class="terminal-199999382-r1" x="0" y="20" textLength="134.2" clip-path="url(#terminal-199999382-line-0)">$ cz --help</text><text class="terminal-199999382-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-199999382-line-0)"> +</text><text class="terminal-199999382-r1" x="0" y="44.4" textLength="122" clip-path="url(#terminal-199999382-line-1)">usage: cz </text><text class="terminal-199999382-r2" x="122" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">[</text><text class="terminal-199999382-r1" x="134.2" y="44.4" textLength="24.4" clip-path="url(#terminal-199999382-line-1)">-h</text><text class="terminal-199999382-r2" x="158.6" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">]</text><text class="terminal-199999382-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">[</text><text class="terminal-199999382-r1" x="195.2" y="44.4" textLength="183" clip-path="url(#terminal-199999382-line-1)">--config CONFIG</text><text class="terminal-199999382-r2" x="378.2" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">]</text><text class="terminal-199999382-r2" x="402.6" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">[</text><text class="terminal-199999382-r1" x="414.8" y="44.4" textLength="85.4" clip-path="url(#terminal-199999382-line-1)">--debug</text><text class="terminal-199999382-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">]</text><text class="terminal-199999382-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">[</text><text class="terminal-199999382-r1" x="536.8" y="44.4" textLength="85.4" clip-path="url(#terminal-199999382-line-1)">-n NAME</text><text class="terminal-199999382-r2" x="622.2" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">]</text><text class="terminal-199999382-r2" x="646.6" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">[</text><text class="terminal-199999382-r1" x="658.8" y="44.4" textLength="146.4" clip-path="url(#terminal-199999382-line-1)">-nr NO_RAISE</text><text class="terminal-199999382-r2" x="805.2" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)">]</text><text class="terminal-199999382-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-199999382-line-1)"> +</text><text class="terminal-199999382-r2" x="122" y="68.8" textLength="12.2" clip-path="url(#terminal-199999382-line-2)">{</text><text class="terminal-199999382-r1" x="134.2" y="68.8" textLength="829.6" clip-path="url(#terminal-199999382-line-2)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-199999382-r2" x="963.8" y="68.8" textLength="12.2" clip-path="url(#terminal-199999382-line-2)">}</text><text class="terminal-199999382-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-199999382-line-2)"> +</text><text class="terminal-199999382-r3" x="122" y="93.2" textLength="36.6" clip-path="url(#terminal-199999382-line-3)">...</text><text class="terminal-199999382-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-199999382-line-3)"> +</text><text class="terminal-199999382-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-199999382-line-4)"> +</text><text class="terminal-199999382-r1" x="0" y="142" textLength="915" clip-path="url(#terminal-199999382-line-5)">Commitizen is a powerful release management tool that helps teams maintain </text><text class="terminal-199999382-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-199999382-line-5)"> +</text><text class="terminal-199999382-r1" x="0" y="166.4" textLength="951.6" clip-path="url(#terminal-199999382-line-6)">consistent and meaningful commit messages while automating version management.</text><text class="terminal-199999382-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-199999382-line-6)"> +</text><text class="terminal-199999382-r1" x="0" y="190.8" textLength="427" clip-path="url(#terminal-199999382-line-7)">For more information, please visit </text><text class="terminal-199999382-r4" x="427" y="190.8" textLength="549" clip-path="url(#terminal-199999382-line-7)">https://commitizen-tools.github.io/commitizen</text><text class="terminal-199999382-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-199999382-line-7)"> +</text><text class="terminal-199999382-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-199999382-line-8)"> +</text><text class="terminal-199999382-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-199999382-line-9)">options:</text><text class="terminal-199999382-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-199999382-line-9)"> +</text><text class="terminal-199999382-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-199999382-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-199999382-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-199999382-line-10)"> +</text><text class="terminal-199999382-r1" x="0" y="288.4" textLength="719.8" clip-path="url(#terminal-199999382-line-11)">  --config CONFIG       The path to the configuration file.</text><text class="terminal-199999382-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-199999382-line-11)"> +</text><text class="terminal-199999382-r1" x="0" y="312.8" textLength="475.8" clip-path="url(#terminal-199999382-line-12)">  --debug               Use debug mode.</text><text class="terminal-199999382-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-199999382-line-12)"> +</text><text class="terminal-199999382-r1" x="0" y="337.2" textLength="597.8" clip-path="url(#terminal-199999382-line-13)">  -n NAME, --name NAME  Use the given commitizen </text><text class="terminal-199999382-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-199999382-line-13)">(</text><text class="terminal-199999382-r1" x="610" y="337.2" textLength="97.6" clip-path="url(#terminal-199999382-line-13)">default:</text><text class="terminal-199999382-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-199999382-line-13)"> +</text><text class="terminal-199999382-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-199999382-line-14)">                        cz_conventional_commits</text><text class="terminal-199999382-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-199999382-line-14)">)</text><text class="terminal-199999382-r1" x="585.6" y="361.6" textLength="12.2" clip-path="url(#terminal-199999382-line-14)">.</text><text class="terminal-199999382-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-199999382-line-14)"> +</text><text class="terminal-199999382-r1" x="0" y="386" textLength="427" clip-path="url(#terminal-199999382-line-15)">  -nr NO_RAISE, --no-raise NO_RAISE</text><text class="terminal-199999382-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-199999382-line-15)"> +</text><text class="terminal-199999382-r1" x="0" y="410.4" textLength="915" clip-path="url(#terminal-199999382-line-16)">                        Comma-separated error codes that won't raise error,</text><text class="terminal-199999382-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-199999382-line-16)"> +</text><text class="terminal-199999382-r1" x="0" y="434.8" textLength="451.4" clip-path="url(#terminal-199999382-line-17)">                        e.g., cz -nr </text><text class="terminal-199999382-r5" x="451.4" y="434.8" textLength="12.2" clip-path="url(#terminal-199999382-line-17)">1</text><text class="terminal-199999382-r1" x="463.6" y="434.8" textLength="12.2" clip-path="url(#terminal-199999382-line-17)">,</text><text class="terminal-199999382-r5" x="475.8" y="434.8" textLength="12.2" clip-path="url(#terminal-199999382-line-17)">2</text><text class="terminal-199999382-r1" x="488" y="434.8" textLength="12.2" clip-path="url(#terminal-199999382-line-17)">,</text><text class="terminal-199999382-r5" x="500.2" y="434.8" textLength="12.2" clip-path="url(#terminal-199999382-line-17)">3</text><text class="terminal-199999382-r1" x="512.4" y="434.8" textLength="231.8" clip-path="url(#terminal-199999382-line-17)"> bump. See codes at</text><text class="terminal-199999382-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-199999382-line-17)"> +</text><text class="terminal-199999382-r4" x="292.8" y="459.2" textLength="231.8" clip-path="url(#terminal-199999382-line-18)">https://commitizen-</text><text class="terminal-199999382-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-199999382-line-18)"> +</text><text class="terminal-199999382-r1" x="0" y="483.6" textLength="756.4" clip-path="url(#terminal-199999382-line-19)">                        tools.github.io/commitizen/exit_codes/</text><text class="terminal-199999382-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-199999382-line-19)"> +</text><text class="terminal-199999382-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-199999382-line-20)"> +</text><text class="terminal-199999382-r1" x="0" y="532.4" textLength="109.8" clip-path="url(#terminal-199999382-line-21)">commands:</text><text class="terminal-199999382-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-199999382-line-21)"> +</text><text class="terminal-199999382-r2" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-199999382-line-22)">{</text><text class="terminal-199999382-r1" x="36.6" y="556.8" textLength="829.6" clip-path="url(#terminal-199999382-line-22)">init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version</text><text class="terminal-199999382-r2" x="866.2" y="556.8" textLength="12.2" clip-path="url(#terminal-199999382-line-22)">}</text><text class="terminal-199999382-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-199999382-line-22)"> +</text><text class="terminal-199999382-r1" x="0" y="581.2" textLength="732" clip-path="url(#terminal-199999382-line-23)">    init                Initialize commitizen configuration.</text><text class="terminal-199999382-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-199999382-line-23)"> +</text><text class="terminal-199999382-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-199999382-line-24)">    commit </text><text class="terminal-199999382-r2" x="134.2" y="605.6" textLength="12.2" clip-path="url(#terminal-199999382-line-24)">(</text><text class="terminal-199999382-r1" x="146.4" y="605.6" textLength="12.2" clip-path="url(#terminal-199999382-line-24)">c</text><text class="terminal-199999382-r2" x="158.6" y="605.6" textLength="12.2" clip-path="url(#terminal-199999382-line-24)">)</text><text class="terminal-199999382-r1" x="170.8" y="605.6" textLength="341.6" clip-path="url(#terminal-199999382-line-24)">          Create new commit.</text><text class="terminal-199999382-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-199999382-line-24)"> +</text><text class="terminal-199999382-r1" x="0" y="630" textLength="622.2" clip-path="url(#terminal-199999382-line-25)">    ls                  Show available Commitizens.</text><text class="terminal-199999382-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-199999382-line-25)"> +</text><text class="terminal-199999382-r1" x="0" y="654.4" textLength="536.8" clip-path="url(#terminal-199999382-line-26)">    example             Show commit example.</text><text class="terminal-199999382-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-199999382-line-26)"> +</text><text class="terminal-199999382-r1" x="0" y="678.8" textLength="658.8" clip-path="url(#terminal-199999382-line-27)">    info                Show information about the cz.</text><text class="terminal-199999382-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-199999382-line-27)"> +</text><text class="terminal-199999382-r1" x="0" y="703.2" textLength="524.6" clip-path="url(#terminal-199999382-line-28)">    schema              Show commit schema.</text><text class="terminal-199999382-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-199999382-line-28)"> +</text><text class="terminal-199999382-r1" x="0" y="727.6" textLength="817.4" clip-path="url(#terminal-199999382-line-29)">    bump                Bump semantic version based on the git log.</text><text class="terminal-199999382-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-199999382-line-29)"> +</text><text class="terminal-199999382-r1" x="0" y="752" textLength="170.8" clip-path="url(#terminal-199999382-line-30)">    changelog </text><text class="terminal-199999382-r2" x="170.8" y="752" textLength="12.2" clip-path="url(#terminal-199999382-line-30)">(</text><text class="terminal-199999382-r1" x="183" y="752" textLength="24.4" clip-path="url(#terminal-199999382-line-30)">ch</text><text class="terminal-199999382-r2" x="207.4" y="752" textLength="12.2" clip-path="url(#terminal-199999382-line-30)">)</text><text class="terminal-199999382-r1" x="219.6" y="752" textLength="305" clip-path="url(#terminal-199999382-line-30)">      Generate changelog </text><text class="terminal-199999382-r2" x="524.6" y="752" textLength="12.2" clip-path="url(#terminal-199999382-line-30)">(</text><text class="terminal-199999382-r1" x="536.8" y="752" textLength="329.4" clip-path="url(#terminal-199999382-line-30)">note that it will overwrite</text><text class="terminal-199999382-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-199999382-line-30)"> +</text><text class="terminal-199999382-r1" x="0" y="776.4" textLength="463.6" clip-path="url(#terminal-199999382-line-31)">                        existing files</text><text class="terminal-199999382-r2" x="463.6" y="776.4" textLength="12.2" clip-path="url(#terminal-199999382-line-31)">)</text><text class="terminal-199999382-r1" x="475.8" y="776.4" textLength="12.2" clip-path="url(#terminal-199999382-line-31)">.</text><text class="terminal-199999382-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-199999382-line-31)"> +</text><text class="terminal-199999382-r1" x="0" y="800.8" textLength="939.4" clip-path="url(#terminal-199999382-line-32)">    check               Validate that a commit message matches the commitizen</text><text class="terminal-199999382-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-199999382-line-32)"> +</text><text class="terminal-199999382-r1" x="0" y="825.2" textLength="378.2" clip-path="url(#terminal-199999382-line-33)">                        schema.</text><text class="terminal-199999382-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-199999382-line-33)"> +</text><text class="terminal-199999382-r1" x="0" y="849.6" textLength="902.8" clip-path="url(#terminal-199999382-line-34)">    version             Get the version of the installed commitizen or the</text><text class="terminal-199999382-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-199999382-line-34)"> +</text><text class="terminal-199999382-r1" x="0" y="874" textLength="488" clip-path="url(#terminal-199999382-line-35)">                        current project </text><text class="terminal-199999382-r2" x="488" y="874" textLength="12.2" clip-path="url(#terminal-199999382-line-35)">(</text><text class="terminal-199999382-r1" x="500.2" y="874" textLength="353.8" clip-path="url(#terminal-199999382-line-35)">default: installed commitizen</text><text class="terminal-199999382-r2" x="854" y="874" textLength="12.2" clip-path="url(#terminal-199999382-line-35)">)</text><text class="terminal-199999382-r1" x="866.2" y="874" textLength="12.2" clip-path="url(#terminal-199999382-line-35)">.</text><text class="terminal-199999382-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-199999382-line-35)"> +</text><text class="terminal-199999382-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-199999382-line-36)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_bump___help.svg b/docs/images/cli_help/cz_bump___help.svg index dff62998d2..ec6b4816f1 100644 --- a/docs/images/cli_help/cz_bump___help.svg +++ b/docs/images/cli_help/cz_bump___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 2099.6" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 2221.6" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,374 +19,395 @@ font-weight: 700; } - .terminal-1363677843-matrix { + .terminal-993994783-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1363677843-title { + .terminal-993994783-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1363677843-r1 { fill: #c5c8c6 } -.terminal-1363677843-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-1363677843-r3 { fill: #68a0b3;font-weight: bold } -.terminal-1363677843-r4 { fill: #98a84b } + .terminal-993994783-r1 { fill: #c5c8c6 } +.terminal-993994783-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-993994783-r3 { fill: #68a0b3;font-weight: bold } +.terminal-993994783-r4 { fill: #98729f;font-weight: bold } +.terminal-993994783-r5 { fill: #98a84b } </style> <defs> - <clipPath id="terminal-1363677843-clip-terminal"> - <rect x="0" y="0" width="975.0" height="2048.6" /> + <clipPath id="terminal-993994783-clip-terminal"> + <rect x="0" y="0" width="975.0" height="2170.6" /> </clipPath> - <clipPath id="terminal-1363677843-line-0"> + <clipPath id="terminal-993994783-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-1"> +<clipPath id="terminal-993994783-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-2"> +<clipPath id="terminal-993994783-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-3"> +<clipPath id="terminal-993994783-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-4"> +<clipPath id="terminal-993994783-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-5"> +<clipPath id="terminal-993994783-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-6"> +<clipPath id="terminal-993994783-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-7"> +<clipPath id="terminal-993994783-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-8"> +<clipPath id="terminal-993994783-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-9"> +<clipPath id="terminal-993994783-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-10"> +<clipPath id="terminal-993994783-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-11"> +<clipPath id="terminal-993994783-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-12"> +<clipPath id="terminal-993994783-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-13"> +<clipPath id="terminal-993994783-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-14"> +<clipPath id="terminal-993994783-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-15"> +<clipPath id="terminal-993994783-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-16"> +<clipPath id="terminal-993994783-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-17"> +<clipPath id="terminal-993994783-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-18"> +<clipPath id="terminal-993994783-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-19"> +<clipPath id="terminal-993994783-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-20"> +<clipPath id="terminal-993994783-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-21"> +<clipPath id="terminal-993994783-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-22"> +<clipPath id="terminal-993994783-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-23"> +<clipPath id="terminal-993994783-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-24"> +<clipPath id="terminal-993994783-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-25"> +<clipPath id="terminal-993994783-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-26"> +<clipPath id="terminal-993994783-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-27"> +<clipPath id="terminal-993994783-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-28"> +<clipPath id="terminal-993994783-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-29"> +<clipPath id="terminal-993994783-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-30"> +<clipPath id="terminal-993994783-line-30"> <rect x="0" y="733.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-31"> +<clipPath id="terminal-993994783-line-31"> <rect x="0" y="757.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-32"> +<clipPath id="terminal-993994783-line-32"> <rect x="0" y="782.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-33"> +<clipPath id="terminal-993994783-line-33"> <rect x="0" y="806.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-34"> +<clipPath id="terminal-993994783-line-34"> <rect x="0" y="831.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-35"> +<clipPath id="terminal-993994783-line-35"> <rect x="0" y="855.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-36"> +<clipPath id="terminal-993994783-line-36"> <rect x="0" y="879.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-37"> +<clipPath id="terminal-993994783-line-37"> <rect x="0" y="904.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-38"> +<clipPath id="terminal-993994783-line-38"> <rect x="0" y="928.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-39"> +<clipPath id="terminal-993994783-line-39"> <rect x="0" y="953.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-40"> +<clipPath id="terminal-993994783-line-40"> <rect x="0" y="977.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-41"> +<clipPath id="terminal-993994783-line-41"> <rect x="0" y="1001.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-42"> +<clipPath id="terminal-993994783-line-42"> <rect x="0" y="1026.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-43"> +<clipPath id="terminal-993994783-line-43"> <rect x="0" y="1050.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-44"> +<clipPath id="terminal-993994783-line-44"> <rect x="0" y="1075.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-45"> +<clipPath id="terminal-993994783-line-45"> <rect x="0" y="1099.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-46"> +<clipPath id="terminal-993994783-line-46"> <rect x="0" y="1123.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-47"> +<clipPath id="terminal-993994783-line-47"> <rect x="0" y="1148.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-48"> +<clipPath id="terminal-993994783-line-48"> <rect x="0" y="1172.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-49"> +<clipPath id="terminal-993994783-line-49"> <rect x="0" y="1197.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-50"> +<clipPath id="terminal-993994783-line-50"> <rect x="0" y="1221.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-51"> +<clipPath id="terminal-993994783-line-51"> <rect x="0" y="1245.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-52"> +<clipPath id="terminal-993994783-line-52"> <rect x="0" y="1270.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-53"> +<clipPath id="terminal-993994783-line-53"> <rect x="0" y="1294.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-54"> +<clipPath id="terminal-993994783-line-54"> <rect x="0" y="1319.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-55"> +<clipPath id="terminal-993994783-line-55"> <rect x="0" y="1343.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-56"> +<clipPath id="terminal-993994783-line-56"> <rect x="0" y="1367.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-57"> +<clipPath id="terminal-993994783-line-57"> <rect x="0" y="1392.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-58"> +<clipPath id="terminal-993994783-line-58"> <rect x="0" y="1416.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-59"> +<clipPath id="terminal-993994783-line-59"> <rect x="0" y="1441.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-60"> +<clipPath id="terminal-993994783-line-60"> <rect x="0" y="1465.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-61"> +<clipPath id="terminal-993994783-line-61"> <rect x="0" y="1489.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-62"> +<clipPath id="terminal-993994783-line-62"> <rect x="0" y="1514.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-63"> +<clipPath id="terminal-993994783-line-63"> <rect x="0" y="1538.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-64"> +<clipPath id="terminal-993994783-line-64"> <rect x="0" y="1563.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-65"> +<clipPath id="terminal-993994783-line-65"> <rect x="0" y="1587.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-66"> +<clipPath id="terminal-993994783-line-66"> <rect x="0" y="1611.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-67"> +<clipPath id="terminal-993994783-line-67"> <rect x="0" y="1636.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-68"> +<clipPath id="terminal-993994783-line-68"> <rect x="0" y="1660.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-69"> +<clipPath id="terminal-993994783-line-69"> <rect x="0" y="1685.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-70"> +<clipPath id="terminal-993994783-line-70"> <rect x="0" y="1709.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-71"> +<clipPath id="terminal-993994783-line-71"> <rect x="0" y="1733.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-72"> +<clipPath id="terminal-993994783-line-72"> <rect x="0" y="1758.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-73"> +<clipPath id="terminal-993994783-line-73"> <rect x="0" y="1782.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-74"> +<clipPath id="terminal-993994783-line-74"> <rect x="0" y="1807.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-75"> +<clipPath id="terminal-993994783-line-75"> <rect x="0" y="1831.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-76"> +<clipPath id="terminal-993994783-line-76"> <rect x="0" y="1855.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-77"> +<clipPath id="terminal-993994783-line-77"> <rect x="0" y="1880.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-78"> +<clipPath id="terminal-993994783-line-78"> <rect x="0" y="1904.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-79"> +<clipPath id="terminal-993994783-line-79"> <rect x="0" y="1929.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-80"> +<clipPath id="terminal-993994783-line-80"> <rect x="0" y="1953.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-81"> +<clipPath id="terminal-993994783-line-81"> <rect x="0" y="1977.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1363677843-line-82"> +<clipPath id="terminal-993994783-line-82"> <rect x="0" y="2002.3" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-993994783-line-83"> + <rect x="0" y="2026.7" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-993994783-line-84"> + <rect x="0" y="2051.1" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-993994783-line-85"> + <rect x="0" y="2075.5" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-993994783-line-86"> + <rect x="0" y="2099.9" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-993994783-line-87"> + <rect x="0" y="2124.3" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="2097.6" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="2219.6" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1363677843-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-993994783-clip-terminal)"> - <g class="terminal-1363677843-matrix"> - <text class="terminal-1363677843-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-1363677843-line-0)">$ cz bump --help</text><text class="terminal-1363677843-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1363677843-line-0)"> -</text><text class="terminal-1363677843-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-1363677843-line-1)">usage: cz bump </text><text class="terminal-1363677843-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1363677843-line-1)">-h</text><text class="terminal-1363677843-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="256.2" y="44.4" textLength="109.8" clip-path="url(#terminal-1363677843-line-1)">--dry-run</text><text class="terminal-1363677843-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="402.6" y="44.4" textLength="146.4" clip-path="url(#terminal-1363677843-line-1)">--files-only</text><text class="terminal-1363677843-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="573.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="585.6" y="44.4" textLength="183" clip-path="url(#terminal-1363677843-line-1)">--local-version</text><text class="terminal-1363677843-r2" x="768.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r2" x="793" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">[</text><text class="terminal-1363677843-r1" x="805.2" y="44.4" textLength="134.2" clip-path="url(#terminal-1363677843-line-1)">--changelog</text><text class="terminal-1363677843-r2" x="939.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)">]</text><text class="terminal-1363677843-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-1)"> -</text><text class="terminal-1363677843-r2" x="183" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">[</text><text class="terminal-1363677843-r1" x="195.2" y="68.8" textLength="134.2" clip-path="url(#terminal-1363677843-line-2)">--no-verify</text><text class="terminal-1363677843-r2" x="329.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">]</text><text class="terminal-1363677843-r2" x="353.8" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">[</text><text class="terminal-1363677843-r1" x="366" y="68.8" textLength="61" clip-path="url(#terminal-1363677843-line-2)">--yes</text><text class="terminal-1363677843-r2" x="427" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">]</text><text class="terminal-1363677843-r2" x="451.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">[</text><text class="terminal-1363677843-r1" x="463.6" y="68.8" textLength="280.6" clip-path="url(#terminal-1363677843-line-2)">--tag-format TAG_FORMAT</text><text class="terminal-1363677843-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)">]</text><text class="terminal-1363677843-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-2)"> -</text><text class="terminal-1363677843-r2" x="183" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">[</text><text class="terminal-1363677843-r1" x="195.2" y="93.2" textLength="329.4" clip-path="url(#terminal-1363677843-line-3)">--bump-message BUMP_MESSAGE</text><text class="terminal-1363677843-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">]</text><text class="terminal-1363677843-r2" x="549" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">[</text><text class="terminal-1363677843-r1" x="561.2" y="93.2" textLength="158.6" clip-path="url(#terminal-1363677843-line-3)">--prerelease </text><text class="terminal-1363677843-r2" x="719.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">{</text><text class="terminal-1363677843-r1" x="732" y="93.2" textLength="158.6" clip-path="url(#terminal-1363677843-line-3)">alpha,beta,rc</text><text class="terminal-1363677843-r2" x="890.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">}</text><text class="terminal-1363677843-r2" x="902.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)">]</text><text class="terminal-1363677843-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-3)"> -</text><text class="terminal-1363677843-r2" x="183" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">[</text><text class="terminal-1363677843-r1" x="195.2" y="117.6" textLength="280.6" clip-path="url(#terminal-1363677843-line-4)">--devrelease DEVRELEASE</text><text class="terminal-1363677843-r2" x="475.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">]</text><text class="terminal-1363677843-r2" x="500.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">[</text><text class="terminal-1363677843-r1" x="512.4" y="117.6" textLength="146.4" clip-path="url(#terminal-1363677843-line-4)">--increment </text><text class="terminal-1363677843-r2" x="658.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">{</text><text class="terminal-1363677843-r1" x="671" y="117.6" textLength="207.4" clip-path="url(#terminal-1363677843-line-4)">MAJOR,MINOR,PATCH</text><text class="terminal-1363677843-r2" x="878.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">}</text><text class="terminal-1363677843-r2" x="890.6" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)">]</text><text class="terminal-1363677843-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-4)"> -</text><text class="terminal-1363677843-r2" x="183" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">[</text><text class="terminal-1363677843-r1" x="195.2" y="142" textLength="207.4" clip-path="url(#terminal-1363677843-line-5)">--increment-mode </text><text class="terminal-1363677843-r2" x="402.6" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">{</text><text class="terminal-1363677843-r1" x="414.8" y="142" textLength="146.4" clip-path="url(#terminal-1363677843-line-5)">linear,exact</text><text class="terminal-1363677843-r2" x="561.2" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">}</text><text class="terminal-1363677843-r2" x="573.4" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">]</text><text class="terminal-1363677843-r2" x="597.8" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">[</text><text class="terminal-1363677843-r1" x="610" y="142" textLength="231.8" clip-path="url(#terminal-1363677843-line-5)">--check-consistency</text><text class="terminal-1363677843-r2" x="841.8" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)">]</text><text class="terminal-1363677843-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1363677843-line-5)"> -</text><text class="terminal-1363677843-r2" x="183" y="166.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-6)">[</text><text class="terminal-1363677843-r1" x="195.2" y="166.4" textLength="183" clip-path="url(#terminal-1363677843-line-6)">--annotated-tag</text><text class="terminal-1363677843-r2" x="378.2" y="166.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-6)">]</text><text class="terminal-1363677843-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-6)"> -</text><text class="terminal-1363677843-r2" x="183" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">[</text><text class="terminal-1363677843-r1" x="195.2" y="190.8" textLength="549" clip-path="url(#terminal-1363677843-line-7)">--annotated-tag-message ANNOTATED_TAG_MESSAGE</text><text class="terminal-1363677843-r2" x="744.2" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">]</text><text class="terminal-1363677843-r2" x="768.6" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">[</text><text class="terminal-1363677843-r1" x="780.8" y="190.8" textLength="122" clip-path="url(#terminal-1363677843-line-7)">--gpg-sign</text><text class="terminal-1363677843-r2" x="902.8" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)">]</text><text class="terminal-1363677843-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-7)"> -</text><text class="terminal-1363677843-r2" x="183" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">[</text><text class="terminal-1363677843-r1" x="195.2" y="215.2" textLength="256.2" clip-path="url(#terminal-1363677843-line-8)">--changelog-to-stdout</text><text class="terminal-1363677843-r2" x="451.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">]</text><text class="terminal-1363677843-r2" x="475.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">[</text><text class="terminal-1363677843-r1" x="488" y="215.2" textLength="268.4" clip-path="url(#terminal-1363677843-line-8)">--git-output-to-stderr</text><text class="terminal-1363677843-r2" x="756.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">]</text><text class="terminal-1363677843-r2" x="780.8" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">[</text><text class="terminal-1363677843-r1" x="793" y="215.2" textLength="85.4" clip-path="url(#terminal-1363677843-line-8)">--retry</text><text class="terminal-1363677843-r2" x="878.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)">]</text><text class="terminal-1363677843-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-8)"> -</text><text class="terminal-1363677843-r2" x="183" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">[</text><text class="terminal-1363677843-r1" x="195.2" y="239.6" textLength="244" clip-path="url(#terminal-1363677843-line-9)">--major-version-zero</text><text class="terminal-1363677843-r2" x="439.2" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">]</text><text class="terminal-1363677843-r2" x="463.6" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">[</text><text class="terminal-1363677843-r1" x="475.8" y="239.6" textLength="231.8" clip-path="url(#terminal-1363677843-line-9)">--template TEMPLATE</text><text class="terminal-1363677843-r2" x="707.6" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">]</text><text class="terminal-1363677843-r2" x="732" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">[</text><text class="terminal-1363677843-r1" x="744.2" y="239.6" textLength="158.6" clip-path="url(#terminal-1363677843-line-9)">--extra EXTRA</text><text class="terminal-1363677843-r2" x="902.8" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)">]</text><text class="terminal-1363677843-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-9)"> -</text><text class="terminal-1363677843-r2" x="183" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">[</text><text class="terminal-1363677843-r1" x="195.2" y="264" textLength="256.2" clip-path="url(#terminal-1363677843-line-10)">--file-name FILE_NAME</text><text class="terminal-1363677843-r2" x="451.4" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">]</text><text class="terminal-1363677843-r2" x="475.8" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">[</text><text class="terminal-1363677843-r1" x="488" y="264" textLength="451.4" clip-path="url(#terminal-1363677843-line-10)">--prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-1363677843-r2" x="939.4" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)">]</text><text class="terminal-1363677843-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1363677843-line-10)"> -</text><text class="terminal-1363677843-r2" x="183" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">[</text><text class="terminal-1363677843-r1" x="195.2" y="288.4" textLength="207.4" clip-path="url(#terminal-1363677843-line-11)">--version-scheme </text><text class="terminal-1363677843-r2" x="402.6" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">{</text><text class="terminal-1363677843-r1" x="414.8" y="288.4" textLength="256.2" clip-path="url(#terminal-1363677843-line-11)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="671" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">}</text><text class="terminal-1363677843-r2" x="683.2" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)">]</text><text class="terminal-1363677843-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-11)"> -</text><text class="terminal-1363677843-r2" x="183" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">[</text><text class="terminal-1363677843-r1" x="195.2" y="312.8" textLength="183" clip-path="url(#terminal-1363677843-line-12)">--version-type </text><text class="terminal-1363677843-r2" x="378.2" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">{</text><text class="terminal-1363677843-r1" x="390.4" y="312.8" textLength="256.2" clip-path="url(#terminal-1363677843-line-12)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="646.6" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">}</text><text class="terminal-1363677843-r2" x="658.8" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)">]</text><text class="terminal-1363677843-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-12)"> -</text><text class="terminal-1363677843-r2" x="183" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">[</text><text class="terminal-1363677843-r1" x="195.2" y="337.2" textLength="378.2" clip-path="url(#terminal-1363677843-line-13)">--build-metadata BUILD_METADATA</text><text class="terminal-1363677843-r2" x="573.4" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">]</text><text class="terminal-1363677843-r2" x="597.8" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">[</text><text class="terminal-1363677843-r1" x="610" y="337.2" textLength="122" clip-path="url(#terminal-1363677843-line-13)">--get-next</text><text class="terminal-1363677843-r2" x="732" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)">]</text><text class="terminal-1363677843-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-13)"> -</text><text class="terminal-1363677843-r2" x="183" y="361.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-14)">[</text><text class="terminal-1363677843-r1" x="195.2" y="361.6" textLength="207.4" clip-path="url(#terminal-1363677843-line-14)">--allow-no-commit</text><text class="terminal-1363677843-r2" x="402.6" y="361.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-14)">]</text><text class="terminal-1363677843-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-14)"> -</text><text class="terminal-1363677843-r2" x="183" y="386" textLength="12.2" clip-path="url(#terminal-1363677843-line-15)">[</text><text class="terminal-1363677843-r1" x="195.2" y="386" textLength="170.8" clip-path="url(#terminal-1363677843-line-15)">MANUAL_VERSION</text><text class="terminal-1363677843-r2" x="366" y="386" textLength="12.2" clip-path="url(#terminal-1363677843-line-15)">]</text><text class="terminal-1363677843-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1363677843-line-15)"> -</text><text class="terminal-1363677843-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-16)"> -</text><text class="terminal-1363677843-r1" x="0" y="434.8" textLength="512.4" clip-path="url(#terminal-1363677843-line-17)">bump semantic version based on the git log</text><text class="terminal-1363677843-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-17)"> -</text><text class="terminal-1363677843-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-18)"> -</text><text class="terminal-1363677843-r1" x="0" y="483.6" textLength="256.2" clip-path="url(#terminal-1363677843-line-19)">positional arguments:</text><text class="terminal-1363677843-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-19)"> -</text><text class="terminal-1363677843-r1" x="0" y="508" textLength="610" clip-path="url(#terminal-1363677843-line-20)">  MANUAL_VERSION        bump to the given version </text><text class="terminal-1363677843-r2" x="610" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">(</text><text class="terminal-1363677843-r1" x="622.2" y="508" textLength="61" clip-path="url(#terminal-1363677843-line-20)">e.g: </text><text class="terminal-1363677843-r3" x="683.2" y="508" textLength="36.6" clip-path="url(#terminal-1363677843-line-20)">1.5</text><text class="terminal-1363677843-r1" x="719.8" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">.</text><text class="terminal-1363677843-r3" x="732" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">3</text><text class="terminal-1363677843-r2" x="744.2" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)">)</text><text class="terminal-1363677843-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1363677843-line-20)"> -</text><text class="terminal-1363677843-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-21)"> -</text><text class="terminal-1363677843-r1" x="0" y="556.8" textLength="97.6" clip-path="url(#terminal-1363677843-line-22)">options:</text><text class="terminal-1363677843-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-22)"> -</text><text class="terminal-1363677843-r1" x="0" y="581.2" textLength="671" clip-path="url(#terminal-1363677843-line-23)">  -h, --help            show this help message and exit</text><text class="terminal-1363677843-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-23)"> -</text><text class="terminal-1363677843-r1" x="0" y="605.6" textLength="915" clip-path="url(#terminal-1363677843-line-24)">  --dry-run             show output to stdout, no commit, no modified files</text><text class="terminal-1363677843-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-24)"> -</text><text class="terminal-1363677843-r1" x="0" y="630" textLength="793" clip-path="url(#terminal-1363677843-line-25)">  --files-only          bump version in the files from the config</text><text class="terminal-1363677843-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1363677843-line-25)"> -</text><text class="terminal-1363677843-r1" x="0" y="654.4" textLength="719.8" clip-path="url(#terminal-1363677843-line-26)">  --local-version       bump only the local version portion</text><text class="terminal-1363677843-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-26)"> -</text><text class="terminal-1363677843-r1" x="0" y="678.8" textLength="841.8" clip-path="url(#terminal-1363677843-line-27)">  --changelog, -ch      generate the changelog for the newest version</text><text class="terminal-1363677843-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-27)"> -</text><text class="terminal-1363677843-r1" x="0" y="703.2" textLength="902.8" clip-path="url(#terminal-1363677843-line-28)">  --no-verify           this option bypasses the pre-commit and commit-msg</text><text class="terminal-1363677843-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-28)"> -</text><text class="terminal-1363677843-r1" x="0" y="727.6" textLength="353.8" clip-path="url(#terminal-1363677843-line-29)">                        hooks</text><text class="terminal-1363677843-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-29)"> -</text><text class="terminal-1363677843-r1" x="0" y="752" textLength="719.8" clip-path="url(#terminal-1363677843-line-30)">  --yes                 accept automatically questions done</text><text class="terminal-1363677843-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1363677843-line-30)"> -</text><text class="terminal-1363677843-r1" x="0" y="776.4" textLength="305" clip-path="url(#terminal-1363677843-line-31)">  --tag-format TAG_FORMAT</text><text class="terminal-1363677843-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-31)"> -</text><text class="terminal-1363677843-r1" x="0" y="800.8" textLength="939.4" clip-path="url(#terminal-1363677843-line-32)">                        the format used to tag the commit and read it, use it</text><text class="terminal-1363677843-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-32)"> -</text><text class="terminal-1363677843-r1" x="0" y="825.2" textLength="866.2" clip-path="url(#terminal-1363677843-line-33)">                        in existing projects, wrap around simple quotes</text><text class="terminal-1363677843-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-33)"> -</text><text class="terminal-1363677843-r1" x="0" y="849.6" textLength="353.8" clip-path="url(#terminal-1363677843-line-34)">  --bump-message BUMP_MESSAGE</text><text class="terminal-1363677843-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-34)"> -</text><text class="terminal-1363677843-r1" x="0" y="874" textLength="902.8" clip-path="url(#terminal-1363677843-line-35)">                        template used to create the release commit, useful</text><text class="terminal-1363677843-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-1363677843-line-35)"> -</text><text class="terminal-1363677843-r1" x="0" y="898.4" textLength="536.8" clip-path="url(#terminal-1363677843-line-36)">                        when working with CI</text><text class="terminal-1363677843-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-36)"> -</text><text class="terminal-1363677843-r1" x="0" y="922.8" textLength="183" clip-path="url(#terminal-1363677843-line-37)">  --prerelease </text><text class="terminal-1363677843-r2" x="183" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">{</text><text class="terminal-1363677843-r1" x="195.2" y="922.8" textLength="158.6" clip-path="url(#terminal-1363677843-line-37)">alpha,beta,rc</text><text class="terminal-1363677843-r2" x="353.8" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">}</text><text class="terminal-1363677843-r1" x="366" y="922.8" textLength="73.2" clip-path="url(#terminal-1363677843-line-37)">, -pr </text><text class="terminal-1363677843-r2" x="439.2" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">{</text><text class="terminal-1363677843-r1" x="451.4" y="922.8" textLength="158.6" clip-path="url(#terminal-1363677843-line-37)">alpha,beta,rc</text><text class="terminal-1363677843-r2" x="610" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)">}</text><text class="terminal-1363677843-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-37)"> -</text><text class="terminal-1363677843-r1" x="0" y="947.2" textLength="597.8" clip-path="url(#terminal-1363677843-line-38)">                        choose type of prerelease</text><text class="terminal-1363677843-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-38)"> -</text><text class="terminal-1363677843-r1" x="0" y="971.6" textLength="488" clip-path="url(#terminal-1363677843-line-39)">  --devrelease DEVRELEASE, -d DEVRELEASE</text><text class="terminal-1363677843-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-39)"> -</text><text class="terminal-1363677843-r1" x="0" y="996" textLength="841.8" clip-path="url(#terminal-1363677843-line-40)">                        specify non-negative integer for dev. release</text><text class="terminal-1363677843-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-1363677843-line-40)"> -</text><text class="terminal-1363677843-r1" x="0" y="1020.4" textLength="170.8" clip-path="url(#terminal-1363677843-line-41)">  --increment </text><text class="terminal-1363677843-r2" x="170.8" y="1020.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-41)">{</text><text class="terminal-1363677843-r1" x="183" y="1020.4" textLength="207.4" clip-path="url(#terminal-1363677843-line-41)">MAJOR,MINOR,PATCH</text><text class="terminal-1363677843-r2" x="390.4" y="1020.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-41)">}</text><text class="terminal-1363677843-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-41)"> -</text><text class="terminal-1363677843-r1" x="0" y="1044.8" textLength="756.4" clip-path="url(#terminal-1363677843-line-42)">                        manually specify the desired increment</text><text class="terminal-1363677843-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-42)"> -</text><text class="terminal-1363677843-r1" x="0" y="1069.2" textLength="231.8" clip-path="url(#terminal-1363677843-line-43)">  --increment-mode </text><text class="terminal-1363677843-r2" x="231.8" y="1069.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-43)">{</text><text class="terminal-1363677843-r1" x="244" y="1069.2" textLength="146.4" clip-path="url(#terminal-1363677843-line-43)">linear,exact</text><text class="terminal-1363677843-r2" x="390.4" y="1069.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-43)">}</text><text class="terminal-1363677843-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-43)"> -</text><text class="terminal-1363677843-r1" x="0" y="1093.6" textLength="902.8" clip-path="url(#terminal-1363677843-line-44)">                        set the method by which the new version is chosen.</text><text class="terminal-1363677843-r1" x="976" y="1093.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-44)"> -</text><text class="terminal-1363677843-r4" x="292.8" y="1118" textLength="97.6" clip-path="url(#terminal-1363677843-line-45)">'linear'</text><text class="terminal-1363677843-r2" x="402.6" y="1118" textLength="12.2" clip-path="url(#terminal-1363677843-line-45)">(</text><text class="terminal-1363677843-r1" x="414.8" y="1118" textLength="85.4" clip-path="url(#terminal-1363677843-line-45)">default</text><text class="terminal-1363677843-r2" x="500.2" y="1118" textLength="12.2" clip-path="url(#terminal-1363677843-line-45)">)</text><text class="terminal-1363677843-r1" x="512.4" y="1118" textLength="414.8" clip-path="url(#terminal-1363677843-line-45)"> guesses the next version based on</text><text class="terminal-1363677843-r1" x="976" y="1118" textLength="12.2" clip-path="url(#terminal-1363677843-line-45)"> -</text><text class="terminal-1363677843-r1" x="0" y="1142.4" textLength="939.4" clip-path="url(#terminal-1363677843-line-46)">                        typical linear version progression, such that bumping</text><text class="terminal-1363677843-r1" x="976" y="1142.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-46)"> -</text><text class="terminal-1363677843-r1" x="0" y="1166.8" textLength="866.2" clip-path="url(#terminal-1363677843-line-47)">                        of a pre-release with lower precedence than the</text><text class="terminal-1363677843-r1" x="976" y="1166.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-47)"> -</text><text class="terminal-1363677843-r1" x="0" y="1191.2" textLength="939.4" clip-path="url(#terminal-1363677843-line-48)">                        current pre-release phase maintains the current phase</text><text class="terminal-1363677843-r1" x="976" y="1191.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-48)"> -</text><text class="terminal-1363677843-r1" x="0" y="1215.6" textLength="561.2" clip-path="url(#terminal-1363677843-line-49)">                        of higher precedence. </text><text class="terminal-1363677843-r4" x="561.2" y="1215.6" textLength="85.4" clip-path="url(#terminal-1363677843-line-49)">'exact'</text><text class="terminal-1363677843-r1" x="646.6" y="1215.6" textLength="305" clip-path="url(#terminal-1363677843-line-49)"> applies the changes that</text><text class="terminal-1363677843-r1" x="976" y="1215.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-49)"> -</text><text class="terminal-1363677843-r1" x="0" y="1240" textLength="536.8" clip-path="url(#terminal-1363677843-line-50)">                        have been specified </text><text class="terminal-1363677843-r2" x="536.8" y="1240" textLength="12.2" clip-path="url(#terminal-1363677843-line-50)">(</text><text class="terminal-1363677843-r1" x="549" y="1240" textLength="353.8" clip-path="url(#terminal-1363677843-line-50)">or determined from the commit</text><text class="terminal-1363677843-r1" x="976" y="1240" textLength="12.2" clip-path="url(#terminal-1363677843-line-50)"> -</text><text class="terminal-1363677843-r1" x="0" y="1264.4" textLength="329.4" clip-path="url(#terminal-1363677843-line-51)">                        log</text><text class="terminal-1363677843-r2" x="329.4" y="1264.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-51)">)</text><text class="terminal-1363677843-r1" x="341.6" y="1264.4" textLength="585.6" clip-path="url(#terminal-1363677843-line-51)"> without interpretation, such that the increment</text><text class="terminal-1363677843-r1" x="976" y="1264.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-51)"> -</text><text class="terminal-1363677843-r1" x="0" y="1288.8" textLength="707.6" clip-path="url(#terminal-1363677843-line-52)">                        and pre-release are always honored</text><text class="terminal-1363677843-r1" x="976" y="1288.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-52)"> -</text><text class="terminal-1363677843-r1" x="0" y="1313.2" textLength="317.2" clip-path="url(#terminal-1363677843-line-53)">  --check-consistency, -cc</text><text class="terminal-1363677843-r1" x="976" y="1313.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-53)"> -</text><text class="terminal-1363677843-r1" x="0" y="1337.6" textLength="951.6" clip-path="url(#terminal-1363677843-line-54)">                        check consistency among versions defined in commitizen</text><text class="terminal-1363677843-r1" x="976" y="1337.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-54)"> -</text><text class="terminal-1363677843-r1" x="0" y="1362" textLength="671" clip-path="url(#terminal-1363677843-line-55)">                        configuration and version_files</text><text class="terminal-1363677843-r1" x="976" y="1362" textLength="12.2" clip-path="url(#terminal-1363677843-line-55)"> -</text><text class="terminal-1363677843-r1" x="0" y="1386.4" textLength="866.2" clip-path="url(#terminal-1363677843-line-56)">  --annotated-tag, -at  create annotated tag instead of lightweight one</text><text class="terminal-1363677843-r1" x="976" y="1386.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-56)"> -</text><text class="terminal-1363677843-r1" x="0" y="1410.8" textLength="915" clip-path="url(#terminal-1363677843-line-57)">  --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE</text><text class="terminal-1363677843-r1" x="976" y="1410.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-57)"> -</text><text class="terminal-1363677843-r1" x="0" y="1435.2" textLength="634.4" clip-path="url(#terminal-1363677843-line-58)">                        create annotated tag message</text><text class="terminal-1363677843-r1" x="976" y="1435.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-58)"> -</text><text class="terminal-1363677843-r1" x="0" y="1459.6" textLength="719.8" clip-path="url(#terminal-1363677843-line-59)">  --gpg-sign, -s        sign tag instead of lightweight one</text><text class="terminal-1363677843-r1" x="976" y="1459.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-59)"> -</text><text class="terminal-1363677843-r1" x="0" y="1484" textLength="280.6" clip-path="url(#terminal-1363677843-line-60)">  --changelog-to-stdout</text><text class="terminal-1363677843-r1" x="976" y="1484" textLength="12.2" clip-path="url(#terminal-1363677843-line-60)"> -</text><text class="terminal-1363677843-r1" x="0" y="1508.4" textLength="658.8" clip-path="url(#terminal-1363677843-line-61)">                        Output changelog to the stdout</text><text class="terminal-1363677843-r1" x="976" y="1508.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-61)"> -</text><text class="terminal-1363677843-r1" x="0" y="1532.8" textLength="292.8" clip-path="url(#terminal-1363677843-line-62)">  --git-output-to-stderr</text><text class="terminal-1363677843-r1" x="976" y="1532.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-62)"> -</text><text class="terminal-1363677843-r1" x="0" y="1557.2" textLength="646.6" clip-path="url(#terminal-1363677843-line-63)">                        Redirect git output to stderr</text><text class="terminal-1363677843-r1" x="976" y="1557.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-63)"> -</text><text class="terminal-1363677843-r1" x="0" y="1581.6" textLength="744.2" clip-path="url(#terminal-1363677843-line-64)">  --retry               retry commit if it fails the 1st time</text><text class="terminal-1363677843-r1" x="976" y="1581.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-64)"> -</text><text class="terminal-1363677843-r1" x="0" y="1606" textLength="939.4" clip-path="url(#terminal-1363677843-line-65)">  --major-version-zero  keep major version at zero, even for breaking changes</text><text class="terminal-1363677843-r1" x="976" y="1606" textLength="12.2" clip-path="url(#terminal-1363677843-line-65)"> -</text><text class="terminal-1363677843-r1" x="0" y="1630.4" textLength="414.8" clip-path="url(#terminal-1363677843-line-66)">  --template TEMPLATE, -t TEMPLATE</text><text class="terminal-1363677843-r1" x="976" y="1630.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-66)"> -</text><text class="terminal-1363677843-r1" x="0" y="1654.8" textLength="646.6" clip-path="url(#terminal-1363677843-line-67)">                        changelog template file name </text><text class="terminal-1363677843-r2" x="646.6" y="1654.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-67)">(</text><text class="terminal-1363677843-r1" x="658.8" y="1654.8" textLength="280.6" clip-path="url(#terminal-1363677843-line-67)">relative to the current</text><text class="terminal-1363677843-r1" x="976" y="1654.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-67)"> -</text><text class="terminal-1363677843-r1" x="0" y="1679.2" textLength="500.2" clip-path="url(#terminal-1363677843-line-68)">                        working directory</text><text class="terminal-1363677843-r2" x="500.2" y="1679.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-68)">)</text><text class="terminal-1363677843-r1" x="976" y="1679.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-68)"> -</text><text class="terminal-1363677843-r1" x="0" y="1703.6" textLength="305" clip-path="url(#terminal-1363677843-line-69)">  --extra EXTRA, -e EXTRA</text><text class="terminal-1363677843-r1" x="976" y="1703.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-69)"> -</text><text class="terminal-1363677843-r1" x="0" y="1728" textLength="622.2" clip-path="url(#terminal-1363677843-line-70)">                        a changelog extra variable </text><text class="terminal-1363677843-r2" x="622.2" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">(</text><text class="terminal-1363677843-r1" x="634.4" y="1728" textLength="146.4" clip-path="url(#terminal-1363677843-line-70)">in the form </text><text class="terminal-1363677843-r4" x="780.8" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">'</text><text class="terminal-1363677843-r4" x="793" y="1728" textLength="36.6" clip-path="url(#terminal-1363677843-line-70)">key</text><text class="terminal-1363677843-r4" x="829.6" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">=</text><text class="terminal-1363677843-r4" x="841.8" y="1728" textLength="61" clip-path="url(#terminal-1363677843-line-70)">value</text><text class="terminal-1363677843-r4" x="902.8" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">'</text><text class="terminal-1363677843-r2" x="915" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)">)</text><text class="terminal-1363677843-r1" x="976" y="1728" textLength="12.2" clip-path="url(#terminal-1363677843-line-70)"> -</text><text class="terminal-1363677843-r1" x="0" y="1752.4" textLength="280.6" clip-path="url(#terminal-1363677843-line-71)">  --file-name FILE_NAME</text><text class="terminal-1363677843-r1" x="976" y="1752.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-71)"> -</text><text class="terminal-1363677843-r1" x="0" y="1776.8" textLength="573.4" clip-path="url(#terminal-1363677843-line-72)">                        file name of changelog </text><text class="terminal-1363677843-r2" x="573.4" y="1776.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-72)">(</text><text class="terminal-1363677843-r1" x="585.6" y="1776.8" textLength="109.8" clip-path="url(#terminal-1363677843-line-72)">default: </text><text class="terminal-1363677843-r4" x="695.4" y="1776.8" textLength="170.8" clip-path="url(#terminal-1363677843-line-72)">'CHANGELOG.md'</text><text class="terminal-1363677843-r2" x="866.2" y="1776.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-72)">)</text><text class="terminal-1363677843-r1" x="976" y="1776.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-72)"> -</text><text class="terminal-1363677843-r1" x="0" y="1801.2" textLength="475.8" clip-path="url(#terminal-1363677843-line-73)">  --prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-1363677843-r1" x="976" y="1801.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-73)"> -</text><text class="terminal-1363677843-r1" x="0" y="1825.6" textLength="719.8" clip-path="url(#terminal-1363677843-line-74)">                        start pre-releases with this offset</text><text class="terminal-1363677843-r1" x="976" y="1825.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-74)"> -</text><text class="terminal-1363677843-r1" x="0" y="1850" textLength="231.8" clip-path="url(#terminal-1363677843-line-75)">  --version-scheme </text><text class="terminal-1363677843-r2" x="231.8" y="1850" textLength="12.2" clip-path="url(#terminal-1363677843-line-75)">{</text><text class="terminal-1363677843-r1" x="244" y="1850" textLength="256.2" clip-path="url(#terminal-1363677843-line-75)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="500.2" y="1850" textLength="12.2" clip-path="url(#terminal-1363677843-line-75)">}</text><text class="terminal-1363677843-r1" x="976" y="1850" textLength="12.2" clip-path="url(#terminal-1363677843-line-75)"> -</text><text class="terminal-1363677843-r1" x="0" y="1874.4" textLength="549" clip-path="url(#terminal-1363677843-line-76)">                        choose version scheme</text><text class="terminal-1363677843-r1" x="976" y="1874.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-76)"> -</text><text class="terminal-1363677843-r1" x="0" y="1898.8" textLength="207.4" clip-path="url(#terminal-1363677843-line-77)">  --version-type </text><text class="terminal-1363677843-r2" x="207.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-77)">{</text><text class="terminal-1363677843-r1" x="219.6" y="1898.8" textLength="256.2" clip-path="url(#terminal-1363677843-line-77)">pep440,semver,semver2</text><text class="terminal-1363677843-r2" x="475.8" y="1898.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-77)">}</text><text class="terminal-1363677843-r1" x="976" y="1898.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-77)"> -</text><text class="terminal-1363677843-r1" x="0" y="1923.2" textLength="780.8" clip-path="url(#terminal-1363677843-line-78)">                        Deprecated, use --version-scheme instead</text><text class="terminal-1363677843-r1" x="976" y="1923.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-78)"> -</text><text class="terminal-1363677843-r1" x="0" y="1947.6" textLength="402.6" clip-path="url(#terminal-1363677843-line-79)">  --build-metadata BUILD_METADATA</text><text class="terminal-1363677843-r1" x="976" y="1947.6" textLength="12.2" clip-path="url(#terminal-1363677843-line-79)"> -</text><text class="terminal-1363677843-r1" x="0" y="1972" textLength="915" clip-path="url(#terminal-1363677843-line-80)">                        Add additional build-metadata to the version-number</text><text class="terminal-1363677843-r1" x="976" y="1972" textLength="12.2" clip-path="url(#terminal-1363677843-line-80)"> -</text><text class="terminal-1363677843-r1" x="0" y="1996.4" textLength="854" clip-path="url(#terminal-1363677843-line-81)">  --get-next            Determine the next version and write to stdout</text><text class="terminal-1363677843-r1" x="976" y="1996.4" textLength="12.2" clip-path="url(#terminal-1363677843-line-81)"> -</text><text class="terminal-1363677843-r1" x="0" y="2020.8" textLength="744.2" clip-path="url(#terminal-1363677843-line-82)">  --allow-no-commit     bump version without eligible commits</text><text class="terminal-1363677843-r1" x="976" y="2020.8" textLength="12.2" clip-path="url(#terminal-1363677843-line-82)"> -</text><text class="terminal-1363677843-r1" x="976" y="2045.2" textLength="12.2" clip-path="url(#terminal-1363677843-line-83)"> + <g class="terminal-993994783-matrix"> + <text class="terminal-993994783-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-993994783-line-0)">$ cz bump --help</text><text class="terminal-993994783-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-993994783-line-0)"> +</text><text class="terminal-993994783-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-993994783-line-1)">usage: cz bump </text><text class="terminal-993994783-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">[</text><text class="terminal-993994783-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-993994783-line-1)">-h</text><text class="terminal-993994783-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">]</text><text class="terminal-993994783-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">[</text><text class="terminal-993994783-r1" x="256.2" y="44.4" textLength="109.8" clip-path="url(#terminal-993994783-line-1)">--dry-run</text><text class="terminal-993994783-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">]</text><text class="terminal-993994783-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">[</text><text class="terminal-993994783-r1" x="402.6" y="44.4" textLength="146.4" clip-path="url(#terminal-993994783-line-1)">--files-only</text><text class="terminal-993994783-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">]</text><text class="terminal-993994783-r2" x="573.4" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">[</text><text class="terminal-993994783-r1" x="585.6" y="44.4" textLength="244" clip-path="url(#terminal-993994783-line-1)">--version-files-only</text><text class="terminal-993994783-r2" x="829.6" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)">]</text><text class="terminal-993994783-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-993994783-line-1)"> +</text><text class="terminal-993994783-r2" x="183" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">[</text><text class="terminal-993994783-r1" x="195.2" y="68.8" textLength="183" clip-path="url(#terminal-993994783-line-2)">--local-version</text><text class="terminal-993994783-r2" x="378.2" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">]</text><text class="terminal-993994783-r2" x="402.6" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">[</text><text class="terminal-993994783-r1" x="414.8" y="68.8" textLength="134.2" clip-path="url(#terminal-993994783-line-2)">--changelog</text><text class="terminal-993994783-r2" x="549" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">]</text><text class="terminal-993994783-r2" x="573.4" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">[</text><text class="terminal-993994783-r1" x="585.6" y="68.8" textLength="134.2" clip-path="url(#terminal-993994783-line-2)">--no-verify</text><text class="terminal-993994783-r2" x="719.8" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">]</text><text class="terminal-993994783-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">[</text><text class="terminal-993994783-r1" x="756.4" y="68.8" textLength="61" clip-path="url(#terminal-993994783-line-2)">--yes</text><text class="terminal-993994783-r2" x="817.4" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)">]</text><text class="terminal-993994783-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-993994783-line-2)"> +</text><text class="terminal-993994783-r2" x="183" y="93.2" textLength="12.2" clip-path="url(#terminal-993994783-line-3)">[</text><text class="terminal-993994783-r1" x="195.2" y="93.2" textLength="280.6" clip-path="url(#terminal-993994783-line-3)">--tag-format TAG_FORMAT</text><text class="terminal-993994783-r2" x="475.8" y="93.2" textLength="12.2" clip-path="url(#terminal-993994783-line-3)">]</text><text class="terminal-993994783-r2" x="500.2" y="93.2" textLength="12.2" clip-path="url(#terminal-993994783-line-3)">[</text><text class="terminal-993994783-r1" x="512.4" y="93.2" textLength="329.4" clip-path="url(#terminal-993994783-line-3)">--bump-message BUMP_MESSAGE</text><text class="terminal-993994783-r2" x="841.8" y="93.2" textLength="12.2" clip-path="url(#terminal-993994783-line-3)">]</text><text class="terminal-993994783-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-993994783-line-3)"> +</text><text class="terminal-993994783-r2" x="183" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)">[</text><text class="terminal-993994783-r1" x="195.2" y="117.6" textLength="158.6" clip-path="url(#terminal-993994783-line-4)">--prerelease </text><text class="terminal-993994783-r2" x="353.8" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)">{</text><text class="terminal-993994783-r1" x="366" y="117.6" textLength="158.6" clip-path="url(#terminal-993994783-line-4)">alpha,beta,rc</text><text class="terminal-993994783-r2" x="524.6" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)">}</text><text class="terminal-993994783-r2" x="536.8" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)">]</text><text class="terminal-993994783-r2" x="561.2" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)">[</text><text class="terminal-993994783-r1" x="573.4" y="117.6" textLength="280.6" clip-path="url(#terminal-993994783-line-4)">--devrelease DEVRELEASE</text><text class="terminal-993994783-r2" x="854" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)">]</text><text class="terminal-993994783-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-993994783-line-4)"> +</text><text class="terminal-993994783-r2" x="183" y="142" textLength="12.2" clip-path="url(#terminal-993994783-line-5)">[</text><text class="terminal-993994783-r1" x="195.2" y="142" textLength="146.4" clip-path="url(#terminal-993994783-line-5)">--increment </text><text class="terminal-993994783-r2" x="341.6" y="142" textLength="12.2" clip-path="url(#terminal-993994783-line-5)">{</text><text class="terminal-993994783-r1" x="353.8" y="142" textLength="207.4" clip-path="url(#terminal-993994783-line-5)">MAJOR,MINOR,PATCH</text><text class="terminal-993994783-r2" x="561.2" y="142" textLength="12.2" clip-path="url(#terminal-993994783-line-5)">}</text><text class="terminal-993994783-r2" x="573.4" y="142" textLength="12.2" clip-path="url(#terminal-993994783-line-5)">]</text><text class="terminal-993994783-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-993994783-line-5)"> +</text><text class="terminal-993994783-r2" x="183" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)">[</text><text class="terminal-993994783-r1" x="195.2" y="166.4" textLength="207.4" clip-path="url(#terminal-993994783-line-6)">--increment-mode </text><text class="terminal-993994783-r2" x="402.6" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)">{</text><text class="terminal-993994783-r1" x="414.8" y="166.4" textLength="146.4" clip-path="url(#terminal-993994783-line-6)">linear,exact</text><text class="terminal-993994783-r2" x="561.2" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)">}</text><text class="terminal-993994783-r2" x="573.4" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)">]</text><text class="terminal-993994783-r2" x="597.8" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)">[</text><text class="terminal-993994783-r1" x="610" y="166.4" textLength="231.8" clip-path="url(#terminal-993994783-line-6)">--check-consistency</text><text class="terminal-993994783-r2" x="841.8" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)">]</text><text class="terminal-993994783-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-993994783-line-6)"> +</text><text class="terminal-993994783-r2" x="183" y="190.8" textLength="12.2" clip-path="url(#terminal-993994783-line-7)">[</text><text class="terminal-993994783-r1" x="195.2" y="190.8" textLength="183" clip-path="url(#terminal-993994783-line-7)">--annotated-tag</text><text class="terminal-993994783-r2" x="378.2" y="190.8" textLength="12.2" clip-path="url(#terminal-993994783-line-7)">]</text><text class="terminal-993994783-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-993994783-line-7)"> +</text><text class="terminal-993994783-r2" x="183" y="215.2" textLength="12.2" clip-path="url(#terminal-993994783-line-8)">[</text><text class="terminal-993994783-r1" x="195.2" y="215.2" textLength="549" clip-path="url(#terminal-993994783-line-8)">--annotated-tag-message ANNOTATED_TAG_MESSAGE</text><text class="terminal-993994783-r2" x="744.2" y="215.2" textLength="12.2" clip-path="url(#terminal-993994783-line-8)">]</text><text class="terminal-993994783-r2" x="768.6" y="215.2" textLength="12.2" clip-path="url(#terminal-993994783-line-8)">[</text><text class="terminal-993994783-r1" x="780.8" y="215.2" textLength="122" clip-path="url(#terminal-993994783-line-8)">--gpg-sign</text><text class="terminal-993994783-r2" x="902.8" y="215.2" textLength="12.2" clip-path="url(#terminal-993994783-line-8)">]</text><text class="terminal-993994783-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-993994783-line-8)"> +</text><text class="terminal-993994783-r2" x="183" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)">[</text><text class="terminal-993994783-r1" x="195.2" y="239.6" textLength="256.2" clip-path="url(#terminal-993994783-line-9)">--changelog-to-stdout</text><text class="terminal-993994783-r2" x="451.4" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)">]</text><text class="terminal-993994783-r2" x="475.8" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)">[</text><text class="terminal-993994783-r1" x="488" y="239.6" textLength="268.4" clip-path="url(#terminal-993994783-line-9)">--git-output-to-stderr</text><text class="terminal-993994783-r2" x="756.4" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)">]</text><text class="terminal-993994783-r2" x="780.8" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)">[</text><text class="terminal-993994783-r1" x="793" y="239.6" textLength="85.4" clip-path="url(#terminal-993994783-line-9)">--retry</text><text class="terminal-993994783-r2" x="878.4" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)">]</text><text class="terminal-993994783-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-993994783-line-9)"> +</text><text class="terminal-993994783-r2" x="183" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)">[</text><text class="terminal-993994783-r1" x="195.2" y="264" textLength="244" clip-path="url(#terminal-993994783-line-10)">--major-version-zero</text><text class="terminal-993994783-r2" x="439.2" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)">]</text><text class="terminal-993994783-r2" x="463.6" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)">[</text><text class="terminal-993994783-r1" x="475.8" y="264" textLength="231.8" clip-path="url(#terminal-993994783-line-10)">--template TEMPLATE</text><text class="terminal-993994783-r2" x="707.6" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)">]</text><text class="terminal-993994783-r2" x="732" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)">[</text><text class="terminal-993994783-r1" x="744.2" y="264" textLength="158.6" clip-path="url(#terminal-993994783-line-10)">--extra EXTRA</text><text class="terminal-993994783-r2" x="902.8" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)">]</text><text class="terminal-993994783-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-993994783-line-10)"> +</text><text class="terminal-993994783-r2" x="183" y="288.4" textLength="12.2" clip-path="url(#terminal-993994783-line-11)">[</text><text class="terminal-993994783-r1" x="195.2" y="288.4" textLength="256.2" clip-path="url(#terminal-993994783-line-11)">--file-name FILE_NAME</text><text class="terminal-993994783-r2" x="451.4" y="288.4" textLength="12.2" clip-path="url(#terminal-993994783-line-11)">]</text><text class="terminal-993994783-r2" x="475.8" y="288.4" textLength="12.2" clip-path="url(#terminal-993994783-line-11)">[</text><text class="terminal-993994783-r1" x="488" y="288.4" textLength="451.4" clip-path="url(#terminal-993994783-line-11)">--prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-993994783-r2" x="939.4" y="288.4" textLength="12.2" clip-path="url(#terminal-993994783-line-11)">]</text><text class="terminal-993994783-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-993994783-line-11)"> +</text><text class="terminal-993994783-r2" x="183" y="312.8" textLength="12.2" clip-path="url(#terminal-993994783-line-12)">[</text><text class="terminal-993994783-r1" x="195.2" y="312.8" textLength="207.4" clip-path="url(#terminal-993994783-line-12)">--version-scheme </text><text class="terminal-993994783-r2" x="402.6" y="312.8" textLength="12.2" clip-path="url(#terminal-993994783-line-12)">{</text><text class="terminal-993994783-r1" x="414.8" y="312.8" textLength="256.2" clip-path="url(#terminal-993994783-line-12)">pep440,semver,semver2</text><text class="terminal-993994783-r2" x="671" y="312.8" textLength="12.2" clip-path="url(#terminal-993994783-line-12)">}</text><text class="terminal-993994783-r2" x="683.2" y="312.8" textLength="12.2" clip-path="url(#terminal-993994783-line-12)">]</text><text class="terminal-993994783-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-993994783-line-12)"> +</text><text class="terminal-993994783-r2" x="183" y="337.2" textLength="12.2" clip-path="url(#terminal-993994783-line-13)">[</text><text class="terminal-993994783-r1" x="195.2" y="337.2" textLength="183" clip-path="url(#terminal-993994783-line-13)">--version-type </text><text class="terminal-993994783-r2" x="378.2" y="337.2" textLength="12.2" clip-path="url(#terminal-993994783-line-13)">{</text><text class="terminal-993994783-r1" x="390.4" y="337.2" textLength="256.2" clip-path="url(#terminal-993994783-line-13)">pep440,semver,semver2</text><text class="terminal-993994783-r2" x="646.6" y="337.2" textLength="12.2" clip-path="url(#terminal-993994783-line-13)">}</text><text class="terminal-993994783-r2" x="658.8" y="337.2" textLength="12.2" clip-path="url(#terminal-993994783-line-13)">]</text><text class="terminal-993994783-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-993994783-line-13)"> +</text><text class="terminal-993994783-r2" x="183" y="361.6" textLength="12.2" clip-path="url(#terminal-993994783-line-14)">[</text><text class="terminal-993994783-r1" x="195.2" y="361.6" textLength="378.2" clip-path="url(#terminal-993994783-line-14)">--build-metadata BUILD_METADATA</text><text class="terminal-993994783-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-993994783-line-14)">]</text><text class="terminal-993994783-r2" x="597.8" y="361.6" textLength="12.2" clip-path="url(#terminal-993994783-line-14)">[</text><text class="terminal-993994783-r1" x="610" y="361.6" textLength="122" clip-path="url(#terminal-993994783-line-14)">--get-next</text><text class="terminal-993994783-r2" x="732" y="361.6" textLength="12.2" clip-path="url(#terminal-993994783-line-14)">]</text><text class="terminal-993994783-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-993994783-line-14)"> +</text><text class="terminal-993994783-r2" x="183" y="386" textLength="12.2" clip-path="url(#terminal-993994783-line-15)">[</text><text class="terminal-993994783-r1" x="195.2" y="386" textLength="207.4" clip-path="url(#terminal-993994783-line-15)">--allow-no-commit</text><text class="terminal-993994783-r2" x="402.6" y="386" textLength="12.2" clip-path="url(#terminal-993994783-line-15)">]</text><text class="terminal-993994783-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-993994783-line-15)"> +</text><text class="terminal-993994783-r2" x="183" y="410.4" textLength="12.2" clip-path="url(#terminal-993994783-line-16)">[</text><text class="terminal-993994783-r1" x="195.2" y="410.4" textLength="170.8" clip-path="url(#terminal-993994783-line-16)">MANUAL_VERSION</text><text class="terminal-993994783-r2" x="366" y="410.4" textLength="12.2" clip-path="url(#terminal-993994783-line-16)">]</text><text class="terminal-993994783-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-993994783-line-16)"> +</text><text class="terminal-993994783-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-993994783-line-17)"> +</text><text class="terminal-993994783-r1" x="0" y="459.2" textLength="512.4" clip-path="url(#terminal-993994783-line-18)">Bump semantic version based on the git log</text><text class="terminal-993994783-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-993994783-line-18)"> +</text><text class="terminal-993994783-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-993994783-line-19)"> +</text><text class="terminal-993994783-r1" x="0" y="508" textLength="256.2" clip-path="url(#terminal-993994783-line-20)">positional arguments:</text><text class="terminal-993994783-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-993994783-line-20)"> +</text><text class="terminal-993994783-r1" x="0" y="532.4" textLength="610" clip-path="url(#terminal-993994783-line-21)">  MANUAL_VERSION        Bump to the given version </text><text class="terminal-993994783-r2" x="610" y="532.4" textLength="12.2" clip-path="url(#terminal-993994783-line-21)">(</text><text class="terminal-993994783-r1" x="622.2" y="532.4" textLength="73.2" clip-path="url(#terminal-993994783-line-21)">e.g., </text><text class="terminal-993994783-r3" x="695.4" y="532.4" textLength="36.6" clip-path="url(#terminal-993994783-line-21)">1.5</text><text class="terminal-993994783-r1" x="732" y="532.4" textLength="12.2" clip-path="url(#terminal-993994783-line-21)">.</text><text class="terminal-993994783-r3" x="744.2" y="532.4" textLength="12.2" clip-path="url(#terminal-993994783-line-21)">3</text><text class="terminal-993994783-r2" x="756.4" y="532.4" textLength="12.2" clip-path="url(#terminal-993994783-line-21)">)</text><text class="terminal-993994783-r1" x="768.6" y="532.4" textLength="12.2" clip-path="url(#terminal-993994783-line-21)">.</text><text class="terminal-993994783-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-993994783-line-21)"> +</text><text class="terminal-993994783-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-993994783-line-22)"> +</text><text class="terminal-993994783-r1" x="0" y="581.2" textLength="97.6" clip-path="url(#terminal-993994783-line-23)">options:</text><text class="terminal-993994783-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-993994783-line-23)"> +</text><text class="terminal-993994783-r1" x="0" y="605.6" textLength="671" clip-path="url(#terminal-993994783-line-24)">  -h, --help            show this help message and exit</text><text class="terminal-993994783-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-993994783-line-24)"> +</text><text class="terminal-993994783-r1" x="0" y="630" textLength="902.8" clip-path="url(#terminal-993994783-line-25)">  --dry-run             Perform a dry run, without committing or modifying</text><text class="terminal-993994783-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-993994783-line-25)"> +</text><text class="terminal-993994783-r1" x="0" y="654.4" textLength="366" clip-path="url(#terminal-993994783-line-26)">                        files.</text><text class="terminal-993994783-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-993994783-line-26)"> +</text><text class="terminal-993994783-r1" x="0" y="678.8" textLength="927.2" clip-path="url(#terminal-993994783-line-27)">  --files-only          Bump version in the `version_files` specified in the</text><text class="terminal-993994783-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-993994783-line-27)"> +</text><text class="terminal-993994783-r1" x="0" y="703.2" textLength="524.6" clip-path="url(#terminal-993994783-line-28)">                        configuration file </text><text class="terminal-993994783-r4" x="524.6" y="703.2" textLength="48.8" clip-path="url(#terminal-993994783-line-28)">only</text><text class="terminal-993994783-r2" x="573.4" y="703.2" textLength="12.2" clip-path="url(#terminal-993994783-line-28)">(</text><text class="terminal-993994783-r1" x="585.6" y="703.2" textLength="317.2" clip-path="url(#terminal-993994783-line-28)">deprecated; use --version-</text><text class="terminal-993994783-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-993994783-line-28)"> +</text><text class="terminal-993994783-r1" x="0" y="727.6" textLength="512.4" clip-path="url(#terminal-993994783-line-29)">                        files-only instead</text><text class="terminal-993994783-r2" x="512.4" y="727.6" textLength="12.2" clip-path="url(#terminal-993994783-line-29)">)</text><text class="terminal-993994783-r1" x="524.6" y="727.6" textLength="12.2" clip-path="url(#terminal-993994783-line-29)">.</text><text class="terminal-993994783-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-993994783-line-29)"> +</text><text class="terminal-993994783-r1" x="0" y="752" textLength="793" clip-path="url(#terminal-993994783-line-30)">  --version-files-only  Bump version in the files from the config</text><text class="terminal-993994783-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-993994783-line-30)"> +</text><text class="terminal-993994783-r1" x="0" y="776.4" textLength="829.6" clip-path="url(#terminal-993994783-line-31)">  --local-version       Bump version only the local version portion </text><text class="terminal-993994783-r2" x="829.6" y="776.4" textLength="12.2" clip-path="url(#terminal-993994783-line-31)">(</text><text class="terminal-993994783-r1" x="841.8" y="776.4" textLength="97.6" clip-path="url(#terminal-993994783-line-31)">ignoring</text><text class="terminal-993994783-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-993994783-line-31)"> +</text><text class="terminal-993994783-r1" x="0" y="800.8" textLength="512.4" clip-path="url(#terminal-993994783-line-32)">                        the public version</text><text class="terminal-993994783-r2" x="512.4" y="800.8" textLength="12.2" clip-path="url(#terminal-993994783-line-32)">)</text><text class="terminal-993994783-r1" x="524.6" y="800.8" textLength="12.2" clip-path="url(#terminal-993994783-line-32)">.</text><text class="terminal-993994783-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-993994783-line-32)"> +</text><text class="terminal-993994783-r1" x="0" y="825.2" textLength="854" clip-path="url(#terminal-993994783-line-33)">  --changelog, -ch      Generate the changelog for the latest version.</text><text class="terminal-993994783-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-993994783-line-33)"> +</text><text class="terminal-993994783-r1" x="0" y="849.6" textLength="817.4" clip-path="url(#terminal-993994783-line-34)">  --no-verify           Bypass the pre-commit and commit-msg hooks.</text><text class="terminal-993994783-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-993994783-line-34)"> +</text><text class="terminal-993994783-r1" x="0" y="874" textLength="780.8" clip-path="url(#terminal-993994783-line-35)">  --yes                 Accept automatically answered questions.</text><text class="terminal-993994783-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-993994783-line-35)"> +</text><text class="terminal-993994783-r1" x="0" y="898.4" textLength="305" clip-path="url(#terminal-993994783-line-36)">  --tag-format TAG_FORMAT</text><text class="terminal-993994783-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-993994783-line-36)"> +</text><text class="terminal-993994783-r1" x="0" y="922.8" textLength="939.4" clip-path="url(#terminal-993994783-line-37)">                        The format used to tag the commit and read it. Use it</text><text class="terminal-993994783-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-993994783-line-37)"> +</text><text class="terminal-993994783-r1" x="0" y="947.2" textLength="927.2" clip-path="url(#terminal-993994783-line-38)">                        in existing projects, and wrap around simple quotes.</text><text class="terminal-993994783-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-993994783-line-38)"> +</text><text class="terminal-993994783-r1" x="0" y="971.6" textLength="353.8" clip-path="url(#terminal-993994783-line-39)">  --bump-message BUMP_MESSAGE</text><text class="terminal-993994783-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-993994783-line-39)"> +</text><text class="terminal-993994783-r1" x="0" y="996" textLength="902.8" clip-path="url(#terminal-993994783-line-40)">                        Template used to create the release commit, useful</text><text class="terminal-993994783-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-993994783-line-40)"> +</text><text class="terminal-993994783-r1" x="0" y="1020.4" textLength="549" clip-path="url(#terminal-993994783-line-41)">                        when working with CI.</text><text class="terminal-993994783-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-993994783-line-41)"> +</text><text class="terminal-993994783-r1" x="0" y="1044.8" textLength="183" clip-path="url(#terminal-993994783-line-42)">  --prerelease </text><text class="terminal-993994783-r2" x="183" y="1044.8" textLength="12.2" clip-path="url(#terminal-993994783-line-42)">{</text><text class="terminal-993994783-r1" x="195.2" y="1044.8" textLength="158.6" clip-path="url(#terminal-993994783-line-42)">alpha,beta,rc</text><text class="terminal-993994783-r2" x="353.8" y="1044.8" textLength="12.2" clip-path="url(#terminal-993994783-line-42)">}</text><text class="terminal-993994783-r1" x="366" y="1044.8" textLength="73.2" clip-path="url(#terminal-993994783-line-42)">, -pr </text><text class="terminal-993994783-r2" x="439.2" y="1044.8" textLength="12.2" clip-path="url(#terminal-993994783-line-42)">{</text><text class="terminal-993994783-r1" x="451.4" y="1044.8" textLength="158.6" clip-path="url(#terminal-993994783-line-42)">alpha,beta,rc</text><text class="terminal-993994783-r2" x="610" y="1044.8" textLength="12.2" clip-path="url(#terminal-993994783-line-42)">}</text><text class="terminal-993994783-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-993994783-line-42)"> +</text><text class="terminal-993994783-r1" x="0" y="1069.2" textLength="524.6" clip-path="url(#terminal-993994783-line-43)">                        Type of prerelease.</text><text class="terminal-993994783-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-993994783-line-43)"> +</text><text class="terminal-993994783-r1" x="0" y="1093.6" textLength="488" clip-path="url(#terminal-993994783-line-44)">  --devrelease DEVRELEASE, -d DEVRELEASE</text><text class="terminal-993994783-r1" x="976" y="1093.6" textLength="12.2" clip-path="url(#terminal-993994783-line-44)"> +</text><text class="terminal-993994783-r1" x="0" y="1118" textLength="841.8" clip-path="url(#terminal-993994783-line-45)">                        Specify non-negative integer for dev release.</text><text class="terminal-993994783-r1" x="976" y="1118" textLength="12.2" clip-path="url(#terminal-993994783-line-45)"> +</text><text class="terminal-993994783-r1" x="0" y="1142.4" textLength="170.8" clip-path="url(#terminal-993994783-line-46)">  --increment </text><text class="terminal-993994783-r2" x="170.8" y="1142.4" textLength="12.2" clip-path="url(#terminal-993994783-line-46)">{</text><text class="terminal-993994783-r1" x="183" y="1142.4" textLength="207.4" clip-path="url(#terminal-993994783-line-46)">MAJOR,MINOR,PATCH</text><text class="terminal-993994783-r2" x="390.4" y="1142.4" textLength="12.2" clip-path="url(#terminal-993994783-line-46)">}</text><text class="terminal-993994783-r1" x="976" y="1142.4" textLength="12.2" clip-path="url(#terminal-993994783-line-46)"> +</text><text class="terminal-993994783-r1" x="0" y="1166.8" textLength="658.8" clip-path="url(#terminal-993994783-line-47)">                        Specify the desired increment.</text><text class="terminal-993994783-r1" x="976" y="1166.8" textLength="12.2" clip-path="url(#terminal-993994783-line-47)"> +</text><text class="terminal-993994783-r1" x="0" y="1191.2" textLength="231.8" clip-path="url(#terminal-993994783-line-48)">  --increment-mode </text><text class="terminal-993994783-r2" x="231.8" y="1191.2" textLength="12.2" clip-path="url(#terminal-993994783-line-48)">{</text><text class="terminal-993994783-r1" x="244" y="1191.2" textLength="146.4" clip-path="url(#terminal-993994783-line-48)">linear,exact</text><text class="terminal-993994783-r2" x="390.4" y="1191.2" textLength="12.2" clip-path="url(#terminal-993994783-line-48)">}</text><text class="terminal-993994783-r1" x="976" y="1191.2" textLength="12.2" clip-path="url(#terminal-993994783-line-48)"> +</text><text class="terminal-993994783-r1" x="0" y="1215.6" textLength="902.8" clip-path="url(#terminal-993994783-line-49)">                        Set the method by which the new version is chosen.</text><text class="terminal-993994783-r1" x="976" y="1215.6" textLength="12.2" clip-path="url(#terminal-993994783-line-49)"> +</text><text class="terminal-993994783-r5" x="292.8" y="1240" textLength="97.6" clip-path="url(#terminal-993994783-line-50)">'linear'</text><text class="terminal-993994783-r2" x="402.6" y="1240" textLength="12.2" clip-path="url(#terminal-993994783-line-50)">(</text><text class="terminal-993994783-r1" x="414.8" y="1240" textLength="85.4" clip-path="url(#terminal-993994783-line-50)">default</text><text class="terminal-993994783-r2" x="500.2" y="1240" textLength="12.2" clip-path="url(#terminal-993994783-line-50)">)</text><text class="terminal-993994783-r1" x="512.4" y="1240" textLength="427" clip-path="url(#terminal-993994783-line-50)"> resolves the next version based on</text><text class="terminal-993994783-r1" x="976" y="1240" textLength="12.2" clip-path="url(#terminal-993994783-line-50)"> +</text><text class="terminal-993994783-r1" x="0" y="1264.4" textLength="951.6" clip-path="url(#terminal-993994783-line-51)">                        typical linear version progression, where bumping of a</text><text class="terminal-993994783-r1" x="976" y="1264.4" textLength="12.2" clip-path="url(#terminal-993994783-line-51)"> +</text><text class="terminal-993994783-r1" x="0" y="1288.8" textLength="902.8" clip-path="url(#terminal-993994783-line-52)">                        pre-release with lower precedence than the current</text><text class="terminal-993994783-r1" x="976" y="1288.8" textLength="12.2" clip-path="url(#terminal-993994783-line-52)"> +</text><text class="terminal-993994783-r1" x="0" y="1313.2" textLength="878.4" clip-path="url(#terminal-993994783-line-53)">                        pre-release phase maintains the current phase of</text><text class="terminal-993994783-r1" x="976" y="1313.2" textLength="12.2" clip-path="url(#terminal-993994783-line-53)"> +</text><text class="terminal-993994783-r1" x="0" y="1337.6" textLength="524.6" clip-path="url(#terminal-993994783-line-54)">                        higher precedence. </text><text class="terminal-993994783-r5" x="524.6" y="1337.6" textLength="85.4" clip-path="url(#terminal-993994783-line-54)">'exact'</text><text class="terminal-993994783-r1" x="610" y="1337.6" textLength="305" clip-path="url(#terminal-993994783-line-54)"> applies the changes that</text><text class="terminal-993994783-r1" x="976" y="1337.6" textLength="12.2" clip-path="url(#terminal-993994783-line-54)"> +</text><text class="terminal-993994783-r1" x="0" y="1362" textLength="536.8" clip-path="url(#terminal-993994783-line-55)">                        have been specified </text><text class="terminal-993994783-r2" x="536.8" y="1362" textLength="12.2" clip-path="url(#terminal-993994783-line-55)">(</text><text class="terminal-993994783-r1" x="549" y="1362" textLength="353.8" clip-path="url(#terminal-993994783-line-55)">or determined from the commit</text><text class="terminal-993994783-r1" x="976" y="1362" textLength="12.2" clip-path="url(#terminal-993994783-line-55)"> +</text><text class="terminal-993994783-r1" x="0" y="1386.4" textLength="329.4" clip-path="url(#terminal-993994783-line-56)">                        log</text><text class="terminal-993994783-r2" x="329.4" y="1386.4" textLength="12.2" clip-path="url(#terminal-993994783-line-56)">)</text><text class="terminal-993994783-r1" x="341.6" y="1386.4" textLength="573.4" clip-path="url(#terminal-993994783-line-56)"> without interpretation, ensuring the increment</text><text class="terminal-993994783-r1" x="976" y="1386.4" textLength="12.2" clip-path="url(#terminal-993994783-line-56)"> +</text><text class="terminal-993994783-r1" x="0" y="1410.8" textLength="719.8" clip-path="url(#terminal-993994783-line-57)">                        and pre-release are always honored.</text><text class="terminal-993994783-r1" x="976" y="1410.8" textLength="12.2" clip-path="url(#terminal-993994783-line-57)"> +</text><text class="terminal-993994783-r1" x="0" y="1435.2" textLength="317.2" clip-path="url(#terminal-993994783-line-58)">  --check-consistency, -cc</text><text class="terminal-993994783-r1" x="976" y="1435.2" textLength="12.2" clip-path="url(#terminal-993994783-line-58)"> +</text><text class="terminal-993994783-r1" x="0" y="1459.6" textLength="951.6" clip-path="url(#terminal-993994783-line-59)">                        Check consistency among versions defined in Commitizen</text><text class="terminal-993994783-r1" x="976" y="1459.6" textLength="12.2" clip-path="url(#terminal-993994783-line-59)"> +</text><text class="terminal-993994783-r1" x="0" y="1484" textLength="768.6" clip-path="url(#terminal-993994783-line-60)">                        configuration file and `version_files`.</text><text class="terminal-993994783-r1" x="976" y="1484" textLength="12.2" clip-path="url(#terminal-993994783-line-60)"> +</text><text class="terminal-993994783-r1" x="0" y="1508.4" textLength="878.4" clip-path="url(#terminal-993994783-line-61)">  --annotated-tag, -at  Create annotated tag instead of lightweight one.</text><text class="terminal-993994783-r1" x="976" y="1508.4" textLength="12.2" clip-path="url(#terminal-993994783-line-61)"> +</text><text class="terminal-993994783-r1" x="0" y="1532.8" textLength="915" clip-path="url(#terminal-993994783-line-62)">  --annotated-tag-message ANNOTATED_TAG_MESSAGE, -atm ANNOTATED_TAG_MESSAGE</text><text class="terminal-993994783-r1" x="976" y="1532.8" textLength="12.2" clip-path="url(#terminal-993994783-line-62)"> +</text><text class="terminal-993994783-r1" x="0" y="1557.2" textLength="646.6" clip-path="url(#terminal-993994783-line-63)">                        Create annotated tag message.</text><text class="terminal-993994783-r1" x="976" y="1557.2" textLength="12.2" clip-path="url(#terminal-993994783-line-63)"> +</text><text class="terminal-993994783-r1" x="0" y="1581.6" textLength="732" clip-path="url(#terminal-993994783-line-64)">  --gpg-sign, -s        Sign tag instead of lightweight one.</text><text class="terminal-993994783-r1" x="976" y="1581.6" textLength="12.2" clip-path="url(#terminal-993994783-line-64)"> +</text><text class="terminal-993994783-r1" x="0" y="1606" textLength="280.6" clip-path="url(#terminal-993994783-line-65)">  --changelog-to-stdout</text><text class="terminal-993994783-r1" x="976" y="1606" textLength="12.2" clip-path="url(#terminal-993994783-line-65)"> +</text><text class="terminal-993994783-r1" x="0" y="1630.4" textLength="622.2" clip-path="url(#terminal-993994783-line-66)">                        Output changelog to stdout.</text><text class="terminal-993994783-r1" x="976" y="1630.4" textLength="12.2" clip-path="url(#terminal-993994783-line-66)"> +</text><text class="terminal-993994783-r1" x="0" y="1654.8" textLength="292.8" clip-path="url(#terminal-993994783-line-67)">  --git-output-to-stderr</text><text class="terminal-993994783-r1" x="976" y="1654.8" textLength="12.2" clip-path="url(#terminal-993994783-line-67)"> +</text><text class="terminal-993994783-r1" x="0" y="1679.2" textLength="658.8" clip-path="url(#terminal-993994783-line-68)">                        Redirect git output to stderr.</text><text class="terminal-993994783-r1" x="976" y="1679.2" textLength="12.2" clip-path="url(#terminal-993994783-line-68)"> +</text><text class="terminal-993994783-r1" x="0" y="1703.6" textLength="829.6" clip-path="url(#terminal-993994783-line-69)">  --retry               Retry commit if it fails for the first time.</text><text class="terminal-993994783-r1" x="976" y="1703.6" textLength="12.2" clip-path="url(#terminal-993994783-line-69)"> +</text><text class="terminal-993994783-r1" x="0" y="1728" textLength="951.6" clip-path="url(#terminal-993994783-line-70)">  --major-version-zero  Keep major version at zero, even for breaking changes.</text><text class="terminal-993994783-r1" x="976" y="1728" textLength="12.2" clip-path="url(#terminal-993994783-line-70)"> +</text><text class="terminal-993994783-r1" x="0" y="1752.4" textLength="414.8" clip-path="url(#terminal-993994783-line-71)">  --template TEMPLATE, -t TEMPLATE</text><text class="terminal-993994783-r1" x="976" y="1752.4" textLength="12.2" clip-path="url(#terminal-993994783-line-71)"> +</text><text class="terminal-993994783-r1" x="0" y="1776.8" textLength="646.6" clip-path="url(#terminal-993994783-line-72)">                        Changelog template file name </text><text class="terminal-993994783-r2" x="646.6" y="1776.8" textLength="12.2" clip-path="url(#terminal-993994783-line-72)">(</text><text class="terminal-993994783-r1" x="658.8" y="1776.8" textLength="280.6" clip-path="url(#terminal-993994783-line-72)">relative to the current</text><text class="terminal-993994783-r1" x="976" y="1776.8" textLength="12.2" clip-path="url(#terminal-993994783-line-72)"> +</text><text class="terminal-993994783-r1" x="0" y="1801.2" textLength="500.2" clip-path="url(#terminal-993994783-line-73)">                        working directory</text><text class="terminal-993994783-r2" x="500.2" y="1801.2" textLength="12.2" clip-path="url(#terminal-993994783-line-73)">)</text><text class="terminal-993994783-r1" x="512.4" y="1801.2" textLength="12.2" clip-path="url(#terminal-993994783-line-73)">.</text><text class="terminal-993994783-r1" x="976" y="1801.2" textLength="12.2" clip-path="url(#terminal-993994783-line-73)"> +</text><text class="terminal-993994783-r1" x="0" y="1825.6" textLength="305" clip-path="url(#terminal-993994783-line-74)">  --extra EXTRA, -e EXTRA</text><text class="terminal-993994783-r1" x="976" y="1825.6" textLength="12.2" clip-path="url(#terminal-993994783-line-74)"> +</text><text class="terminal-993994783-r1" x="0" y="1850" textLength="610" clip-path="url(#terminal-993994783-line-75)">                        Changelog extra variables </text><text class="terminal-993994783-r2" x="610" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)">(</text><text class="terminal-993994783-r1" x="622.2" y="1850" textLength="146.4" clip-path="url(#terminal-993994783-line-75)">in the form </text><text class="terminal-993994783-r5" x="768.6" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)">'</text><text class="terminal-993994783-r5" x="780.8" y="1850" textLength="36.6" clip-path="url(#terminal-993994783-line-75)">key</text><text class="terminal-993994783-r5" x="817.4" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)">=</text><text class="terminal-993994783-r5" x="829.6" y="1850" textLength="61" clip-path="url(#terminal-993994783-line-75)">value</text><text class="terminal-993994783-r5" x="890.6" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)">'</text><text class="terminal-993994783-r2" x="902.8" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)">)</text><text class="terminal-993994783-r1" x="915" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)">.</text><text class="terminal-993994783-r1" x="976" y="1850" textLength="12.2" clip-path="url(#terminal-993994783-line-75)"> +</text><text class="terminal-993994783-r1" x="0" y="1874.4" textLength="280.6" clip-path="url(#terminal-993994783-line-76)">  --file-name FILE_NAME</text><text class="terminal-993994783-r1" x="976" y="1874.4" textLength="12.2" clip-path="url(#terminal-993994783-line-76)"> +</text><text class="terminal-993994783-r1" x="0" y="1898.8" textLength="573.4" clip-path="url(#terminal-993994783-line-77)">                        File name of changelog </text><text class="terminal-993994783-r2" x="573.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-993994783-line-77)">(</text><text class="terminal-993994783-r1" x="585.6" y="1898.8" textLength="109.8" clip-path="url(#terminal-993994783-line-77)">default: </text><text class="terminal-993994783-r5" x="695.4" y="1898.8" textLength="170.8" clip-path="url(#terminal-993994783-line-77)">'CHANGELOG.md'</text><text class="terminal-993994783-r2" x="866.2" y="1898.8" textLength="12.2" clip-path="url(#terminal-993994783-line-77)">)</text><text class="terminal-993994783-r1" x="878.4" y="1898.8" textLength="12.2" clip-path="url(#terminal-993994783-line-77)">.</text><text class="terminal-993994783-r1" x="976" y="1898.8" textLength="12.2" clip-path="url(#terminal-993994783-line-77)"> +</text><text class="terminal-993994783-r1" x="0" y="1923.2" textLength="475.8" clip-path="url(#terminal-993994783-line-78)">  --prerelease-offset PRERELEASE_OFFSET</text><text class="terminal-993994783-r1" x="976" y="1923.2" textLength="12.2" clip-path="url(#terminal-993994783-line-78)"> +</text><text class="terminal-993994783-r1" x="0" y="1947.6" textLength="732" clip-path="url(#terminal-993994783-line-79)">                        Start pre-releases with this offset.</text><text class="terminal-993994783-r1" x="976" y="1947.6" textLength="12.2" clip-path="url(#terminal-993994783-line-79)"> +</text><text class="terminal-993994783-r1" x="0" y="1972" textLength="231.8" clip-path="url(#terminal-993994783-line-80)">  --version-scheme </text><text class="terminal-993994783-r2" x="231.8" y="1972" textLength="12.2" clip-path="url(#terminal-993994783-line-80)">{</text><text class="terminal-993994783-r1" x="244" y="1972" textLength="256.2" clip-path="url(#terminal-993994783-line-80)">pep440,semver,semver2</text><text class="terminal-993994783-r2" x="500.2" y="1972" textLength="12.2" clip-path="url(#terminal-993994783-line-80)">}</text><text class="terminal-993994783-r1" x="976" y="1972" textLength="12.2" clip-path="url(#terminal-993994783-line-80)"> +</text><text class="terminal-993994783-r1" x="0" y="1996.4" textLength="561.2" clip-path="url(#terminal-993994783-line-81)">                        Choose version scheme.</text><text class="terminal-993994783-r1" x="976" y="1996.4" textLength="12.2" clip-path="url(#terminal-993994783-line-81)"> +</text><text class="terminal-993994783-r1" x="0" y="2020.8" textLength="207.4" clip-path="url(#terminal-993994783-line-82)">  --version-type </text><text class="terminal-993994783-r2" x="207.4" y="2020.8" textLength="12.2" clip-path="url(#terminal-993994783-line-82)">{</text><text class="terminal-993994783-r1" x="219.6" y="2020.8" textLength="256.2" clip-path="url(#terminal-993994783-line-82)">pep440,semver,semver2</text><text class="terminal-993994783-r2" x="475.8" y="2020.8" textLength="12.2" clip-path="url(#terminal-993994783-line-82)">}</text><text class="terminal-993994783-r1" x="976" y="2020.8" textLength="12.2" clip-path="url(#terminal-993994783-line-82)"> +</text><text class="terminal-993994783-r1" x="0" y="2045.2" textLength="817.4" clip-path="url(#terminal-993994783-line-83)">                        Deprecated, use `--version-scheme` instead.</text><text class="terminal-993994783-r1" x="976" y="2045.2" textLength="12.2" clip-path="url(#terminal-993994783-line-83)"> +</text><text class="terminal-993994783-r1" x="0" y="2069.6" textLength="402.6" clip-path="url(#terminal-993994783-line-84)">  --build-metadata BUILD_METADATA</text><text class="terminal-993994783-r1" x="976" y="2069.6" textLength="12.2" clip-path="url(#terminal-993994783-line-84)"> +</text><text class="terminal-993994783-r1" x="0" y="2094" textLength="927.2" clip-path="url(#terminal-993994783-line-85)">                        Add additional build-metadata to the version-number.</text><text class="terminal-993994783-r1" x="976" y="2094" textLength="12.2" clip-path="url(#terminal-993994783-line-85)"> +</text><text class="terminal-993994783-r1" x="0" y="2118.4" textLength="866.2" clip-path="url(#terminal-993994783-line-86)">  --get-next            Determine the next version and write to stdout.</text><text class="terminal-993994783-r1" x="976" y="2118.4" textLength="12.2" clip-path="url(#terminal-993994783-line-86)"> +</text><text class="terminal-993994783-r1" x="0" y="2142.8" textLength="756.4" clip-path="url(#terminal-993994783-line-87)">  --allow-no-commit     Bump version without eligible commits.</text><text class="terminal-993994783-r1" x="976" y="2142.8" textLength="12.2" clip-path="url(#terminal-993994783-line-87)"> +</text><text class="terminal-993994783-r1" x="976" y="2167.2" textLength="12.2" clip-path="url(#terminal-993994783-line-88)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_changelog___help.svg b/docs/images/cli_help/cz_changelog___help.svg index 1d98c05b38..b0d048caed 100644 --- a/docs/images/cli_help/cz_changelog___help.svg +++ b/docs/images/cli_help/cz_changelog___help.svg @@ -19,156 +19,156 @@ font-weight: 700; } - .terminal-192800993-matrix { + .terminal-922159541-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-192800993-title { + .terminal-922159541-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-192800993-r1 { fill: #c5c8c6 } -.terminal-192800993-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-192800993-r3 { fill: #68a0b3;font-weight: bold } -.terminal-192800993-r4 { fill: #98a84b } + .terminal-922159541-r1 { fill: #c5c8c6 } +.terminal-922159541-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-922159541-r3 { fill: #68a0b3;font-weight: bold } +.terminal-922159541-r4 { fill: #98a84b } </style> <defs> - <clipPath id="terminal-192800993-clip-terminal"> + <clipPath id="terminal-922159541-clip-terminal"> <rect x="0" y="0" width="975.0" height="1072.6" /> </clipPath> - <clipPath id="terminal-192800993-line-0"> + <clipPath id="terminal-922159541-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-1"> +<clipPath id="terminal-922159541-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-2"> +<clipPath id="terminal-922159541-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-3"> +<clipPath id="terminal-922159541-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-4"> +<clipPath id="terminal-922159541-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-5"> +<clipPath id="terminal-922159541-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-6"> +<clipPath id="terminal-922159541-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-7"> +<clipPath id="terminal-922159541-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-8"> +<clipPath id="terminal-922159541-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-9"> +<clipPath id="terminal-922159541-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-10"> +<clipPath id="terminal-922159541-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-11"> +<clipPath id="terminal-922159541-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-12"> +<clipPath id="terminal-922159541-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-13"> +<clipPath id="terminal-922159541-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-14"> +<clipPath id="terminal-922159541-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-15"> +<clipPath id="terminal-922159541-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-16"> +<clipPath id="terminal-922159541-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-17"> +<clipPath id="terminal-922159541-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-18"> +<clipPath id="terminal-922159541-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-19"> +<clipPath id="terminal-922159541-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-20"> +<clipPath id="terminal-922159541-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-21"> +<clipPath id="terminal-922159541-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-22"> +<clipPath id="terminal-922159541-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-23"> +<clipPath id="terminal-922159541-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-24"> +<clipPath id="terminal-922159541-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-25"> +<clipPath id="terminal-922159541-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-26"> +<clipPath id="terminal-922159541-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-27"> +<clipPath id="terminal-922159541-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-28"> +<clipPath id="terminal-922159541-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-29"> +<clipPath id="terminal-922159541-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-30"> +<clipPath id="terminal-922159541-line-30"> <rect x="0" y="733.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-31"> +<clipPath id="terminal-922159541-line-31"> <rect x="0" y="757.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-32"> +<clipPath id="terminal-922159541-line-32"> <rect x="0" y="782.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-33"> +<clipPath id="terminal-922159541-line-33"> <rect x="0" y="806.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-34"> +<clipPath id="terminal-922159541-line-34"> <rect x="0" y="831.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-35"> +<clipPath id="terminal-922159541-line-35"> <rect x="0" y="855.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-36"> +<clipPath id="terminal-922159541-line-36"> <rect x="0" y="879.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-37"> +<clipPath id="terminal-922159541-line-37"> <rect x="0" y="904.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-38"> +<clipPath id="terminal-922159541-line-38"> <rect x="0" y="928.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-39"> +<clipPath id="terminal-922159541-line-39"> <rect x="0" y="953.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-40"> +<clipPath id="terminal-922159541-line-40"> <rect x="0" y="977.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-41"> +<clipPath id="terminal-922159541-line-41"> <rect x="0" y="1001.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-192800993-line-42"> +<clipPath id="terminal-922159541-line-42"> <rect x="0" y="1026.3" width="976" height="24.65"/> </clipPath> </defs> @@ -180,53 +180,53 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-192800993-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-922159541-clip-terminal)"> - <g class="terminal-192800993-matrix"> - <text class="terminal-192800993-r1" x="0" y="20" textLength="256.2" clip-path="url(#terminal-192800993-line-0)">$ cz changelog --help</text><text class="terminal-192800993-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-192800993-line-0)"> -</text><text class="terminal-192800993-r1" x="0" y="44.4" textLength="244" clip-path="url(#terminal-192800993-line-1)">usage: cz changelog </text><text class="terminal-192800993-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">[</text><text class="terminal-192800993-r1" x="256.2" y="44.4" textLength="24.4" clip-path="url(#terminal-192800993-line-1)">-h</text><text class="terminal-192800993-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">]</text><text class="terminal-192800993-r2" x="305" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">[</text><text class="terminal-192800993-r1" x="317.2" y="44.4" textLength="109.8" clip-path="url(#terminal-192800993-line-1)">--dry-run</text><text class="terminal-192800993-r2" x="427" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">]</text><text class="terminal-192800993-r2" x="451.4" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">[</text><text class="terminal-192800993-r1" x="463.6" y="44.4" textLength="256.2" clip-path="url(#terminal-192800993-line-1)">--file-name FILE_NAME</text><text class="terminal-192800993-r2" x="719.8" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)">]</text><text class="terminal-192800993-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-192800993-line-1)"> -</text><text class="terminal-192800993-r2" x="244" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">[</text><text class="terminal-192800993-r1" x="256.2" y="68.8" textLength="475.8" clip-path="url(#terminal-192800993-line-2)">--unreleased-version UNRELEASED_VERSION</text><text class="terminal-192800993-r2" x="732" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">]</text><text class="terminal-192800993-r2" x="756.4" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">[</text><text class="terminal-192800993-r1" x="768.6" y="68.8" textLength="158.6" clip-path="url(#terminal-192800993-line-2)">--incremental</text><text class="terminal-192800993-r2" x="927.2" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)">]</text><text class="terminal-192800993-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-192800993-line-2)"> -</text><text class="terminal-192800993-r2" x="244" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">[</text><text class="terminal-192800993-r1" x="256.2" y="93.2" textLength="256.2" clip-path="url(#terminal-192800993-line-3)">--start-rev START_REV</text><text class="terminal-192800993-r2" x="512.4" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">]</text><text class="terminal-192800993-r2" x="536.8" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">[</text><text class="terminal-192800993-r1" x="549" y="93.2" textLength="219.6" clip-path="url(#terminal-192800993-line-3)">--merge-prerelease</text><text class="terminal-192800993-r2" x="768.6" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)">]</text><text class="terminal-192800993-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-192800993-line-3)"> -</text><text class="terminal-192800993-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">[</text><text class="terminal-192800993-r1" x="256.2" y="117.6" textLength="207.4" clip-path="url(#terminal-192800993-line-4)">--version-scheme </text><text class="terminal-192800993-r2" x="463.6" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">{</text><text class="terminal-192800993-r1" x="475.8" y="117.6" textLength="256.2" clip-path="url(#terminal-192800993-line-4)">pep440,semver,semver2</text><text class="terminal-192800993-r2" x="732" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">}</text><text class="terminal-192800993-r2" x="744.2" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)">]</text><text class="terminal-192800993-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-192800993-line-4)"> -</text><text class="terminal-192800993-r2" x="244" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">[</text><text class="terminal-192800993-r1" x="256.2" y="142" textLength="402.6" clip-path="url(#terminal-192800993-line-5)">--export-template EXPORT_TEMPLATE</text><text class="terminal-192800993-r2" x="658.8" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">]</text><text class="terminal-192800993-r2" x="683.2" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">[</text><text class="terminal-192800993-r1" x="695.4" y="142" textLength="231.8" clip-path="url(#terminal-192800993-line-5)">--template TEMPLATE</text><text class="terminal-192800993-r2" x="927.2" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)">]</text><text class="terminal-192800993-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-192800993-line-5)"> -</text><text class="terminal-192800993-r2" x="244" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">[</text><text class="terminal-192800993-r1" x="256.2" y="166.4" textLength="158.6" clip-path="url(#terminal-192800993-line-6)">--extra EXTRA</text><text class="terminal-192800993-r2" x="414.8" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">]</text><text class="terminal-192800993-r2" x="439.2" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">[</text><text class="terminal-192800993-r1" x="451.4" y="166.4" textLength="280.6" clip-path="url(#terminal-192800993-line-6)">--tag-format TAG_FORMAT</text><text class="terminal-192800993-r2" x="732" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)">]</text><text class="terminal-192800993-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-192800993-line-6)"> -</text><text class="terminal-192800993-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-192800993-line-7)"> -</text><text class="terminal-192800993-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-192800993-line-8)"> -</text><text class="terminal-192800993-r1" x="0" y="239.6" textLength="231.8" clip-path="url(#terminal-192800993-line-9)">generate changelog </text><text class="terminal-192800993-r2" x="231.8" y="239.6" textLength="12.2" clip-path="url(#terminal-192800993-line-9)">(</text><text class="terminal-192800993-r1" x="244" y="239.6" textLength="500.2" clip-path="url(#terminal-192800993-line-9)">note that it will overwrite existing file</text><text class="terminal-192800993-r2" x="744.2" y="239.6" textLength="12.2" clip-path="url(#terminal-192800993-line-9)">)</text><text class="terminal-192800993-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-192800993-line-9)"> -</text><text class="terminal-192800993-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-192800993-line-10)"> -</text><text class="terminal-192800993-r1" x="0" y="288.4" textLength="256.2" clip-path="url(#terminal-192800993-line-11)">positional arguments:</text><text class="terminal-192800993-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-192800993-line-11)"> -</text><text class="terminal-192800993-r1" x="0" y="312.8" textLength="805.2" clip-path="url(#terminal-192800993-line-12)">  rev_range             generates changelog for the given version </text><text class="terminal-192800993-r2" x="805.2" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">(</text><text class="terminal-192800993-r1" x="817.4" y="312.8" textLength="61" clip-path="url(#terminal-192800993-line-12)">e.g: </text><text class="terminal-192800993-r3" x="878.4" y="312.8" textLength="36.6" clip-path="url(#terminal-192800993-line-12)">1.5</text><text class="terminal-192800993-r1" x="915" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">.</text><text class="terminal-192800993-r3" x="927.2" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">3</text><text class="terminal-192800993-r2" x="939.4" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)">)</text><text class="terminal-192800993-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-192800993-line-12)"> -</text><text class="terminal-192800993-r1" x="0" y="337.2" textLength="500.2" clip-path="url(#terminal-192800993-line-13)">                        or version range </text><text class="terminal-192800993-r2" x="500.2" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">(</text><text class="terminal-192800993-r1" x="512.4" y="337.2" textLength="61" clip-path="url(#terminal-192800993-line-13)">e.g: </text><text class="terminal-192800993-r3" x="573.4" y="337.2" textLength="36.6" clip-path="url(#terminal-192800993-line-13)">1.5</text><text class="terminal-192800993-r1" x="610" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">.</text><text class="terminal-192800993-r3" x="622.2" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">3</text><text class="terminal-192800993-r1" x="634.4" y="337.2" textLength="24.4" clip-path="url(#terminal-192800993-line-13)">..</text><text class="terminal-192800993-r3" x="658.8" y="337.2" textLength="36.6" clip-path="url(#terminal-192800993-line-13)">1.7</text><text class="terminal-192800993-r1" x="695.4" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">.</text><text class="terminal-192800993-r3" x="707.6" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">9</text><text class="terminal-192800993-r2" x="719.8" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)">)</text><text class="terminal-192800993-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-192800993-line-13)"> -</text><text class="terminal-192800993-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-192800993-line-14)"> -</text><text class="terminal-192800993-r1" x="0" y="386" textLength="97.6" clip-path="url(#terminal-192800993-line-15)">options:</text><text class="terminal-192800993-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-192800993-line-15)"> -</text><text class="terminal-192800993-r1" x="0" y="410.4" textLength="671" clip-path="url(#terminal-192800993-line-16)">  -h, --help            show this help message and exit</text><text class="terminal-192800993-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-192800993-line-16)"> -</text><text class="terminal-192800993-r1" x="0" y="434.8" textLength="585.6" clip-path="url(#terminal-192800993-line-17)">  --dry-run             show changelog to stdout</text><text class="terminal-192800993-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-192800993-line-17)"> -</text><text class="terminal-192800993-r1" x="0" y="459.2" textLength="280.6" clip-path="url(#terminal-192800993-line-18)">  --file-name FILE_NAME</text><text class="terminal-192800993-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-192800993-line-18)"> -</text><text class="terminal-192800993-r1" x="0" y="483.6" textLength="573.4" clip-path="url(#terminal-192800993-line-19)">                        file name of changelog </text><text class="terminal-192800993-r2" x="573.4" y="483.6" textLength="12.2" clip-path="url(#terminal-192800993-line-19)">(</text><text class="terminal-192800993-r1" x="585.6" y="483.6" textLength="109.8" clip-path="url(#terminal-192800993-line-19)">default: </text><text class="terminal-192800993-r4" x="695.4" y="483.6" textLength="170.8" clip-path="url(#terminal-192800993-line-19)">'CHANGELOG.md'</text><text class="terminal-192800993-r2" x="866.2" y="483.6" textLength="12.2" clip-path="url(#terminal-192800993-line-19)">)</text><text class="terminal-192800993-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-192800993-line-19)"> -</text><text class="terminal-192800993-r1" x="0" y="508" textLength="500.2" clip-path="url(#terminal-192800993-line-20)">  --unreleased-version UNRELEASED_VERSION</text><text class="terminal-192800993-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-192800993-line-20)"> -</text><text class="terminal-192800993-r1" x="0" y="532.4" textLength="707.6" clip-path="url(#terminal-192800993-line-21)">                        set the value for the new version </text><text class="terminal-192800993-r2" x="707.6" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)">(</text><text class="terminal-192800993-r1" x="719.8" y="532.4" textLength="207.4" clip-path="url(#terminal-192800993-line-21)">use the tag value</text><text class="terminal-192800993-r2" x="927.2" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)">)</text><text class="terminal-192800993-r1" x="939.4" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)">,</text><text class="terminal-192800993-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-192800993-line-21)"> -</text><text class="terminal-192800993-r1" x="0" y="556.8" textLength="622.2" clip-path="url(#terminal-192800993-line-22)">                        instead of using unreleased</text><text class="terminal-192800993-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-192800993-line-22)"> -</text><text class="terminal-192800993-r1" x="0" y="581.2" textLength="939.4" clip-path="url(#terminal-192800993-line-23)">  --incremental         generates changelog from last created version, useful</text><text class="terminal-192800993-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-192800993-line-23)"> -</text><text class="terminal-192800993-r1" x="0" y="605.6" textLength="817.4" clip-path="url(#terminal-192800993-line-24)">                        if the changelog has been manually modified</text><text class="terminal-192800993-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-192800993-line-24)"> -</text><text class="terminal-192800993-r1" x="0" y="630" textLength="280.6" clip-path="url(#terminal-192800993-line-25)">  --start-rev START_REV</text><text class="terminal-192800993-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-192800993-line-25)"> -</text><text class="terminal-192800993-r1" x="0" y="654.4" textLength="866.2" clip-path="url(#terminal-192800993-line-26)">                        start rev of the changelog. If not set, it will</text><text class="terminal-192800993-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-192800993-line-26)"> -</text><text class="terminal-192800993-r1" x="0" y="678.8" textLength="695.4" clip-path="url(#terminal-192800993-line-27)">                        generate changelog from the start</text><text class="terminal-192800993-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-192800993-line-27)"> -</text><text class="terminal-192800993-r1" x="0" y="703.2" textLength="915" clip-path="url(#terminal-192800993-line-28)">  --merge-prerelease    collect all changes from prereleases into next non-</text><text class="terminal-192800993-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-192800993-line-28)"> -</text><text class="terminal-192800993-r1" x="0" y="727.6" textLength="951.6" clip-path="url(#terminal-192800993-line-29)">                        prerelease. If not set, it will include prereleases in</text><text class="terminal-192800993-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-192800993-line-29)"> -</text><text class="terminal-192800993-r1" x="0" y="752" textLength="451.4" clip-path="url(#terminal-192800993-line-30)">                        the changelog</text><text class="terminal-192800993-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-192800993-line-30)"> -</text><text class="terminal-192800993-r1" x="0" y="776.4" textLength="231.8" clip-path="url(#terminal-192800993-line-31)">  --version-scheme </text><text class="terminal-192800993-r2" x="231.8" y="776.4" textLength="12.2" clip-path="url(#terminal-192800993-line-31)">{</text><text class="terminal-192800993-r1" x="244" y="776.4" textLength="256.2" clip-path="url(#terminal-192800993-line-31)">pep440,semver,semver2</text><text class="terminal-192800993-r2" x="500.2" y="776.4" textLength="12.2" clip-path="url(#terminal-192800993-line-31)">}</text><text class="terminal-192800993-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-192800993-line-31)"> -</text><text class="terminal-192800993-r1" x="0" y="800.8" textLength="549" clip-path="url(#terminal-192800993-line-32)">                        choose version scheme</text><text class="terminal-192800993-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-192800993-line-32)"> -</text><text class="terminal-192800993-r1" x="0" y="825.2" textLength="427" clip-path="url(#terminal-192800993-line-33)">  --export-template EXPORT_TEMPLATE</text><text class="terminal-192800993-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-192800993-line-33)"> -</text><text class="terminal-192800993-r1" x="0" y="849.6" textLength="927.2" clip-path="url(#terminal-192800993-line-34)">                        Export the changelog template into this file instead</text><text class="terminal-192800993-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-192800993-line-34)"> -</text><text class="terminal-192800993-r1" x="0" y="874" textLength="475.8" clip-path="url(#terminal-192800993-line-35)">                        of rendering it</text><text class="terminal-192800993-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-192800993-line-35)"> -</text><text class="terminal-192800993-r1" x="0" y="898.4" textLength="414.8" clip-path="url(#terminal-192800993-line-36)">  --template TEMPLATE, -t TEMPLATE</text><text class="terminal-192800993-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-192800993-line-36)"> -</text><text class="terminal-192800993-r1" x="0" y="922.8" textLength="646.6" clip-path="url(#terminal-192800993-line-37)">                        changelog template file name </text><text class="terminal-192800993-r2" x="646.6" y="922.8" textLength="12.2" clip-path="url(#terminal-192800993-line-37)">(</text><text class="terminal-192800993-r1" x="658.8" y="922.8" textLength="280.6" clip-path="url(#terminal-192800993-line-37)">relative to the current</text><text class="terminal-192800993-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-192800993-line-37)"> -</text><text class="terminal-192800993-r1" x="0" y="947.2" textLength="500.2" clip-path="url(#terminal-192800993-line-38)">                        working directory</text><text class="terminal-192800993-r2" x="500.2" y="947.2" textLength="12.2" clip-path="url(#terminal-192800993-line-38)">)</text><text class="terminal-192800993-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-192800993-line-38)"> -</text><text class="terminal-192800993-r1" x="0" y="971.6" textLength="305" clip-path="url(#terminal-192800993-line-39)">  --extra EXTRA, -e EXTRA</text><text class="terminal-192800993-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-192800993-line-39)"> -</text><text class="terminal-192800993-r1" x="0" y="996" textLength="622.2" clip-path="url(#terminal-192800993-line-40)">                        a changelog extra variable </text><text class="terminal-192800993-r2" x="622.2" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">(</text><text class="terminal-192800993-r1" x="634.4" y="996" textLength="146.4" clip-path="url(#terminal-192800993-line-40)">in the form </text><text class="terminal-192800993-r4" x="780.8" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">'</text><text class="terminal-192800993-r4" x="793" y="996" textLength="36.6" clip-path="url(#terminal-192800993-line-40)">key</text><text class="terminal-192800993-r4" x="829.6" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">=</text><text class="terminal-192800993-r4" x="841.8" y="996" textLength="61" clip-path="url(#terminal-192800993-line-40)">value</text><text class="terminal-192800993-r4" x="902.8" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">'</text><text class="terminal-192800993-r2" x="915" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)">)</text><text class="terminal-192800993-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-192800993-line-40)"> -</text><text class="terminal-192800993-r1" x="0" y="1020.4" textLength="305" clip-path="url(#terminal-192800993-line-41)">  --tag-format TAG_FORMAT</text><text class="terminal-192800993-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-192800993-line-41)"> -</text><text class="terminal-192800993-r1" x="0" y="1044.8" textLength="878.4" clip-path="url(#terminal-192800993-line-42)">                        The format of the tag, wrap around simple quotes</text><text class="terminal-192800993-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-192800993-line-42)"> -</text><text class="terminal-192800993-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-192800993-line-43)"> + <g class="terminal-922159541-matrix"> + <text class="terminal-922159541-r1" x="0" y="20" textLength="256.2" clip-path="url(#terminal-922159541-line-0)">$ cz changelog --help</text><text class="terminal-922159541-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-922159541-line-0)"> +</text><text class="terminal-922159541-r1" x="0" y="44.4" textLength="244" clip-path="url(#terminal-922159541-line-1)">usage: cz changelog </text><text class="terminal-922159541-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)">[</text><text class="terminal-922159541-r1" x="256.2" y="44.4" textLength="24.4" clip-path="url(#terminal-922159541-line-1)">-h</text><text class="terminal-922159541-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)">]</text><text class="terminal-922159541-r2" x="305" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)">[</text><text class="terminal-922159541-r1" x="317.2" y="44.4" textLength="109.8" clip-path="url(#terminal-922159541-line-1)">--dry-run</text><text class="terminal-922159541-r2" x="427" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)">]</text><text class="terminal-922159541-r2" x="451.4" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)">[</text><text class="terminal-922159541-r1" x="463.6" y="44.4" textLength="256.2" clip-path="url(#terminal-922159541-line-1)">--file-name FILE_NAME</text><text class="terminal-922159541-r2" x="719.8" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)">]</text><text class="terminal-922159541-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-922159541-line-1)"> +</text><text class="terminal-922159541-r2" x="244" y="68.8" textLength="12.2" clip-path="url(#terminal-922159541-line-2)">[</text><text class="terminal-922159541-r1" x="256.2" y="68.8" textLength="475.8" clip-path="url(#terminal-922159541-line-2)">--unreleased-version UNRELEASED_VERSION</text><text class="terminal-922159541-r2" x="732" y="68.8" textLength="12.2" clip-path="url(#terminal-922159541-line-2)">]</text><text class="terminal-922159541-r2" x="756.4" y="68.8" textLength="12.2" clip-path="url(#terminal-922159541-line-2)">[</text><text class="terminal-922159541-r1" x="768.6" y="68.8" textLength="158.6" clip-path="url(#terminal-922159541-line-2)">--incremental</text><text class="terminal-922159541-r2" x="927.2" y="68.8" textLength="12.2" clip-path="url(#terminal-922159541-line-2)">]</text><text class="terminal-922159541-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-922159541-line-2)"> +</text><text class="terminal-922159541-r2" x="244" y="93.2" textLength="12.2" clip-path="url(#terminal-922159541-line-3)">[</text><text class="terminal-922159541-r1" x="256.2" y="93.2" textLength="256.2" clip-path="url(#terminal-922159541-line-3)">--start-rev START_REV</text><text class="terminal-922159541-r2" x="512.4" y="93.2" textLength="12.2" clip-path="url(#terminal-922159541-line-3)">]</text><text class="terminal-922159541-r2" x="536.8" y="93.2" textLength="12.2" clip-path="url(#terminal-922159541-line-3)">[</text><text class="terminal-922159541-r1" x="549" y="93.2" textLength="219.6" clip-path="url(#terminal-922159541-line-3)">--merge-prerelease</text><text class="terminal-922159541-r2" x="768.6" y="93.2" textLength="12.2" clip-path="url(#terminal-922159541-line-3)">]</text><text class="terminal-922159541-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-922159541-line-3)"> +</text><text class="terminal-922159541-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-922159541-line-4)">[</text><text class="terminal-922159541-r1" x="256.2" y="117.6" textLength="207.4" clip-path="url(#terminal-922159541-line-4)">--version-scheme </text><text class="terminal-922159541-r2" x="463.6" y="117.6" textLength="12.2" clip-path="url(#terminal-922159541-line-4)">{</text><text class="terminal-922159541-r1" x="475.8" y="117.6" textLength="256.2" clip-path="url(#terminal-922159541-line-4)">pep440,semver,semver2</text><text class="terminal-922159541-r2" x="732" y="117.6" textLength="12.2" clip-path="url(#terminal-922159541-line-4)">}</text><text class="terminal-922159541-r2" x="744.2" y="117.6" textLength="12.2" clip-path="url(#terminal-922159541-line-4)">]</text><text class="terminal-922159541-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-922159541-line-4)"> +</text><text class="terminal-922159541-r2" x="244" y="142" textLength="12.2" clip-path="url(#terminal-922159541-line-5)">[</text><text class="terminal-922159541-r1" x="256.2" y="142" textLength="402.6" clip-path="url(#terminal-922159541-line-5)">--export-template EXPORT_TEMPLATE</text><text class="terminal-922159541-r2" x="658.8" y="142" textLength="12.2" clip-path="url(#terminal-922159541-line-5)">]</text><text class="terminal-922159541-r2" x="683.2" y="142" textLength="12.2" clip-path="url(#terminal-922159541-line-5)">[</text><text class="terminal-922159541-r1" x="695.4" y="142" textLength="231.8" clip-path="url(#terminal-922159541-line-5)">--template TEMPLATE</text><text class="terminal-922159541-r2" x="927.2" y="142" textLength="12.2" clip-path="url(#terminal-922159541-line-5)">]</text><text class="terminal-922159541-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-922159541-line-5)"> +</text><text class="terminal-922159541-r2" x="244" y="166.4" textLength="12.2" clip-path="url(#terminal-922159541-line-6)">[</text><text class="terminal-922159541-r1" x="256.2" y="166.4" textLength="158.6" clip-path="url(#terminal-922159541-line-6)">--extra EXTRA</text><text class="terminal-922159541-r2" x="414.8" y="166.4" textLength="12.2" clip-path="url(#terminal-922159541-line-6)">]</text><text class="terminal-922159541-r2" x="439.2" y="166.4" textLength="12.2" clip-path="url(#terminal-922159541-line-6)">[</text><text class="terminal-922159541-r1" x="451.4" y="166.4" textLength="280.6" clip-path="url(#terminal-922159541-line-6)">--tag-format TAG_FORMAT</text><text class="terminal-922159541-r2" x="732" y="166.4" textLength="12.2" clip-path="url(#terminal-922159541-line-6)">]</text><text class="terminal-922159541-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-922159541-line-6)"> +</text><text class="terminal-922159541-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-922159541-line-7)"> +</text><text class="terminal-922159541-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-922159541-line-8)"> +</text><text class="terminal-922159541-r1" x="0" y="239.6" textLength="231.8" clip-path="url(#terminal-922159541-line-9)">Generate changelog </text><text class="terminal-922159541-r2" x="231.8" y="239.6" textLength="12.2" clip-path="url(#terminal-922159541-line-9)">(</text><text class="terminal-922159541-r1" x="244" y="239.6" textLength="512.4" clip-path="url(#terminal-922159541-line-9)">note that it will overwrite existing files</text><text class="terminal-922159541-r2" x="756.4" y="239.6" textLength="12.2" clip-path="url(#terminal-922159541-line-9)">)</text><text class="terminal-922159541-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-922159541-line-9)"> +</text><text class="terminal-922159541-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-922159541-line-10)"> +</text><text class="terminal-922159541-r1" x="0" y="288.4" textLength="256.2" clip-path="url(#terminal-922159541-line-11)">positional arguments:</text><text class="terminal-922159541-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-922159541-line-11)"> +</text><text class="terminal-922159541-r1" x="0" y="312.8" textLength="793" clip-path="url(#terminal-922159541-line-12)">  rev_range             Generate changelog for the given version </text><text class="terminal-922159541-r2" x="793" y="312.8" textLength="12.2" clip-path="url(#terminal-922159541-line-12)">(</text><text class="terminal-922159541-r1" x="805.2" y="312.8" textLength="73.2" clip-path="url(#terminal-922159541-line-12)">e.g., </text><text class="terminal-922159541-r3" x="878.4" y="312.8" textLength="36.6" clip-path="url(#terminal-922159541-line-12)">1.5</text><text class="terminal-922159541-r1" x="915" y="312.8" textLength="12.2" clip-path="url(#terminal-922159541-line-12)">.</text><text class="terminal-922159541-r3" x="927.2" y="312.8" textLength="12.2" clip-path="url(#terminal-922159541-line-12)">3</text><text class="terminal-922159541-r2" x="939.4" y="312.8" textLength="12.2" clip-path="url(#terminal-922159541-line-12)">)</text><text class="terminal-922159541-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-922159541-line-12)"> +</text><text class="terminal-922159541-r1" x="0" y="337.2" textLength="500.2" clip-path="url(#terminal-922159541-line-13)">                        or version range </text><text class="terminal-922159541-r2" x="500.2" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">(</text><text class="terminal-922159541-r1" x="512.4" y="337.2" textLength="73.2" clip-path="url(#terminal-922159541-line-13)">e.g., </text><text class="terminal-922159541-r3" x="585.6" y="337.2" textLength="36.6" clip-path="url(#terminal-922159541-line-13)">1.5</text><text class="terminal-922159541-r1" x="622.2" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">.</text><text class="terminal-922159541-r3" x="634.4" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">3</text><text class="terminal-922159541-r1" x="646.6" y="337.2" textLength="24.4" clip-path="url(#terminal-922159541-line-13)">..</text><text class="terminal-922159541-r3" x="671" y="337.2" textLength="36.6" clip-path="url(#terminal-922159541-line-13)">1.7</text><text class="terminal-922159541-r1" x="707.6" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">.</text><text class="terminal-922159541-r3" x="719.8" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">9</text><text class="terminal-922159541-r2" x="732" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">)</text><text class="terminal-922159541-r1" x="744.2" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)">.</text><text class="terminal-922159541-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-922159541-line-13)"> +</text><text class="terminal-922159541-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-922159541-line-14)"> +</text><text class="terminal-922159541-r1" x="0" y="386" textLength="97.6" clip-path="url(#terminal-922159541-line-15)">options:</text><text class="terminal-922159541-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-922159541-line-15)"> +</text><text class="terminal-922159541-r1" x="0" y="410.4" textLength="671" clip-path="url(#terminal-922159541-line-16)">  -h, --help            show this help message and exit</text><text class="terminal-922159541-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-922159541-line-16)"> +</text><text class="terminal-922159541-r1" x="0" y="434.8" textLength="597.8" clip-path="url(#terminal-922159541-line-17)">  --dry-run             Show changelog to stdout.</text><text class="terminal-922159541-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-922159541-line-17)"> +</text><text class="terminal-922159541-r1" x="0" y="459.2" textLength="280.6" clip-path="url(#terminal-922159541-line-18)">  --file-name FILE_NAME</text><text class="terminal-922159541-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-922159541-line-18)"> +</text><text class="terminal-922159541-r1" x="0" y="483.6" textLength="573.4" clip-path="url(#terminal-922159541-line-19)">                        File name of changelog </text><text class="terminal-922159541-r2" x="573.4" y="483.6" textLength="12.2" clip-path="url(#terminal-922159541-line-19)">(</text><text class="terminal-922159541-r1" x="585.6" y="483.6" textLength="109.8" clip-path="url(#terminal-922159541-line-19)">default: </text><text class="terminal-922159541-r4" x="695.4" y="483.6" textLength="170.8" clip-path="url(#terminal-922159541-line-19)">'CHANGELOG.md'</text><text class="terminal-922159541-r2" x="866.2" y="483.6" textLength="12.2" clip-path="url(#terminal-922159541-line-19)">)</text><text class="terminal-922159541-r1" x="878.4" y="483.6" textLength="12.2" clip-path="url(#terminal-922159541-line-19)">.</text><text class="terminal-922159541-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-922159541-line-19)"> +</text><text class="terminal-922159541-r1" x="0" y="508" textLength="500.2" clip-path="url(#terminal-922159541-line-20)">  --unreleased-version UNRELEASED_VERSION</text><text class="terminal-922159541-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-922159541-line-20)"> +</text><text class="terminal-922159541-r1" x="0" y="532.4" textLength="707.6" clip-path="url(#terminal-922159541-line-21)">                        Set the value for the new version </text><text class="terminal-922159541-r2" x="707.6" y="532.4" textLength="12.2" clip-path="url(#terminal-922159541-line-21)">(</text><text class="terminal-922159541-r1" x="719.8" y="532.4" textLength="207.4" clip-path="url(#terminal-922159541-line-21)">use the tag value</text><text class="terminal-922159541-r2" x="927.2" y="532.4" textLength="12.2" clip-path="url(#terminal-922159541-line-21)">)</text><text class="terminal-922159541-r1" x="939.4" y="532.4" textLength="12.2" clip-path="url(#terminal-922159541-line-21)">,</text><text class="terminal-922159541-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-922159541-line-21)"> +</text><text class="terminal-922159541-r1" x="0" y="556.8" textLength="744.2" clip-path="url(#terminal-922159541-line-22)">                        instead of using unreleased versions.</text><text class="terminal-922159541-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-922159541-line-22)"> +</text><text class="terminal-922159541-r1" x="0" y="581.2" textLength="890.6" clip-path="url(#terminal-922159541-line-23)">  --incremental         Generate changelog from the last created version,</text><text class="terminal-922159541-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-922159541-line-23)"> +</text><text class="terminal-922159541-r1" x="0" y="605.6" textLength="915" clip-path="url(#terminal-922159541-line-24)">                        useful if the changelog has been manually modified.</text><text class="terminal-922159541-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-922159541-line-24)"> +</text><text class="terminal-922159541-r1" x="0" y="630" textLength="280.6" clip-path="url(#terminal-922159541-line-25)">  --start-rev START_REV</text><text class="terminal-922159541-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-922159541-line-25)"> +</text><text class="terminal-922159541-r1" x="0" y="654.4" textLength="866.2" clip-path="url(#terminal-922159541-line-26)">                        Start rev of the changelog. If not set, it will</text><text class="terminal-922159541-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-922159541-line-26)"> +</text><text class="terminal-922159541-r1" x="0" y="678.8" textLength="756.4" clip-path="url(#terminal-922159541-line-27)">                        generate changelog from the beginning.</text><text class="terminal-922159541-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-922159541-line-27)"> +</text><text class="terminal-922159541-r1" x="0" y="703.2" textLength="902.8" clip-path="url(#terminal-922159541-line-28)">  --merge-prerelease    Collect all changes from prereleases into the next</text><text class="terminal-922159541-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-922159541-line-28)"> +</text><text class="terminal-922159541-r1" x="0" y="727.6" textLength="817.4" clip-path="url(#terminal-922159541-line-29)">                        non-prerelease. If not set, it will include</text><text class="terminal-922159541-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-922159541-line-29)"> +</text><text class="terminal-922159541-r1" x="0" y="752" textLength="646.6" clip-path="url(#terminal-922159541-line-30)">                        prereleases in the changelog.</text><text class="terminal-922159541-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-922159541-line-30)"> +</text><text class="terminal-922159541-r1" x="0" y="776.4" textLength="231.8" clip-path="url(#terminal-922159541-line-31)">  --version-scheme </text><text class="terminal-922159541-r2" x="231.8" y="776.4" textLength="12.2" clip-path="url(#terminal-922159541-line-31)">{</text><text class="terminal-922159541-r1" x="244" y="776.4" textLength="256.2" clip-path="url(#terminal-922159541-line-31)">pep440,semver,semver2</text><text class="terminal-922159541-r2" x="500.2" y="776.4" textLength="12.2" clip-path="url(#terminal-922159541-line-31)">}</text><text class="terminal-922159541-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-922159541-line-31)"> +</text><text class="terminal-922159541-r1" x="0" y="800.8" textLength="561.2" clip-path="url(#terminal-922159541-line-32)">                        Choose version scheme.</text><text class="terminal-922159541-r1" x="976" y="800.8" textLength="12.2" clip-path="url(#terminal-922159541-line-32)"> +</text><text class="terminal-922159541-r1" x="0" y="825.2" textLength="427" clip-path="url(#terminal-922159541-line-33)">  --export-template EXPORT_TEMPLATE</text><text class="terminal-922159541-r1" x="976" y="825.2" textLength="12.2" clip-path="url(#terminal-922159541-line-33)"> +</text><text class="terminal-922159541-r1" x="0" y="849.6" textLength="927.2" clip-path="url(#terminal-922159541-line-34)">                        Export the changelog template into this file instead</text><text class="terminal-922159541-r1" x="976" y="849.6" textLength="12.2" clip-path="url(#terminal-922159541-line-34)"> +</text><text class="terminal-922159541-r1" x="0" y="874" textLength="488" clip-path="url(#terminal-922159541-line-35)">                        of rendering it.</text><text class="terminal-922159541-r1" x="976" y="874" textLength="12.2" clip-path="url(#terminal-922159541-line-35)"> +</text><text class="terminal-922159541-r1" x="0" y="898.4" textLength="414.8" clip-path="url(#terminal-922159541-line-36)">  --template TEMPLATE, -t TEMPLATE</text><text class="terminal-922159541-r1" x="976" y="898.4" textLength="12.2" clip-path="url(#terminal-922159541-line-36)"> +</text><text class="terminal-922159541-r1" x="0" y="922.8" textLength="646.6" clip-path="url(#terminal-922159541-line-37)">                        Changelog template file name </text><text class="terminal-922159541-r2" x="646.6" y="922.8" textLength="12.2" clip-path="url(#terminal-922159541-line-37)">(</text><text class="terminal-922159541-r1" x="658.8" y="922.8" textLength="280.6" clip-path="url(#terminal-922159541-line-37)">relative to the current</text><text class="terminal-922159541-r1" x="976" y="922.8" textLength="12.2" clip-path="url(#terminal-922159541-line-37)"> +</text><text class="terminal-922159541-r1" x="0" y="947.2" textLength="500.2" clip-path="url(#terminal-922159541-line-38)">                        working directory</text><text class="terminal-922159541-r2" x="500.2" y="947.2" textLength="12.2" clip-path="url(#terminal-922159541-line-38)">)</text><text class="terminal-922159541-r1" x="512.4" y="947.2" textLength="12.2" clip-path="url(#terminal-922159541-line-38)">.</text><text class="terminal-922159541-r1" x="976" y="947.2" textLength="12.2" clip-path="url(#terminal-922159541-line-38)"> +</text><text class="terminal-922159541-r1" x="0" y="971.6" textLength="305" clip-path="url(#terminal-922159541-line-39)">  --extra EXTRA, -e EXTRA</text><text class="terminal-922159541-r1" x="976" y="971.6" textLength="12.2" clip-path="url(#terminal-922159541-line-39)"> +</text><text class="terminal-922159541-r1" x="0" y="996" textLength="610" clip-path="url(#terminal-922159541-line-40)">                        Changelog extra variables </text><text class="terminal-922159541-r2" x="610" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)">(</text><text class="terminal-922159541-r1" x="622.2" y="996" textLength="146.4" clip-path="url(#terminal-922159541-line-40)">in the form </text><text class="terminal-922159541-r4" x="768.6" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)">'</text><text class="terminal-922159541-r4" x="780.8" y="996" textLength="36.6" clip-path="url(#terminal-922159541-line-40)">key</text><text class="terminal-922159541-r4" x="817.4" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)">=</text><text class="terminal-922159541-r4" x="829.6" y="996" textLength="61" clip-path="url(#terminal-922159541-line-40)">value</text><text class="terminal-922159541-r4" x="890.6" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)">'</text><text class="terminal-922159541-r2" x="902.8" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)">)</text><text class="terminal-922159541-r1" x="915" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)">.</text><text class="terminal-922159541-r1" x="976" y="996" textLength="12.2" clip-path="url(#terminal-922159541-line-40)"> +</text><text class="terminal-922159541-r1" x="0" y="1020.4" textLength="305" clip-path="url(#terminal-922159541-line-41)">  --tag-format TAG_FORMAT</text><text class="terminal-922159541-r1" x="976" y="1020.4" textLength="12.2" clip-path="url(#terminal-922159541-line-41)"> +</text><text class="terminal-922159541-r1" x="0" y="1044.8" textLength="890.6" clip-path="url(#terminal-922159541-line-42)">                        The format of the tag, wrap around simple quotes.</text><text class="terminal-922159541-r1" x="976" y="1044.8" textLength="12.2" clip-path="url(#terminal-922159541-line-42)"> +</text><text class="terminal-922159541-r1" x="976" y="1069.2" textLength="12.2" clip-path="url(#terminal-922159541-line-43)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_check___help.svg b/docs/images/cli_help/cz_check___help.svg index 0ced75f60a..1091491d36 100644 --- a/docs/images/cli_help/cz_check___help.svg +++ b/docs/images/cli_help/cz_check___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 806.4" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 830.8" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,162 +19,166 @@ font-weight: 700; } - .terminal-3805463-matrix { + .terminal-1597319345-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3805463-title { + .terminal-1597319345-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3805463-r1 { fill: #c5c8c6 } -.terminal-3805463-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-3805463-r3 { fill: #d0b344 } -.terminal-3805463-r4 { fill: #68a0b3;font-weight: bold } + .terminal-1597319345-r1 { fill: #c5c8c6 } +.terminal-1597319345-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-1597319345-r3 { fill: #d0b344 } +.terminal-1597319345-r4 { fill: #68a0b3;font-weight: bold } </style> <defs> - <clipPath id="terminal-3805463-clip-terminal"> - <rect x="0" y="0" width="975.0" height="755.4" /> + <clipPath id="terminal-1597319345-clip-terminal"> + <rect x="0" y="0" width="975.0" height="779.8" /> </clipPath> - <clipPath id="terminal-3805463-line-0"> + <clipPath id="terminal-1597319345-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-1"> +<clipPath id="terminal-1597319345-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-2"> +<clipPath id="terminal-1597319345-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-3"> +<clipPath id="terminal-1597319345-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-4"> +<clipPath id="terminal-1597319345-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-5"> +<clipPath id="terminal-1597319345-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-6"> +<clipPath id="terminal-1597319345-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-7"> +<clipPath id="terminal-1597319345-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-8"> +<clipPath id="terminal-1597319345-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-9"> +<clipPath id="terminal-1597319345-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-10"> +<clipPath id="terminal-1597319345-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-11"> +<clipPath id="terminal-1597319345-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-12"> +<clipPath id="terminal-1597319345-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-13"> +<clipPath id="terminal-1597319345-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-14"> +<clipPath id="terminal-1597319345-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-15"> +<clipPath id="terminal-1597319345-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-16"> +<clipPath id="terminal-1597319345-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-17"> +<clipPath id="terminal-1597319345-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-18"> +<clipPath id="terminal-1597319345-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-19"> +<clipPath id="terminal-1597319345-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-20"> +<clipPath id="terminal-1597319345-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-21"> +<clipPath id="terminal-1597319345-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-22"> +<clipPath id="terminal-1597319345-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-23"> +<clipPath id="terminal-1597319345-line-23"> <rect x="0" y="562.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-24"> +<clipPath id="terminal-1597319345-line-24"> <rect x="0" y="587.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-25"> +<clipPath id="terminal-1597319345-line-25"> <rect x="0" y="611.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-26"> +<clipPath id="terminal-1597319345-line-26"> <rect x="0" y="635.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-27"> +<clipPath id="terminal-1597319345-line-27"> <rect x="0" y="660.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-28"> +<clipPath id="terminal-1597319345-line-28"> <rect x="0" y="684.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-3805463-line-29"> +<clipPath id="terminal-1597319345-line-29"> <rect x="0" y="709.1" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-1597319345-line-30"> + <rect x="0" y="733.5" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="804.4" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="828.8" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-3805463-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-1597319345-clip-terminal)"> - <g class="terminal-3805463-matrix"> - <text class="terminal-3805463-r1" x="0" y="20" textLength="207.4" clip-path="url(#terminal-3805463-line-0)">$ cz check --help</text><text class="terminal-3805463-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-3805463-line-0)"> -</text><text class="terminal-3805463-r1" x="0" y="44.4" textLength="195.2" clip-path="url(#terminal-3805463-line-1)">usage: cz check </text><text class="terminal-3805463-r2" x="195.2" y="44.4" textLength="12.2" clip-path="url(#terminal-3805463-line-1)">[</text><text class="terminal-3805463-r1" x="207.4" y="44.4" textLength="24.4" clip-path="url(#terminal-3805463-line-1)">-h</text><text class="terminal-3805463-r2" x="231.8" y="44.4" textLength="12.2" clip-path="url(#terminal-3805463-line-1)">]</text><text class="terminal-3805463-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-3805463-line-1)"> -</text><text class="terminal-3805463-r2" x="195.2" y="68.8" textLength="12.2" clip-path="url(#terminal-3805463-line-2)">[</text><text class="terminal-3805463-r1" x="207.4" y="68.8" textLength="768.6" clip-path="url(#terminal-3805463-line-2)">--commit-msg-file COMMIT_MSG_FILE | --rev-range REV_RANGE | -d </text><text class="terminal-3805463-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-3805463-line-2)"> -</text><text class="terminal-3805463-r1" x="0" y="93.2" textLength="146.4" clip-path="url(#terminal-3805463-line-3)">| -m MESSAGE</text><text class="terminal-3805463-r2" x="146.4" y="93.2" textLength="12.2" clip-path="url(#terminal-3805463-line-3)">]</text><text class="terminal-3805463-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-3805463-line-3)"> -</text><text class="terminal-3805463-r2" x="195.2" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">[</text><text class="terminal-3805463-r1" x="207.4" y="117.6" textLength="158.6" clip-path="url(#terminal-3805463-line-4)">--allow-abort</text><text class="terminal-3805463-r2" x="366" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">]</text><text class="terminal-3805463-r2" x="390.4" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">[</text><text class="terminal-3805463-r1" x="402.6" y="117.6" textLength="231.8" clip-path="url(#terminal-3805463-line-4)">--allowed-prefixes </text><text class="terminal-3805463-r2" x="634.4" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">[</text><text class="terminal-3805463-r1" x="646.6" y="117.6" textLength="207.4" clip-path="url(#terminal-3805463-line-4)">ALLOWED_PREFIXES </text><text class="terminal-3805463-r3" x="854" y="117.6" textLength="36.6" clip-path="url(#terminal-3805463-line-4)">...</text><text class="terminal-3805463-r2" x="890.6" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">]</text><text class="terminal-3805463-r2" x="902.8" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)">]</text><text class="terminal-3805463-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-3805463-line-4)"> -</text><text class="terminal-3805463-r2" x="195.2" y="142" textLength="12.2" clip-path="url(#terminal-3805463-line-5)">[</text><text class="terminal-3805463-r1" x="207.4" y="142" textLength="280.6" clip-path="url(#terminal-3805463-line-5)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-3805463-r2" x="488" y="142" textLength="12.2" clip-path="url(#terminal-3805463-line-5)">]</text><text class="terminal-3805463-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-3805463-line-5)"> -</text><text class="terminal-3805463-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-3805463-line-6)"> -</text><text class="terminal-3805463-r1" x="0" y="190.8" textLength="744.2" clip-path="url(#terminal-3805463-line-7)">validates that a commit message matches the commitizen schema</text><text class="terminal-3805463-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-3805463-line-7)"> -</text><text class="terminal-3805463-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-3805463-line-8)"> -</text><text class="terminal-3805463-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-3805463-line-9)">options:</text><text class="terminal-3805463-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-3805463-line-9)"> -</text><text class="terminal-3805463-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-3805463-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-3805463-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-3805463-line-10)"> -</text><text class="terminal-3805463-r1" x="0" y="288.4" textLength="427" clip-path="url(#terminal-3805463-line-11)">  --commit-msg-file COMMIT_MSG_FILE</text><text class="terminal-3805463-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-3805463-line-11)"> -</text><text class="terminal-3805463-r1" x="0" y="312.8" textLength="915" clip-path="url(#terminal-3805463-line-12)">                        ask for the name of the temporal file that contains</text><text class="terminal-3805463-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-3805463-line-12)"> -</text><text class="terminal-3805463-r1" x="0" y="337.2" textLength="902.8" clip-path="url(#terminal-3805463-line-13)">                        the commit message. Using it in a git hook script:</text><text class="terminal-3805463-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-3805463-line-13)"> -</text><text class="terminal-3805463-r3" x="292.8" y="361.6" textLength="97.6" clip-path="url(#terminal-3805463-line-14)">MSG_FILE</text><text class="terminal-3805463-r1" x="390.4" y="361.6" textLength="24.4" clip-path="url(#terminal-3805463-line-14)">=$</text><text class="terminal-3805463-r4" x="414.8" y="361.6" textLength="12.2" clip-path="url(#terminal-3805463-line-14)">1</text><text class="terminal-3805463-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-3805463-line-14)"> -</text><text class="terminal-3805463-r1" x="0" y="386" textLength="280.6" clip-path="url(#terminal-3805463-line-15)">  --rev-range REV_RANGE</text><text class="terminal-3805463-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-3805463-line-15)"> -</text><text class="terminal-3805463-r1" x="0" y="410.4" textLength="854" clip-path="url(#terminal-3805463-line-16)">                        a range of git rev to check. e.g, master..HEAD</text><text class="terminal-3805463-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-3805463-line-16)"> -</text><text class="terminal-3805463-r1" x="0" y="434.8" textLength="305" clip-path="url(#terminal-3805463-line-17)">  -d, --use-default-range</text><text class="terminal-3805463-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-3805463-line-17)"> -</text><text class="terminal-3805463-r1" x="0" y="459.2" textLength="817.4" clip-path="url(#terminal-3805463-line-18)">                        check from the default branch to HEAD. e.g,</text><text class="terminal-3805463-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-3805463-line-18)"> -</text><text class="terminal-3805463-r1" x="0" y="483.6" textLength="683.2" clip-path="url(#terminal-3805463-line-19)">                        refs/remotes/origin/master..HEAD</text><text class="terminal-3805463-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-3805463-line-19)"> -</text><text class="terminal-3805463-r1" x="0" y="508" textLength="378.2" clip-path="url(#terminal-3805463-line-20)">  -m MESSAGE, --message MESSAGE</text><text class="terminal-3805463-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-3805463-line-20)"> -</text><text class="terminal-3805463-r1" x="0" y="532.4" textLength="768.6" clip-path="url(#terminal-3805463-line-21)">                        commit message that needs to be checked</text><text class="terminal-3805463-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-3805463-line-21)"> -</text><text class="terminal-3805463-r1" x="0" y="556.8" textLength="927.2" clip-path="url(#terminal-3805463-line-22)">  --allow-abort         allow empty commit messages, which typically abort a</text><text class="terminal-3805463-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-3805463-line-22)"> -</text><text class="terminal-3805463-r1" x="0" y="581.2" textLength="366" clip-path="url(#terminal-3805463-line-23)">                        commit</text><text class="terminal-3805463-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-3805463-line-23)"> -</text><text class="terminal-3805463-r1" x="0" y="605.6" textLength="256.2" clip-path="url(#terminal-3805463-line-24)">  --allowed-prefixes </text><text class="terminal-3805463-r2" x="256.2" y="605.6" textLength="12.2" clip-path="url(#terminal-3805463-line-24)">[</text><text class="terminal-3805463-r1" x="268.4" y="605.6" textLength="207.4" clip-path="url(#terminal-3805463-line-24)">ALLOWED_PREFIXES </text><text class="terminal-3805463-r3" x="475.8" y="605.6" textLength="36.6" clip-path="url(#terminal-3805463-line-24)">...</text><text class="terminal-3805463-r2" x="512.4" y="605.6" textLength="12.2" clip-path="url(#terminal-3805463-line-24)">]</text><text class="terminal-3805463-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-3805463-line-24)"> -</text><text class="terminal-3805463-r1" x="0" y="630" textLength="951.6" clip-path="url(#terminal-3805463-line-25)">                        allowed commit message prefixes. If the message starts</text><text class="terminal-3805463-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-3805463-line-25)"> -</text><text class="terminal-3805463-r1" x="0" y="654.4" textLength="951.6" clip-path="url(#terminal-3805463-line-26)">                        by one of these prefixes, the message won't be checked</text><text class="terminal-3805463-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-3805463-line-26)"> -</text><text class="terminal-3805463-r1" x="0" y="678.8" textLength="500.2" clip-path="url(#terminal-3805463-line-27)">                        against the regex</text><text class="terminal-3805463-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-3805463-line-27)"> -</text><text class="terminal-3805463-r1" x="0" y="703.2" textLength="854" clip-path="url(#terminal-3805463-line-28)">  -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-3805463-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-3805463-line-28)"> -</text><text class="terminal-3805463-r1" x="0" y="727.6" textLength="732" clip-path="url(#terminal-3805463-line-29)">                        length limit of the commit message; </text><text class="terminal-3805463-r4" x="732" y="727.6" textLength="12.2" clip-path="url(#terminal-3805463-line-29)">0</text><text class="terminal-3805463-r1" x="744.2" y="727.6" textLength="158.6" clip-path="url(#terminal-3805463-line-29)"> for no limit</text><text class="terminal-3805463-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-3805463-line-29)"> -</text><text class="terminal-3805463-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-3805463-line-30)"> + <g class="terminal-1597319345-matrix"> + <text class="terminal-1597319345-r1" x="0" y="20" textLength="207.4" clip-path="url(#terminal-1597319345-line-0)">$ cz check --help</text><text class="terminal-1597319345-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1597319345-line-0)"> +</text><text class="terminal-1597319345-r1" x="0" y="44.4" textLength="195.2" clip-path="url(#terminal-1597319345-line-1)">usage: cz check </text><text class="terminal-1597319345-r2" x="195.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-1)">[</text><text class="terminal-1597319345-r1" x="207.4" y="44.4" textLength="24.4" clip-path="url(#terminal-1597319345-line-1)">-h</text><text class="terminal-1597319345-r2" x="231.8" y="44.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-1)">]</text><text class="terminal-1597319345-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-1)"> +</text><text class="terminal-1597319345-r2" x="195.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-2)">[</text><text class="terminal-1597319345-r1" x="207.4" y="68.8" textLength="768.6" clip-path="url(#terminal-1597319345-line-2)">--commit-msg-file COMMIT_MSG_FILE | --rev-range REV_RANGE | -d </text><text class="terminal-1597319345-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-2)"> +</text><text class="terminal-1597319345-r1" x="0" y="93.2" textLength="146.4" clip-path="url(#terminal-1597319345-line-3)">| -m MESSAGE</text><text class="terminal-1597319345-r2" x="146.4" y="93.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-3)">]</text><text class="terminal-1597319345-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-3)"> +</text><text class="terminal-1597319345-r2" x="195.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)">[</text><text class="terminal-1597319345-r1" x="207.4" y="117.6" textLength="158.6" clip-path="url(#terminal-1597319345-line-4)">--allow-abort</text><text class="terminal-1597319345-r2" x="366" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)">]</text><text class="terminal-1597319345-r2" x="390.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)">[</text><text class="terminal-1597319345-r1" x="402.6" y="117.6" textLength="231.8" clip-path="url(#terminal-1597319345-line-4)">--allowed-prefixes </text><text class="terminal-1597319345-r2" x="634.4" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)">[</text><text class="terminal-1597319345-r1" x="646.6" y="117.6" textLength="207.4" clip-path="url(#terminal-1597319345-line-4)">ALLOWED_PREFIXES </text><text class="terminal-1597319345-r3" x="854" y="117.6" textLength="36.6" clip-path="url(#terminal-1597319345-line-4)">...</text><text class="terminal-1597319345-r2" x="890.6" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)">]</text><text class="terminal-1597319345-r2" x="902.8" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)">]</text><text class="terminal-1597319345-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-4)"> +</text><text class="terminal-1597319345-r2" x="195.2" y="142" textLength="12.2" clip-path="url(#terminal-1597319345-line-5)">[</text><text class="terminal-1597319345-r1" x="207.4" y="142" textLength="280.6" clip-path="url(#terminal-1597319345-line-5)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-1597319345-r2" x="488" y="142" textLength="12.2" clip-path="url(#terminal-1597319345-line-5)">]</text><text class="terminal-1597319345-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1597319345-line-5)"> +</text><text class="terminal-1597319345-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-6)"> +</text><text class="terminal-1597319345-r1" x="0" y="190.8" textLength="732" clip-path="url(#terminal-1597319345-line-7)">Validate that a commit message matches the commitizen schema</text><text class="terminal-1597319345-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-7)"> +</text><text class="terminal-1597319345-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-8)"> +</text><text class="terminal-1597319345-r1" x="0" y="239.6" textLength="97.6" clip-path="url(#terminal-1597319345-line-9)">options:</text><text class="terminal-1597319345-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-9)"> +</text><text class="terminal-1597319345-r1" x="0" y="264" textLength="671" clip-path="url(#terminal-1597319345-line-10)">  -h, --help            show this help message and exit</text><text class="terminal-1597319345-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1597319345-line-10)"> +</text><text class="terminal-1597319345-r1" x="0" y="288.4" textLength="427" clip-path="url(#terminal-1597319345-line-11)">  --commit-msg-file COMMIT_MSG_FILE</text><text class="terminal-1597319345-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-11)"> +</text><text class="terminal-1597319345-r1" x="0" y="312.8" textLength="927.2" clip-path="url(#terminal-1597319345-line-12)">                        Ask for the name of the temporary file that contains</text><text class="terminal-1597319345-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-12)"> +</text><text class="terminal-1597319345-r1" x="0" y="337.2" textLength="878.4" clip-path="url(#terminal-1597319345-line-13)">                        the commit message. Use it in a git hook script:</text><text class="terminal-1597319345-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-13)"> +</text><text class="terminal-1597319345-r3" x="292.8" y="361.6" textLength="97.6" clip-path="url(#terminal-1597319345-line-14)">MSG_FILE</text><text class="terminal-1597319345-r1" x="390.4" y="361.6" textLength="24.4" clip-path="url(#terminal-1597319345-line-14)">=$</text><text class="terminal-1597319345-r4" x="414.8" y="361.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-14)">1</text><text class="terminal-1597319345-r1" x="427" y="361.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-14)">.</text><text class="terminal-1597319345-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-14)"> +</text><text class="terminal-1597319345-r1" x="0" y="386" textLength="280.6" clip-path="url(#terminal-1597319345-line-15)">  --rev-range REV_RANGE</text><text class="terminal-1597319345-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1597319345-line-15)"> +</text><text class="terminal-1597319345-r1" x="0" y="410.4" textLength="915" clip-path="url(#terminal-1597319345-line-16)">                        Validate the commits in the given range of git rev,</text><text class="terminal-1597319345-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-16)"> +</text><text class="terminal-1597319345-r1" x="0" y="434.8" textLength="524.6" clip-path="url(#terminal-1597319345-line-17)">                        e.g., master..HEAD.</text><text class="terminal-1597319345-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-17)"> +</text><text class="terminal-1597319345-r1" x="0" y="459.2" textLength="305" clip-path="url(#terminal-1597319345-line-18)">  -d, --use-default-range</text><text class="terminal-1597319345-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-18)"> +</text><text class="terminal-1597319345-r1" x="0" y="483.6" textLength="939.4" clip-path="url(#terminal-1597319345-line-19)">                        Validate the commits from the default branch to HEAD,</text><text class="terminal-1597319345-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-19)"> +</text><text class="terminal-1597319345-r1" x="0" y="508" textLength="768.6" clip-path="url(#terminal-1597319345-line-20)">                        e.g., refs/remotes/origin/master..HEAD.</text><text class="terminal-1597319345-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1597319345-line-20)"> +</text><text class="terminal-1597319345-r1" x="0" y="532.4" textLength="378.2" clip-path="url(#terminal-1597319345-line-21)">  -m MESSAGE, --message MESSAGE</text><text class="terminal-1597319345-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-21)"> +</text><text class="terminal-1597319345-r1" x="0" y="556.8" textLength="707.6" clip-path="url(#terminal-1597319345-line-22)">                        Validate the given commit message.</text><text class="terminal-1597319345-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-22)"> +</text><text class="terminal-1597319345-r1" x="0" y="581.2" textLength="927.2" clip-path="url(#terminal-1597319345-line-23)">  --allow-abort         Allow empty commit messages, which typically abort a</text><text class="terminal-1597319345-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-23)"> +</text><text class="terminal-1597319345-r1" x="0" y="605.6" textLength="378.2" clip-path="url(#terminal-1597319345-line-24)">                        commit.</text><text class="terminal-1597319345-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-24)"> +</text><text class="terminal-1597319345-r1" x="0" y="630" textLength="256.2" clip-path="url(#terminal-1597319345-line-25)">  --allowed-prefixes </text><text class="terminal-1597319345-r2" x="256.2" y="630" textLength="12.2" clip-path="url(#terminal-1597319345-line-25)">[</text><text class="terminal-1597319345-r1" x="268.4" y="630" textLength="207.4" clip-path="url(#terminal-1597319345-line-25)">ALLOWED_PREFIXES </text><text class="terminal-1597319345-r3" x="475.8" y="630" textLength="36.6" clip-path="url(#terminal-1597319345-line-25)">...</text><text class="terminal-1597319345-r2" x="512.4" y="630" textLength="12.2" clip-path="url(#terminal-1597319345-line-25)">]</text><text class="terminal-1597319345-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1597319345-line-25)"> +</text><text class="terminal-1597319345-r1" x="0" y="654.4" textLength="915" clip-path="url(#terminal-1597319345-line-26)">                        Skip validation for commit messages that start with</text><text class="terminal-1597319345-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-26)"> +</text><text class="terminal-1597319345-r1" x="0" y="678.8" textLength="573.4" clip-path="url(#terminal-1597319345-line-27)">                        the specified prefixes.</text><text class="terminal-1597319345-r1" x="976" y="678.8" textLength="12.2" clip-path="url(#terminal-1597319345-line-27)"> +</text><text class="terminal-1597319345-r1" x="0" y="703.2" textLength="854" clip-path="url(#terminal-1597319345-line-28)">  -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-1597319345-r1" x="976" y="703.2" textLength="12.2" clip-path="url(#terminal-1597319345-line-28)"> +</text><text class="terminal-1597319345-r1" x="0" y="727.6" textLength="878.4" clip-path="url(#terminal-1597319345-line-29)">                        Restrict the length of the **first line** of the</text><text class="terminal-1597319345-r1" x="976" y="727.6" textLength="12.2" clip-path="url(#terminal-1597319345-line-29)"> +</text><text class="terminal-1597319345-r1" x="0" y="752" textLength="488" clip-path="url(#terminal-1597319345-line-30)">                        commit message; </text><text class="terminal-1597319345-r4" x="488" y="752" textLength="12.2" clip-path="url(#terminal-1597319345-line-30)">0</text><text class="terminal-1597319345-r1" x="500.2" y="752" textLength="170.8" clip-path="url(#terminal-1597319345-line-30)"> for no limit.</text><text class="terminal-1597319345-r1" x="976" y="752" textLength="12.2" clip-path="url(#terminal-1597319345-line-30)"> +</text><text class="terminal-1597319345-r1" x="976" y="776.4" textLength="12.2" clip-path="url(#terminal-1597319345-line-31)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_commit___help.svg b/docs/images/cli_help/cz_commit___help.svg index 9b68844b57..1905186bb5 100644 --- a/docs/images/cli_help/cz_commit___help.svg +++ b/docs/images/cli_help/cz_commit___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 708.8" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,134 +19,145 @@ font-weight: 700; } - .terminal-650700618-matrix { + .terminal-1022884229-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-650700618-title { + .terminal-1022884229-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-650700618-r1 { fill: #c5c8c6 } -.terminal-650700618-r2 { fill: #c5c8c6;font-weight: bold } -.terminal-650700618-r3 { fill: #98a84b } -.terminal-650700618-r4 { fill: #68a0b3;font-weight: bold } + .terminal-1022884229-r1 { fill: #c5c8c6 } +.terminal-1022884229-r2 { fill: #c5c8c6;font-weight: bold } +.terminal-1022884229-r3 { fill: #68a0b3;font-weight: bold } </style> <defs> - <clipPath id="terminal-650700618-clip-terminal"> - <rect x="0" y="0" width="975.0" height="584.5999999999999" /> + <clipPath id="terminal-1022884229-clip-terminal"> + <rect x="0" y="0" width="975.0" height="657.8" /> </clipPath> - <clipPath id="terminal-650700618-line-0"> + <clipPath id="terminal-1022884229-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-1"> +<clipPath id="terminal-1022884229-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-2"> +<clipPath id="terminal-1022884229-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-3"> +<clipPath id="terminal-1022884229-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-4"> +<clipPath id="terminal-1022884229-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-5"> +<clipPath id="terminal-1022884229-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-6"> +<clipPath id="terminal-1022884229-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-7"> +<clipPath id="terminal-1022884229-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-8"> +<clipPath id="terminal-1022884229-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-9"> +<clipPath id="terminal-1022884229-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-10"> +<clipPath id="terminal-1022884229-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-11"> +<clipPath id="terminal-1022884229-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-12"> +<clipPath id="terminal-1022884229-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-13"> +<clipPath id="terminal-1022884229-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-14"> +<clipPath id="terminal-1022884229-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-15"> +<clipPath id="terminal-1022884229-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-16"> +<clipPath id="terminal-1022884229-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-17"> +<clipPath id="terminal-1022884229-line-17"> <rect x="0" y="416.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-18"> +<clipPath id="terminal-1022884229-line-18"> <rect x="0" y="440.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-19"> +<clipPath id="terminal-1022884229-line-19"> <rect x="0" y="465.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-20"> +<clipPath id="terminal-1022884229-line-20"> <rect x="0" y="489.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-21"> +<clipPath id="terminal-1022884229-line-21"> <rect x="0" y="513.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-650700618-line-22"> +<clipPath id="terminal-1022884229-line-22"> <rect x="0" y="538.3" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-1022884229-line-23"> + <rect x="0" y="562.7" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-1022884229-line-24"> + <rect x="0" y="587.1" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-1022884229-line-25"> + <rect x="0" y="611.5" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="706.8" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-650700618-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-1022884229-clip-terminal)"> - <g class="terminal-650700618-matrix"> - <text class="terminal-650700618-r1" x="0" y="20" textLength="219.6" clip-path="url(#terminal-650700618-line-0)">$ cz commit --help</text><text class="terminal-650700618-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-650700618-line-0)"> -</text><text class="terminal-650700618-r1" x="0" y="44.4" textLength="207.4" clip-path="url(#terminal-650700618-line-1)">usage: cz commit </text><text class="terminal-650700618-r2" x="207.4" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="219.6" y="44.4" textLength="24.4" clip-path="url(#terminal-650700618-line-1)">-h</text><text class="terminal-650700618-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r2" x="268.4" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="280.6" y="44.4" textLength="85.4" clip-path="url(#terminal-650700618-line-1)">--retry</text><text class="terminal-650700618-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="402.6" y="44.4" textLength="122" clip-path="url(#terminal-650700618-line-1)">--no-retry</text><text class="terminal-650700618-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">[</text><text class="terminal-650700618-r1" x="561.2" y="44.4" textLength="109.8" clip-path="url(#terminal-650700618-line-1)">--dry-run</text><text class="terminal-650700618-r2" x="671" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)">]</text><text class="terminal-650700618-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-650700618-line-1)"> -</text><text class="terminal-650700618-r2" x="207.4" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="219.6" y="68.8" textLength="402.6" clip-path="url(#terminal-650700618-line-2)">--write-message-to-file FILE_PATH</text><text class="terminal-650700618-r2" x="622.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r2" x="646.6" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="658.8" y="68.8" textLength="24.4" clip-path="url(#terminal-650700618-line-2)">-s</text><text class="terminal-650700618-r2" x="683.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r2" x="707.6" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="719.8" y="68.8" textLength="24.4" clip-path="url(#terminal-650700618-line-2)">-a</text><text class="terminal-650700618-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r2" x="768.6" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">[</text><text class="terminal-650700618-r1" x="780.8" y="68.8" textLength="24.4" clip-path="url(#terminal-650700618-line-2)">-e</text><text class="terminal-650700618-r2" x="805.2" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)">]</text><text class="terminal-650700618-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-650700618-line-2)"> -</text><text class="terminal-650700618-r2" x="207.4" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">[</text><text class="terminal-650700618-r1" x="219.6" y="93.2" textLength="280.6" clip-path="url(#terminal-650700618-line-3)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-650700618-r2" x="500.2" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">]</text><text class="terminal-650700618-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">[</text><text class="terminal-650700618-r1" x="536.8" y="93.2" textLength="24.4" clip-path="url(#terminal-650700618-line-3)">--</text><text class="terminal-650700618-r2" x="561.2" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)">]</text><text class="terminal-650700618-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-650700618-line-3)"> -</text><text class="terminal-650700618-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-650700618-line-4)"> -</text><text class="terminal-650700618-r1" x="0" y="142" textLength="207.4" clip-path="url(#terminal-650700618-line-5)">create new commit</text><text class="terminal-650700618-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-650700618-line-5)"> -</text><text class="terminal-650700618-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-650700618-line-6)"> -</text><text class="terminal-650700618-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-650700618-line-7)">options:</text><text class="terminal-650700618-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-650700618-line-7)"> -</text><text class="terminal-650700618-r1" x="0" y="215.2" textLength="671" clip-path="url(#terminal-650700618-line-8)">  -h, --help            show this help message and exit</text><text class="terminal-650700618-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-650700618-line-8)"> -</text><text class="terminal-650700618-r1" x="0" y="239.6" textLength="500.2" clip-path="url(#terminal-650700618-line-9)">  --retry               retry last commit</text><text class="terminal-650700618-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-650700618-line-9)"> -</text><text class="terminal-650700618-r1" x="0" y="264" textLength="878.4" clip-path="url(#terminal-650700618-line-10)">  --no-retry            skip retry if retry_after_failure is set to true</text><text class="terminal-650700618-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-650700618-line-10)"> -</text><text class="terminal-650700618-r1" x="0" y="288.4" textLength="915" clip-path="url(#terminal-650700618-line-11)">  --dry-run             show output to stdout, no commit, no modified files</text><text class="terminal-650700618-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-650700618-line-11)"> -</text><text class="terminal-650700618-r1" x="0" y="312.8" textLength="427" clip-path="url(#terminal-650700618-line-12)">  --write-message-to-file FILE_PATH</text><text class="terminal-650700618-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-650700618-line-12)"> -</text><text class="terminal-650700618-r1" x="0" y="337.2" textLength="780.8" clip-path="url(#terminal-650700618-line-13)">                        write message to file before committing </text><text class="terminal-650700618-r2" x="780.8" y="337.2" textLength="12.2" clip-path="url(#terminal-650700618-line-13)">(</text><text class="terminal-650700618-r1" x="793" y="337.2" textLength="73.2" clip-path="url(#terminal-650700618-line-13)">can be</text><text class="terminal-650700618-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-650700618-line-13)"> -</text><text class="terminal-650700618-r1" x="0" y="361.6" textLength="573.4" clip-path="url(#terminal-650700618-line-14)">                        combined with --dry-run</text><text class="terminal-650700618-r2" x="573.4" y="361.6" textLength="12.2" clip-path="url(#terminal-650700618-line-14)">)</text><text class="terminal-650700618-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-650700618-line-14)"> -</text><text class="terminal-650700618-r1" x="0" y="386" textLength="488" clip-path="url(#terminal-650700618-line-15)">  -s, --signoff         Deprecated, use </text><text class="terminal-650700618-r3" x="488" y="386" textLength="207.4" clip-path="url(#terminal-650700618-line-15)">'cz commit -- -s'</text><text class="terminal-650700618-r1" x="695.4" y="386" textLength="97.6" clip-path="url(#terminal-650700618-line-15)"> instead</text><text class="terminal-650700618-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-650700618-line-15)"> -</text><text class="terminal-650700618-r1" x="0" y="410.4" textLength="902.8" clip-path="url(#terminal-650700618-line-16)">  -a, --all             Tell the command to automatically stage files that</text><text class="terminal-650700618-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-650700618-line-16)"> -</text><text class="terminal-650700618-r1" x="0" y="434.8" textLength="951.6" clip-path="url(#terminal-650700618-line-17)">                        have been modified and deleted, but new files you have</text><text class="terminal-650700618-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-650700618-line-17)"> -</text><text class="terminal-650700618-r1" x="0" y="459.2" textLength="732" clip-path="url(#terminal-650700618-line-18)">                        not told Git about are not affected.</text><text class="terminal-650700618-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-650700618-line-18)"> -</text><text class="terminal-650700618-r1" x="0" y="483.6" textLength="793" clip-path="url(#terminal-650700618-line-19)">  -e, --edit            edit the commit message before committing</text><text class="terminal-650700618-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-650700618-line-19)"> -</text><text class="terminal-650700618-r1" x="0" y="508" textLength="854" clip-path="url(#terminal-650700618-line-20)">  -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-650700618-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-650700618-line-20)"> -</text><text class="terminal-650700618-r1" x="0" y="532.4" textLength="732" clip-path="url(#terminal-650700618-line-21)">                        length limit of the commit message; </text><text class="terminal-650700618-r4" x="732" y="532.4" textLength="12.2" clip-path="url(#terminal-650700618-line-21)">0</text><text class="terminal-650700618-r1" x="744.2" y="532.4" textLength="158.6" clip-path="url(#terminal-650700618-line-21)"> for no limit</text><text class="terminal-650700618-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-650700618-line-21)"> -</text><text class="terminal-650700618-r1" x="0" y="556.8" textLength="671" clip-path="url(#terminal-650700618-line-22)">  --                    Positional arguments separator </text><text class="terminal-650700618-r2" x="671" y="556.8" textLength="12.2" clip-path="url(#terminal-650700618-line-22)">(</text><text class="terminal-650700618-r1" x="683.2" y="556.8" textLength="134.2" clip-path="url(#terminal-650700618-line-22)">recommended</text><text class="terminal-650700618-r2" x="817.4" y="556.8" textLength="12.2" clip-path="url(#terminal-650700618-line-22)">)</text><text class="terminal-650700618-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-650700618-line-22)"> -</text><text class="terminal-650700618-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-650700618-line-23)"> + <g class="terminal-1022884229-matrix"> + <text class="terminal-1022884229-r1" x="0" y="20" textLength="219.6" clip-path="url(#terminal-1022884229-line-0)">$ cz commit --help</text><text class="terminal-1022884229-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1022884229-line-0)"> +</text><text class="terminal-1022884229-r1" x="0" y="44.4" textLength="207.4" clip-path="url(#terminal-1022884229-line-1)">usage: cz commit </text><text class="terminal-1022884229-r2" x="207.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">[</text><text class="terminal-1022884229-r1" x="219.6" y="44.4" textLength="24.4" clip-path="url(#terminal-1022884229-line-1)">-h</text><text class="terminal-1022884229-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">]</text><text class="terminal-1022884229-r2" x="268.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">[</text><text class="terminal-1022884229-r1" x="280.6" y="44.4" textLength="85.4" clip-path="url(#terminal-1022884229-line-1)">--retry</text><text class="terminal-1022884229-r2" x="366" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">]</text><text class="terminal-1022884229-r2" x="390.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">[</text><text class="terminal-1022884229-r1" x="402.6" y="44.4" textLength="122" clip-path="url(#terminal-1022884229-line-1)">--no-retry</text><text class="terminal-1022884229-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">]</text><text class="terminal-1022884229-r2" x="549" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">[</text><text class="terminal-1022884229-r1" x="561.2" y="44.4" textLength="109.8" clip-path="url(#terminal-1022884229-line-1)">--dry-run</text><text class="terminal-1022884229-r2" x="671" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)">]</text><text class="terminal-1022884229-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-1)"> +</text><text class="terminal-1022884229-r2" x="207.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">[</text><text class="terminal-1022884229-r1" x="219.6" y="68.8" textLength="402.6" clip-path="url(#terminal-1022884229-line-2)">--write-message-to-file FILE_PATH</text><text class="terminal-1022884229-r2" x="622.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">]</text><text class="terminal-1022884229-r2" x="646.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">[</text><text class="terminal-1022884229-r1" x="658.8" y="68.8" textLength="24.4" clip-path="url(#terminal-1022884229-line-2)">-s</text><text class="terminal-1022884229-r2" x="683.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">]</text><text class="terminal-1022884229-r2" x="707.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">[</text><text class="terminal-1022884229-r1" x="719.8" y="68.8" textLength="24.4" clip-path="url(#terminal-1022884229-line-2)">-a</text><text class="terminal-1022884229-r2" x="744.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">]</text><text class="terminal-1022884229-r2" x="768.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">[</text><text class="terminal-1022884229-r1" x="780.8" y="68.8" textLength="24.4" clip-path="url(#terminal-1022884229-line-2)">-e</text><text class="terminal-1022884229-r2" x="805.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)">]</text><text class="terminal-1022884229-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-2)"> +</text><text class="terminal-1022884229-r2" x="207.4" y="93.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-3)">[</text><text class="terminal-1022884229-r1" x="219.6" y="93.2" textLength="280.6" clip-path="url(#terminal-1022884229-line-3)">-l MESSAGE_LENGTH_LIMIT</text><text class="terminal-1022884229-r2" x="500.2" y="93.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-3)">]</text><text class="terminal-1022884229-r2" x="524.6" y="93.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-3)">[</text><text class="terminal-1022884229-r1" x="536.8" y="93.2" textLength="24.4" clip-path="url(#terminal-1022884229-line-3)">--</text><text class="terminal-1022884229-r2" x="561.2" y="93.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-3)">]</text><text class="terminal-1022884229-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-3)"> +</text><text class="terminal-1022884229-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1022884229-line-4)"> +</text><text class="terminal-1022884229-r1" x="0" y="142" textLength="207.4" clip-path="url(#terminal-1022884229-line-5)">Create new commit</text><text class="terminal-1022884229-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1022884229-line-5)"> +</text><text class="terminal-1022884229-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-6)"> +</text><text class="terminal-1022884229-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-1022884229-line-7)">options:</text><text class="terminal-1022884229-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-7)"> +</text><text class="terminal-1022884229-r1" x="0" y="215.2" textLength="671" clip-path="url(#terminal-1022884229-line-8)">  -h, --help            show this help message and exit</text><text class="terminal-1022884229-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-8)"> +</text><text class="terminal-1022884229-r1" x="0" y="239.6" textLength="561.2" clip-path="url(#terminal-1022884229-line-9)">  --retry               Retry the last commit.</text><text class="terminal-1022884229-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1022884229-line-9)"> +</text><text class="terminal-1022884229-r1" x="0" y="264" textLength="939.4" clip-path="url(#terminal-1022884229-line-10)">  --no-retry            Skip retry if --retry or `retry_after_failure` is set</text><text class="terminal-1022884229-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1022884229-line-10)"> +</text><text class="terminal-1022884229-r1" x="0" y="288.4" textLength="390.4" clip-path="url(#terminal-1022884229-line-11)">                        to true.</text><text class="terminal-1022884229-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-11)"> +</text><text class="terminal-1022884229-r1" x="0" y="312.8" textLength="902.8" clip-path="url(#terminal-1022884229-line-12)">  --dry-run             Perform a dry run, without committing or modifying</text><text class="terminal-1022884229-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-12)"> +</text><text class="terminal-1022884229-r1" x="0" y="337.2" textLength="366" clip-path="url(#terminal-1022884229-line-13)">                        files.</text><text class="terminal-1022884229-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-13)"> +</text><text class="terminal-1022884229-r1" x="0" y="361.6" textLength="427" clip-path="url(#terminal-1022884229-line-14)">  --write-message-to-file FILE_PATH</text><text class="terminal-1022884229-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1022884229-line-14)"> +</text><text class="terminal-1022884229-r1" x="0" y="386" textLength="841.8" clip-path="url(#terminal-1022884229-line-15)">                        Write message to FILE_PATH before committing </text><text class="terminal-1022884229-r2" x="841.8" y="386" textLength="12.2" clip-path="url(#terminal-1022884229-line-15)">(</text><text class="terminal-1022884229-r1" x="854" y="386" textLength="73.2" clip-path="url(#terminal-1022884229-line-15)">can be</text><text class="terminal-1022884229-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1022884229-line-15)"> +</text><text class="terminal-1022884229-r1" x="0" y="410.4" textLength="524.6" clip-path="url(#terminal-1022884229-line-16)">                        used with --dry-run</text><text class="terminal-1022884229-r2" x="524.6" y="410.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-16)">)</text><text class="terminal-1022884229-r1" x="536.8" y="410.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-16)">.</text><text class="terminal-1022884229-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-16)"> +</text><text class="terminal-1022884229-r1" x="0" y="434.8" textLength="805.2" clip-path="url(#terminal-1022884229-line-17)">  -s, --signoff         Deprecated, use `cz commit -- -s` instead.</text><text class="terminal-1022884229-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-17)"> +</text><text class="terminal-1022884229-r1" x="0" y="459.2" textLength="939.4" clip-path="url(#terminal-1022884229-line-18)">  -a, --all             Automatically stage files that have been modified and</text><text class="terminal-1022884229-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-18)"> +</text><text class="terminal-1022884229-r1" x="0" y="483.6" textLength="951.6" clip-path="url(#terminal-1022884229-line-19)">                        deleted, but new files you have not told Git about are</text><text class="terminal-1022884229-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1022884229-line-19)"> +</text><text class="terminal-1022884229-r1" x="0" y="508" textLength="451.4" clip-path="url(#terminal-1022884229-line-20)">                        not affected.</text><text class="terminal-1022884229-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1022884229-line-20)"> +</text><text class="terminal-1022884229-r1" x="0" y="532.4" textLength="805.2" clip-path="url(#terminal-1022884229-line-21)">  -e, --edit            Edit the commit message before committing.</text><text class="terminal-1022884229-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-21)"> +</text><text class="terminal-1022884229-r1" x="0" y="556.8" textLength="854" clip-path="url(#terminal-1022884229-line-22)">  -l MESSAGE_LENGTH_LIMIT, --message-length-limit MESSAGE_LENGTH_LIMIT</text><text class="terminal-1022884229-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1022884229-line-22)"> +</text><text class="terminal-1022884229-r1" x="0" y="581.2" textLength="829.6" clip-path="url(#terminal-1022884229-line-23)">                        Set the length limit of the commit message; </text><text class="terminal-1022884229-r3" x="829.6" y="581.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-23)">0</text><text class="terminal-1022884229-r1" x="841.8" y="581.2" textLength="85.4" clip-path="url(#terminal-1022884229-line-23)"> for no</text><text class="terminal-1022884229-r1" x="976" y="581.2" textLength="12.2" clip-path="url(#terminal-1022884229-line-23)"> +</text><text class="terminal-1022884229-r1" x="0" y="605.6" textLength="366" clip-path="url(#terminal-1022884229-line-24)">                        limit.</text><text class="terminal-1022884229-r1" x="976" y="605.6" textLength="12.2" clip-path="url(#terminal-1022884229-line-24)"> +</text><text class="terminal-1022884229-r1" x="0" y="630" textLength="671" clip-path="url(#terminal-1022884229-line-25)">  --                    Positional arguments separator </text><text class="terminal-1022884229-r2" x="671" y="630" textLength="12.2" clip-path="url(#terminal-1022884229-line-25)">(</text><text class="terminal-1022884229-r1" x="683.2" y="630" textLength="134.2" clip-path="url(#terminal-1022884229-line-25)">recommended</text><text class="terminal-1022884229-r2" x="817.4" y="630" textLength="12.2" clip-path="url(#terminal-1022884229-line-25)">)</text><text class="terminal-1022884229-r1" x="829.6" y="630" textLength="12.2" clip-path="url(#terminal-1022884229-line-25)">.</text><text class="terminal-1022884229-r1" x="976" y="630" textLength="12.2" clip-path="url(#terminal-1022884229-line-25)"> +</text><text class="terminal-1022884229-r1" x="976" y="654.4" textLength="12.2" clip-path="url(#terminal-1022884229-line-26)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_example___help.svg b/docs/images/cli_help/cz_example___help.svg index 9fe4fd659a..6bf85336b8 100644 --- a/docs/images/cli_help/cz_example___help.svg +++ b/docs/images/cli_help/cz_example___help.svg @@ -19,46 +19,46 @@ font-weight: 700; } - .terminal-1643610534-matrix { + .terminal-1249345926-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1643610534-title { + .terminal-1249345926-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1643610534-r1 { fill: #c5c8c6 } -.terminal-1643610534-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-1249345926-r1 { fill: #c5c8c6 } +.terminal-1249345926-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-1643610534-clip-terminal"> + <clipPath id="terminal-1249345926-clip-terminal"> <rect x="0" y="0" width="975.0" height="194.2" /> </clipPath> - <clipPath id="terminal-1643610534-line-0"> + <clipPath id="terminal-1249345926-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1643610534-line-1"> +<clipPath id="terminal-1249345926-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1643610534-line-2"> +<clipPath id="terminal-1249345926-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1643610534-line-3"> +<clipPath id="terminal-1249345926-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1643610534-line-4"> +<clipPath id="terminal-1249345926-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1643610534-line-5"> +<clipPath id="terminal-1249345926-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1643610534-line-6"> +<clipPath id="terminal-1249345926-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> </defs> @@ -70,17 +70,17 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1643610534-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-1249345926-clip-terminal)"> - <g class="terminal-1643610534-matrix"> - <text class="terminal-1643610534-r1" x="0" y="20" textLength="231.8" clip-path="url(#terminal-1643610534-line-0)">$ cz example --help</text><text class="terminal-1643610534-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1643610534-line-0)"> -</text><text class="terminal-1643610534-r1" x="0" y="44.4" textLength="219.6" clip-path="url(#terminal-1643610534-line-1)">usage: cz example </text><text class="terminal-1643610534-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1643610534-line-1)">[</text><text class="terminal-1643610534-r1" x="231.8" y="44.4" textLength="24.4" clip-path="url(#terminal-1643610534-line-1)">-h</text><text class="terminal-1643610534-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1643610534-line-1)">]</text><text class="terminal-1643610534-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1643610534-line-1)"> -</text><text class="terminal-1643610534-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1643610534-line-2)"> -</text><text class="terminal-1643610534-r1" x="0" y="93.2" textLength="231.8" clip-path="url(#terminal-1643610534-line-3)">show commit example</text><text class="terminal-1643610534-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1643610534-line-3)"> -</text><text class="terminal-1643610534-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1643610534-line-4)"> -</text><text class="terminal-1643610534-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-1643610534-line-5)">options:</text><text class="terminal-1643610534-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1643610534-line-5)"> -</text><text class="terminal-1643610534-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-1643610534-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-1643610534-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1643610534-line-6)"> -</text><text class="terminal-1643610534-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1643610534-line-7)"> + <g class="terminal-1249345926-matrix"> + <text class="terminal-1249345926-r1" x="0" y="20" textLength="231.8" clip-path="url(#terminal-1249345926-line-0)">$ cz example --help</text><text class="terminal-1249345926-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1249345926-line-0)"> +</text><text class="terminal-1249345926-r1" x="0" y="44.4" textLength="219.6" clip-path="url(#terminal-1249345926-line-1)">usage: cz example </text><text class="terminal-1249345926-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1249345926-line-1)">[</text><text class="terminal-1249345926-r1" x="231.8" y="44.4" textLength="24.4" clip-path="url(#terminal-1249345926-line-1)">-h</text><text class="terminal-1249345926-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1249345926-line-1)">]</text><text class="terminal-1249345926-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1249345926-line-1)"> +</text><text class="terminal-1249345926-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1249345926-line-2)"> +</text><text class="terminal-1249345926-r1" x="0" y="93.2" textLength="231.8" clip-path="url(#terminal-1249345926-line-3)">Show commit example</text><text class="terminal-1249345926-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1249345926-line-3)"> +</text><text class="terminal-1249345926-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1249345926-line-4)"> +</text><text class="terminal-1249345926-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-1249345926-line-5)">options:</text><text class="terminal-1249345926-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1249345926-line-5)"> +</text><text class="terminal-1249345926-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-1249345926-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-1249345926-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1249345926-line-6)"> +</text><text class="terminal-1249345926-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1249345926-line-7)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_info___help.svg b/docs/images/cli_help/cz_info___help.svg index b8827e34c2..5ab81ec051 100644 --- a/docs/images/cli_help/cz_info___help.svg +++ b/docs/images/cli_help/cz_info___help.svg @@ -19,46 +19,46 @@ font-weight: 700; } - .terminal-4196041424-matrix { + .terminal-3780805296-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-4196041424-title { + .terminal-3780805296-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-4196041424-r1 { fill: #c5c8c6 } -.terminal-4196041424-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-3780805296-r1 { fill: #c5c8c6 } +.terminal-3780805296-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-4196041424-clip-terminal"> + <clipPath id="terminal-3780805296-clip-terminal"> <rect x="0" y="0" width="975.0" height="194.2" /> </clipPath> - <clipPath id="terminal-4196041424-line-0"> + <clipPath id="terminal-3780805296-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-4196041424-line-1"> +<clipPath id="terminal-3780805296-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-4196041424-line-2"> +<clipPath id="terminal-3780805296-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-4196041424-line-3"> +<clipPath id="terminal-3780805296-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-4196041424-line-4"> +<clipPath id="terminal-3780805296-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-4196041424-line-5"> +<clipPath id="terminal-3780805296-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-4196041424-line-6"> +<clipPath id="terminal-3780805296-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> </defs> @@ -70,17 +70,17 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-4196041424-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-3780805296-clip-terminal)"> - <g class="terminal-4196041424-matrix"> - <text class="terminal-4196041424-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-4196041424-line-0)">$ cz info --help</text><text class="terminal-4196041424-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-4196041424-line-0)"> -</text><text class="terminal-4196041424-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-4196041424-line-1)">usage: cz info </text><text class="terminal-4196041424-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-4196041424-line-1)">[</text><text class="terminal-4196041424-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-4196041424-line-1)">-h</text><text class="terminal-4196041424-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-4196041424-line-1)">]</text><text class="terminal-4196041424-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-4196041424-line-1)"> -</text><text class="terminal-4196041424-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-4196041424-line-2)"> -</text><text class="terminal-4196041424-r1" x="0" y="93.2" textLength="353.8" clip-path="url(#terminal-4196041424-line-3)">show information about the cz</text><text class="terminal-4196041424-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-4196041424-line-3)"> -</text><text class="terminal-4196041424-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-4196041424-line-4)"> -</text><text class="terminal-4196041424-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-4196041424-line-5)">options:</text><text class="terminal-4196041424-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-4196041424-line-5)"> -</text><text class="terminal-4196041424-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-4196041424-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-4196041424-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-4196041424-line-6)"> -</text><text class="terminal-4196041424-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-4196041424-line-7)"> + <g class="terminal-3780805296-matrix"> + <text class="terminal-3780805296-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-3780805296-line-0)">$ cz info --help</text><text class="terminal-3780805296-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-3780805296-line-0)"> +</text><text class="terminal-3780805296-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-3780805296-line-1)">usage: cz info </text><text class="terminal-3780805296-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-3780805296-line-1)">[</text><text class="terminal-3780805296-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-3780805296-line-1)">-h</text><text class="terminal-3780805296-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-3780805296-line-1)">]</text><text class="terminal-3780805296-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-3780805296-line-1)"> +</text><text class="terminal-3780805296-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-3780805296-line-2)"> +</text><text class="terminal-3780805296-r1" x="0" y="93.2" textLength="353.8" clip-path="url(#terminal-3780805296-line-3)">Show information about the cz</text><text class="terminal-3780805296-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-3780805296-line-3)"> +</text><text class="terminal-3780805296-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-3780805296-line-4)"> +</text><text class="terminal-3780805296-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-3780805296-line-5)">options:</text><text class="terminal-3780805296-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-3780805296-line-5)"> +</text><text class="terminal-3780805296-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-3780805296-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-3780805296-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-3780805296-line-6)"> +</text><text class="terminal-3780805296-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-3780805296-line-7)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_init___help.svg b/docs/images/cli_help/cz_init___help.svg index 41a950ebdb..709b779189 100644 --- a/docs/images/cli_help/cz_init___help.svg +++ b/docs/images/cli_help/cz_init___help.svg @@ -19,46 +19,46 @@ font-weight: 700; } - .terminal-1838121835-matrix { + .terminal-3508504009-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1838121835-title { + .terminal-3508504009-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1838121835-r1 { fill: #c5c8c6 } -.terminal-1838121835-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-3508504009-r1 { fill: #c5c8c6 } +.terminal-3508504009-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-1838121835-clip-terminal"> + <clipPath id="terminal-3508504009-clip-terminal"> <rect x="0" y="0" width="975.0" height="194.2" /> </clipPath> - <clipPath id="terminal-1838121835-line-0"> + <clipPath id="terminal-3508504009-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1838121835-line-1"> +<clipPath id="terminal-3508504009-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1838121835-line-2"> +<clipPath id="terminal-3508504009-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1838121835-line-3"> +<clipPath id="terminal-3508504009-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1838121835-line-4"> +<clipPath id="terminal-3508504009-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1838121835-line-5"> +<clipPath id="terminal-3508504009-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1838121835-line-6"> +<clipPath id="terminal-3508504009-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> </defs> @@ -70,17 +70,17 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1838121835-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-3508504009-clip-terminal)"> - <g class="terminal-1838121835-matrix"> - <text class="terminal-1838121835-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-1838121835-line-0)">$ cz init --help</text><text class="terminal-1838121835-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1838121835-line-0)"> -</text><text class="terminal-1838121835-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-1838121835-line-1)">usage: cz init </text><text class="terminal-1838121835-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-1838121835-line-1)">[</text><text class="terminal-1838121835-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-1838121835-line-1)">-h</text><text class="terminal-1838121835-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-1838121835-line-1)">]</text><text class="terminal-1838121835-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1838121835-line-1)"> -</text><text class="terminal-1838121835-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1838121835-line-2)"> -</text><text class="terminal-1838121835-r1" x="0" y="93.2" textLength="353.8" clip-path="url(#terminal-1838121835-line-3)">init commitizen configuration</text><text class="terminal-1838121835-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1838121835-line-3)"> -</text><text class="terminal-1838121835-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1838121835-line-4)"> -</text><text class="terminal-1838121835-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-1838121835-line-5)">options:</text><text class="terminal-1838121835-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1838121835-line-5)"> -</text><text class="terminal-1838121835-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-1838121835-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-1838121835-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1838121835-line-6)"> -</text><text class="terminal-1838121835-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1838121835-line-7)"> + <g class="terminal-3508504009-matrix"> + <text class="terminal-3508504009-r1" x="0" y="20" textLength="195.2" clip-path="url(#terminal-3508504009-line-0)">$ cz init --help</text><text class="terminal-3508504009-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-3508504009-line-0)"> +</text><text class="terminal-3508504009-r1" x="0" y="44.4" textLength="183" clip-path="url(#terminal-3508504009-line-1)">usage: cz init </text><text class="terminal-3508504009-r2" x="183" y="44.4" textLength="12.2" clip-path="url(#terminal-3508504009-line-1)">[</text><text class="terminal-3508504009-r1" x="195.2" y="44.4" textLength="24.4" clip-path="url(#terminal-3508504009-line-1)">-h</text><text class="terminal-3508504009-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-3508504009-line-1)">]</text><text class="terminal-3508504009-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-3508504009-line-1)"> +</text><text class="terminal-3508504009-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-3508504009-line-2)"> +</text><text class="terminal-3508504009-r1" x="0" y="93.2" textLength="427" clip-path="url(#terminal-3508504009-line-3)">Initialize commitizen configuration</text><text class="terminal-3508504009-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-3508504009-line-3)"> +</text><text class="terminal-3508504009-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-3508504009-line-4)"> +</text><text class="terminal-3508504009-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-3508504009-line-5)">options:</text><text class="terminal-3508504009-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-3508504009-line-5)"> +</text><text class="terminal-3508504009-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-3508504009-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-3508504009-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-3508504009-line-6)"> +</text><text class="terminal-3508504009-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-3508504009-line-7)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_ls___help.svg b/docs/images/cli_help/cz_ls___help.svg index 3ec3532ef1..fc6e0bc7e7 100644 --- a/docs/images/cli_help/cz_ls___help.svg +++ b/docs/images/cli_help/cz_ls___help.svg @@ -19,46 +19,46 @@ font-weight: 700; } - .terminal-589791338-matrix { + .terminal-4097343530-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-589791338-title { + .terminal-4097343530-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-589791338-r1 { fill: #c5c8c6 } -.terminal-589791338-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-4097343530-r1 { fill: #c5c8c6 } +.terminal-4097343530-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-589791338-clip-terminal"> + <clipPath id="terminal-4097343530-clip-terminal"> <rect x="0" y="0" width="975.0" height="194.2" /> </clipPath> - <clipPath id="terminal-589791338-line-0"> + <clipPath id="terminal-4097343530-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-589791338-line-1"> +<clipPath id="terminal-4097343530-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-589791338-line-2"> +<clipPath id="terminal-4097343530-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-589791338-line-3"> +<clipPath id="terminal-4097343530-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-589791338-line-4"> +<clipPath id="terminal-4097343530-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-589791338-line-5"> +<clipPath id="terminal-4097343530-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-589791338-line-6"> +<clipPath id="terminal-4097343530-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> </defs> @@ -70,17 +70,17 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-589791338-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-4097343530-clip-terminal)"> - <g class="terminal-589791338-matrix"> - <text class="terminal-589791338-r1" x="0" y="20" textLength="170.8" clip-path="url(#terminal-589791338-line-0)">$ cz ls --help</text><text class="terminal-589791338-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-589791338-line-0)"> -</text><text class="terminal-589791338-r1" x="0" y="44.4" textLength="158.6" clip-path="url(#terminal-589791338-line-1)">usage: cz ls </text><text class="terminal-589791338-r2" x="158.6" y="44.4" textLength="12.2" clip-path="url(#terminal-589791338-line-1)">[</text><text class="terminal-589791338-r1" x="170.8" y="44.4" textLength="24.4" clip-path="url(#terminal-589791338-line-1)">-h</text><text class="terminal-589791338-r2" x="195.2" y="44.4" textLength="12.2" clip-path="url(#terminal-589791338-line-1)">]</text><text class="terminal-589791338-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-589791338-line-1)"> -</text><text class="terminal-589791338-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-589791338-line-2)"> -</text><text class="terminal-589791338-r1" x="0" y="93.2" textLength="317.2" clip-path="url(#terminal-589791338-line-3)">show available commitizens</text><text class="terminal-589791338-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-589791338-line-3)"> -</text><text class="terminal-589791338-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-589791338-line-4)"> -</text><text class="terminal-589791338-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-589791338-line-5)">options:</text><text class="terminal-589791338-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-589791338-line-5)"> -</text><text class="terminal-589791338-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-589791338-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-589791338-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-589791338-line-6)"> -</text><text class="terminal-589791338-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-589791338-line-7)"> + <g class="terminal-4097343530-matrix"> + <text class="terminal-4097343530-r1" x="0" y="20" textLength="170.8" clip-path="url(#terminal-4097343530-line-0)">$ cz ls --help</text><text class="terminal-4097343530-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-4097343530-line-0)"> +</text><text class="terminal-4097343530-r1" x="0" y="44.4" textLength="158.6" clip-path="url(#terminal-4097343530-line-1)">usage: cz ls </text><text class="terminal-4097343530-r2" x="158.6" y="44.4" textLength="12.2" clip-path="url(#terminal-4097343530-line-1)">[</text><text class="terminal-4097343530-r1" x="170.8" y="44.4" textLength="24.4" clip-path="url(#terminal-4097343530-line-1)">-h</text><text class="terminal-4097343530-r2" x="195.2" y="44.4" textLength="12.2" clip-path="url(#terminal-4097343530-line-1)">]</text><text class="terminal-4097343530-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-4097343530-line-1)"> +</text><text class="terminal-4097343530-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-4097343530-line-2)"> +</text><text class="terminal-4097343530-r1" x="0" y="93.2" textLength="317.2" clip-path="url(#terminal-4097343530-line-3)">Show available Commitizens</text><text class="terminal-4097343530-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-4097343530-line-3)"> +</text><text class="terminal-4097343530-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-4097343530-line-4)"> +</text><text class="terminal-4097343530-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-4097343530-line-5)">options:</text><text class="terminal-4097343530-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-4097343530-line-5)"> +</text><text class="terminal-4097343530-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-4097343530-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-4097343530-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-4097343530-line-6)"> +</text><text class="terminal-4097343530-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-4097343530-line-7)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_schema___help.svg b/docs/images/cli_help/cz_schema___help.svg index afe8982e9a..110569a022 100644 --- a/docs/images/cli_help/cz_schema___help.svg +++ b/docs/images/cli_help/cz_schema___help.svg @@ -19,46 +19,46 @@ font-weight: 700; } - .terminal-1497071669-matrix { + .terminal-1104904213-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1497071669-title { + .terminal-1104904213-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1497071669-r1 { fill: #c5c8c6 } -.terminal-1497071669-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-1104904213-r1 { fill: #c5c8c6 } +.terminal-1104904213-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-1497071669-clip-terminal"> + <clipPath id="terminal-1104904213-clip-terminal"> <rect x="0" y="0" width="975.0" height="194.2" /> </clipPath> - <clipPath id="terminal-1497071669-line-0"> + <clipPath id="terminal-1104904213-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1497071669-line-1"> +<clipPath id="terminal-1104904213-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1497071669-line-2"> +<clipPath id="terminal-1104904213-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1497071669-line-3"> +<clipPath id="terminal-1104904213-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1497071669-line-4"> +<clipPath id="terminal-1104904213-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1497071669-line-5"> +<clipPath id="terminal-1104904213-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-1497071669-line-6"> +<clipPath id="terminal-1104904213-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> </defs> @@ -70,17 +70,17 @@ <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-1497071669-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-1104904213-clip-terminal)"> - <g class="terminal-1497071669-matrix"> - <text class="terminal-1497071669-r1" x="0" y="20" textLength="219.6" clip-path="url(#terminal-1497071669-line-0)">$ cz schema --help</text><text class="terminal-1497071669-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1497071669-line-0)"> -</text><text class="terminal-1497071669-r1" x="0" y="44.4" textLength="207.4" clip-path="url(#terminal-1497071669-line-1)">usage: cz schema </text><text class="terminal-1497071669-r2" x="207.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1497071669-line-1)">[</text><text class="terminal-1497071669-r1" x="219.6" y="44.4" textLength="24.4" clip-path="url(#terminal-1497071669-line-1)">-h</text><text class="terminal-1497071669-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-1497071669-line-1)">]</text><text class="terminal-1497071669-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1497071669-line-1)"> -</text><text class="terminal-1497071669-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1497071669-line-2)"> -</text><text class="terminal-1497071669-r1" x="0" y="93.2" textLength="219.6" clip-path="url(#terminal-1497071669-line-3)">show commit schema</text><text class="terminal-1497071669-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1497071669-line-3)"> -</text><text class="terminal-1497071669-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1497071669-line-4)"> -</text><text class="terminal-1497071669-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-1497071669-line-5)">options:</text><text class="terminal-1497071669-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1497071669-line-5)"> -</text><text class="terminal-1497071669-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-1497071669-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-1497071669-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1497071669-line-6)"> -</text><text class="terminal-1497071669-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1497071669-line-7)"> + <g class="terminal-1104904213-matrix"> + <text class="terminal-1104904213-r1" x="0" y="20" textLength="219.6" clip-path="url(#terminal-1104904213-line-0)">$ cz schema --help</text><text class="terminal-1104904213-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1104904213-line-0)"> +</text><text class="terminal-1104904213-r1" x="0" y="44.4" textLength="207.4" clip-path="url(#terminal-1104904213-line-1)">usage: cz schema </text><text class="terminal-1104904213-r2" x="207.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1104904213-line-1)">[</text><text class="terminal-1104904213-r1" x="219.6" y="44.4" textLength="24.4" clip-path="url(#terminal-1104904213-line-1)">-h</text><text class="terminal-1104904213-r2" x="244" y="44.4" textLength="12.2" clip-path="url(#terminal-1104904213-line-1)">]</text><text class="terminal-1104904213-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1104904213-line-1)"> +</text><text class="terminal-1104904213-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1104904213-line-2)"> +</text><text class="terminal-1104904213-r1" x="0" y="93.2" textLength="219.6" clip-path="url(#terminal-1104904213-line-3)">Show commit schema</text><text class="terminal-1104904213-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1104904213-line-3)"> +</text><text class="terminal-1104904213-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1104904213-line-4)"> +</text><text class="terminal-1104904213-r1" x="0" y="142" textLength="97.6" clip-path="url(#terminal-1104904213-line-5)">options:</text><text class="terminal-1104904213-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1104904213-line-5)"> +</text><text class="terminal-1104904213-r1" x="0" y="166.4" textLength="549" clip-path="url(#terminal-1104904213-line-6)">  -h, --help  show this help message and exit</text><text class="terminal-1104904213-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1104904213-line-6)"> +</text><text class="terminal-1104904213-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1104904213-line-7)"> </text> </g> </g> diff --git a/docs/images/cli_help/cz_version___help.svg b/docs/images/cli_help/cz_version___help.svg index a8e0bd844e..0c45576bc5 100644 --- a/docs/images/cli_help/cz_version___help.svg +++ b/docs/images/cli_help/cz_version___help.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 994 489.2" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 994 538.0" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -19,108 +19,116 @@ font-weight: 700; } - .terminal-752487608-matrix { + .terminal-3401796841-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-752487608-title { + .terminal-3401796841-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-752487608-r1 { fill: #c5c8c6 } -.terminal-752487608-r2 { fill: #c5c8c6;font-weight: bold } + .terminal-3401796841-r1 { fill: #c5c8c6 } +.terminal-3401796841-r2 { fill: #c5c8c6;font-weight: bold } </style> <defs> - <clipPath id="terminal-752487608-clip-terminal"> - <rect x="0" y="0" width="975.0" height="438.2" /> + <clipPath id="terminal-3401796841-clip-terminal"> + <rect x="0" y="0" width="975.0" height="487.0" /> </clipPath> - <clipPath id="terminal-752487608-line-0"> + <clipPath id="terminal-3401796841-line-0"> <rect x="0" y="1.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-1"> +<clipPath id="terminal-3401796841-line-1"> <rect x="0" y="25.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-2"> +<clipPath id="terminal-3401796841-line-2"> <rect x="0" y="50.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-3"> +<clipPath id="terminal-3401796841-line-3"> <rect x="0" y="74.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-4"> +<clipPath id="terminal-3401796841-line-4"> <rect x="0" y="99.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-5"> +<clipPath id="terminal-3401796841-line-5"> <rect x="0" y="123.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-6"> +<clipPath id="terminal-3401796841-line-6"> <rect x="0" y="147.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-7"> +<clipPath id="terminal-3401796841-line-7"> <rect x="0" y="172.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-8"> +<clipPath id="terminal-3401796841-line-8"> <rect x="0" y="196.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-9"> +<clipPath id="terminal-3401796841-line-9"> <rect x="0" y="221.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-10"> +<clipPath id="terminal-3401796841-line-10"> <rect x="0" y="245.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-11"> +<clipPath id="terminal-3401796841-line-11"> <rect x="0" y="269.9" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-12"> +<clipPath id="terminal-3401796841-line-12"> <rect x="0" y="294.3" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-13"> +<clipPath id="terminal-3401796841-line-13"> <rect x="0" y="318.7" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-14"> +<clipPath id="terminal-3401796841-line-14"> <rect x="0" y="343.1" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-15"> +<clipPath id="terminal-3401796841-line-15"> <rect x="0" y="367.5" width="976" height="24.65"/> </clipPath> -<clipPath id="terminal-752487608-line-16"> +<clipPath id="terminal-3401796841-line-16"> <rect x="0" y="391.9" width="976" height="24.65"/> </clipPath> +<clipPath id="terminal-3401796841-line-17"> + <rect x="0" y="416.3" width="976" height="24.65"/> + </clipPath> +<clipPath id="terminal-3401796841-line-18"> + <rect x="0" y="440.7" width="976" height="24.65"/> + </clipPath> </defs> - <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="487.2" rx="8"/> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="536" rx="8"/> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="44" cy="0" r="7" fill="#28c840"/> </g> - <g transform="translate(9, 41)" clip-path="url(#terminal-752487608-clip-terminal)"> + <g transform="translate(9, 41)" clip-path="url(#terminal-3401796841-clip-terminal)"> - <g class="terminal-752487608-matrix"> - <text class="terminal-752487608-r1" x="0" y="20" textLength="231.8" clip-path="url(#terminal-752487608-line-0)">$ cz version --help</text><text class="terminal-752487608-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-752487608-line-0)"> -</text><text class="terminal-752487608-r1" x="0" y="44.4" textLength="219.6" clip-path="url(#terminal-752487608-line-1)">usage: cz version </text><text class="terminal-752487608-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">[</text><text class="terminal-752487608-r1" x="231.8" y="44.4" textLength="24.4" clip-path="url(#terminal-752487608-line-1)">-h</text><text class="terminal-752487608-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">]</text><text class="terminal-752487608-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">[</text><text class="terminal-752487608-r1" x="292.8" y="44.4" textLength="207.4" clip-path="url(#terminal-752487608-line-1)">-r | -p | -c | -v</text><text class="terminal-752487608-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">]</text><text class="terminal-752487608-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">[</text><text class="terminal-752487608-r1" x="536.8" y="44.4" textLength="207.4" clip-path="url(#terminal-752487608-line-1)">--major | --minor</text><text class="terminal-752487608-r2" x="744.2" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)">]</text><text class="terminal-752487608-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-752487608-line-1)"> -</text><text class="terminal-752487608-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-752487608-line-2)"> -</text><text class="terminal-752487608-r1" x="0" y="93.2" textLength="817.4" clip-path="url(#terminal-752487608-line-3)">get the version of the installed commitizen or the current project </text><text class="terminal-752487608-r2" x="817.4" y="93.2" textLength="12.2" clip-path="url(#terminal-752487608-line-3)">(</text><text class="terminal-752487608-r1" x="829.6" y="93.2" textLength="97.6" clip-path="url(#terminal-752487608-line-3)">default:</text><text class="terminal-752487608-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-752487608-line-3)"> -</text><text class="terminal-752487608-r1" x="0" y="117.6" textLength="244" clip-path="url(#terminal-752487608-line-4)">installed commitizen</text><text class="terminal-752487608-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-752487608-line-4)">)</text><text class="terminal-752487608-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-752487608-line-4)"> -</text><text class="terminal-752487608-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-752487608-line-5)"> -</text><text class="terminal-752487608-r1" x="0" y="166.4" textLength="97.6" clip-path="url(#terminal-752487608-line-6)">options:</text><text class="terminal-752487608-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-752487608-line-6)"> -</text><text class="terminal-752487608-r1" x="0" y="190.8" textLength="622.2" clip-path="url(#terminal-752487608-line-7)">  -h, --help        show this help message and exit</text><text class="terminal-752487608-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-752487608-line-7)"> -</text><text class="terminal-752487608-r1" x="0" y="215.2" textLength="744.2" clip-path="url(#terminal-752487608-line-8)">  -r, --report      get system information for reporting bugs</text><text class="terminal-752487608-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-752487608-line-8)"> -</text><text class="terminal-752487608-r1" x="0" y="239.6" textLength="707.6" clip-path="url(#terminal-752487608-line-9)">  -p, --project     get the version of the current project</text><text class="terminal-752487608-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-752487608-line-9)"> -</text><text class="terminal-752487608-r1" x="0" y="264" textLength="768.6" clip-path="url(#terminal-752487608-line-10)">  -c, --commitizen  get the version of the installed commitizen</text><text class="terminal-752487608-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-752487608-line-10)"> -</text><text class="terminal-752487608-r1" x="0" y="288.4" textLength="927.2" clip-path="url(#terminal-752487608-line-11)">  -v, --verbose     get the version of both the installed commitizen and the</text><text class="terminal-752487608-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-752487608-line-11)"> -</text><text class="terminal-752487608-r1" x="0" y="312.8" textLength="427" clip-path="url(#terminal-752487608-line-12)">                    current project</text><text class="terminal-752487608-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-752487608-line-12)"> -</text><text class="terminal-752487608-r1" x="0" y="337.2" textLength="951.6" clip-path="url(#terminal-752487608-line-13)">  --major           get just the major version. Need to be used with --project</text><text class="terminal-752487608-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-752487608-line-13)"> -</text><text class="terminal-752487608-r1" x="0" y="361.6" textLength="402.6" clip-path="url(#terminal-752487608-line-14)">                    or --verbose.</text><text class="terminal-752487608-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-752487608-line-14)"> -</text><text class="terminal-752487608-r1" x="0" y="386" textLength="951.6" clip-path="url(#terminal-752487608-line-15)">  --minor           get just the minor version. Need to be used with --project</text><text class="terminal-752487608-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-752487608-line-15)"> -</text><text class="terminal-752487608-r1" x="0" y="410.4" textLength="402.6" clip-path="url(#terminal-752487608-line-16)">                    or --verbose.</text><text class="terminal-752487608-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-752487608-line-16)"> -</text><text class="terminal-752487608-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-752487608-line-17)"> + <g class="terminal-3401796841-matrix"> + <text class="terminal-3401796841-r1" x="0" y="20" textLength="231.8" clip-path="url(#terminal-3401796841-line-0)">$ cz version --help</text><text class="terminal-3401796841-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-3401796841-line-0)"> +</text><text class="terminal-3401796841-r1" x="0" y="44.4" textLength="219.6" clip-path="url(#terminal-3401796841-line-1)">usage: cz version </text><text class="terminal-3401796841-r2" x="219.6" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)">[</text><text class="terminal-3401796841-r1" x="231.8" y="44.4" textLength="24.4" clip-path="url(#terminal-3401796841-line-1)">-h</text><text class="terminal-3401796841-r2" x="256.2" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)">]</text><text class="terminal-3401796841-r2" x="280.6" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)">[</text><text class="terminal-3401796841-r1" x="292.8" y="44.4" textLength="207.4" clip-path="url(#terminal-3401796841-line-1)">-r | -p | -c | -v</text><text class="terminal-3401796841-r2" x="500.2" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)">]</text><text class="terminal-3401796841-r2" x="524.6" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)">[</text><text class="terminal-3401796841-r1" x="536.8" y="44.4" textLength="305" clip-path="url(#terminal-3401796841-line-1)">--major | --minor | --tag</text><text class="terminal-3401796841-r2" x="841.8" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)">]</text><text class="terminal-3401796841-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-1)"> +</text><text class="terminal-3401796841-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-3401796841-line-2)"> +</text><text class="terminal-3401796841-r1" x="0" y="93.2" textLength="817.4" clip-path="url(#terminal-3401796841-line-3)">Get the version of the installed commitizen or the current project </text><text class="terminal-3401796841-r2" x="817.4" y="93.2" textLength="12.2" clip-path="url(#terminal-3401796841-line-3)">(</text><text class="terminal-3401796841-r1" x="829.6" y="93.2" textLength="97.6" clip-path="url(#terminal-3401796841-line-3)">default:</text><text class="terminal-3401796841-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-3401796841-line-3)"> +</text><text class="terminal-3401796841-r1" x="0" y="117.6" textLength="244" clip-path="url(#terminal-3401796841-line-4)">installed commitizen</text><text class="terminal-3401796841-r2" x="244" y="117.6" textLength="12.2" clip-path="url(#terminal-3401796841-line-4)">)</text><text class="terminal-3401796841-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-3401796841-line-4)"> +</text><text class="terminal-3401796841-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-3401796841-line-5)"> +</text><text class="terminal-3401796841-r1" x="0" y="166.4" textLength="97.6" clip-path="url(#terminal-3401796841-line-6)">options:</text><text class="terminal-3401796841-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-6)"> +</text><text class="terminal-3401796841-r1" x="0" y="190.8" textLength="622.2" clip-path="url(#terminal-3401796841-line-7)">  -h, --help        show this help message and exit</text><text class="terminal-3401796841-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-3401796841-line-7)"> +</text><text class="terminal-3401796841-r1" x="0" y="215.2" textLength="841.8" clip-path="url(#terminal-3401796841-line-8)">  -r, --report      Output the system information for reporting bugs.</text><text class="terminal-3401796841-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-3401796841-line-8)"> +</text><text class="terminal-3401796841-r1" x="0" y="239.6" textLength="756.4" clip-path="url(#terminal-3401796841-line-9)">  -p, --project     Output the version of the current project.</text><text class="terminal-3401796841-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-3401796841-line-9)"> +</text><text class="terminal-3401796841-r1" x="0" y="264" textLength="817.4" clip-path="url(#terminal-3401796841-line-10)">  -c, --commitizen  Output the version of the installed commitizen.</text><text class="terminal-3401796841-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-3401796841-line-10)"> +</text><text class="terminal-3401796841-r1" x="0" y="288.4" textLength="915" clip-path="url(#terminal-3401796841-line-11)">  -v, --verbose     Output the version of both the installed commitizen and</text><text class="terminal-3401796841-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-11)"> +</text><text class="terminal-3401796841-r1" x="0" y="312.8" textLength="488" clip-path="url(#terminal-3401796841-line-12)">                    the current project.</text><text class="terminal-3401796841-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-3401796841-line-12)"> +</text><text class="terminal-3401796841-r1" x="0" y="337.2" textLength="951.6" clip-path="url(#terminal-3401796841-line-13)">  --major           Output just the major version. Must be used with --project</text><text class="terminal-3401796841-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-3401796841-line-13)"> +</text><text class="terminal-3401796841-r1" x="0" y="361.6" textLength="402.6" clip-path="url(#terminal-3401796841-line-14)">                    or --verbose.</text><text class="terminal-3401796841-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-3401796841-line-14)"> +</text><text class="terminal-3401796841-r1" x="0" y="386" textLength="951.6" clip-path="url(#terminal-3401796841-line-15)">  --minor           Output just the minor version. Must be used with --project</text><text class="terminal-3401796841-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-3401796841-line-15)"> +</text><text class="terminal-3401796841-r1" x="0" y="410.4" textLength="402.6" clip-path="url(#terminal-3401796841-line-16)">                    or --verbose.</text><text class="terminal-3401796841-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-3401796841-line-16)"> +</text><text class="terminal-3401796841-r1" x="0" y="434.8" textLength="890.6" clip-path="url(#terminal-3401796841-line-17)">  --tag             get the version with tag prefix. Need to be used with</text><text class="terminal-3401796841-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-3401796841-line-17)"> +</text><text class="terminal-3401796841-r1" x="0" y="459.2" textLength="524.6" clip-path="url(#terminal-3401796841-line-18)">                    --project or --verbose.</text><text class="terminal-3401796841-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-3401796841-line-18)"> +</text><text class="terminal-3401796841-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-3401796841-line-19)"> </text> </g> </g> From bc1542cf234d48b56547c782205c4d6f9c0db11a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Feb 2026 11:00:47 +0000 Subject: [PATCH 221/221] =?UTF-8?q?bump:=20version=204.12.1=20=E2=86=92=20?= =?UTF-8?q?4.13.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 21 +++++++++++++++++++++ commitizen/__version__.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2a7cc5672b..0f69f0a42e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.12.1 # automatically updated by Commitizen + rev: v4.13.0 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c7b7598c8..db91c63b39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +## v4.13.0 (2026-02-01) + +### Feat + +- **bump**: add --version-files-only and deprecate --files-only (#1802) +- **version**: add --tag tag to version command (#1819) +- **cli**: add description when choosing a commit rule (#1825) +- **tags**: enable version schemes with less than 3 components (#1705) + +### Fix + +- **config**: include pyproject.toml in multi config file warning (#1803) +- add pytest ruff rule PT and fix missing deprecation warning (#1826) +- **message_length_limit**: align the behavior of message_length_limit (#1813) +- **cli**: capitalize the first characters of help texts and fix minor grammar errors + +### Refactor + +- replace hard-coded string "cz_conventional_commits" with DEFAULT_SETTINGS (#1830) +- **bump**: fix unbounded variable type issue + ## v4.12.1 (2026-01-22) ### Fix diff --git a/commitizen/__version__.py b/commitizen/__version__.py index 33111828cc..5b886240e3 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.12.1" +__version__ = "4.13.0" diff --git a/pyproject.toml b/pyproject.toml index 38cf5da23c..ad639ba9bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.12.1" +version = "4.13.0" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/uv.lock b/uv.lock index 75732c7ac0..69e2f8e9e4 100644 --- a/uv.lock +++ b/uv.lock @@ -195,7 +195,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.12.1" +version = "4.13.0" source = { editable = "." } dependencies = [ { name = "argcomplete" },