diff --git a/.github/workflows/bumpversion.yml b/.github/workflows/bumpversion.yml index ba48d677e..d74ed624a 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 eb52dc46a..0102856cb 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 8c315b632..3ca67da81 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: @@ -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@v7 with: token: ${{secrets.PERSONAL_ACCESS_TOKEN}} formula: commitizen diff --git a/.github/workflows/label_pr.yml b/.github/workflows/label_pr.yml index c1a3df2c7..8e2d674f2 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 7a574c9e0..4e4738ac9 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -6,11 +6,11 @@ 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: - - 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 e70690a1a..de078815f 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 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf207ea60..f70fbf2f1 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 f8bca478b..7ee748085 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 897e6be2f..4e499ea83 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.10.0" +__version__ = "4.10.1" diff --git a/commitizen/bump.py b/commitizen/bump.py index 6672c5f50..cb572d361 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,13 +59,13 @@ def find_increment( if increment == MAJOR: break - return cast(Increment, increment) + return cast("Increment", 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 +80,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/changelog.py b/commitizen/changelog.py index bdf11326b..dfc415772 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 9a5eea7ab..e4eb5e0a5 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 64a795207..eef6a2368 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/cli.py b/commitizen/cli.py index c11e9078d..e5538aeb4 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", }, @@ -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/commitizen/cmd.py b/commitizen/cmd.py index c8d4f3301..fe70da9c9 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 3dc678920..0ed5ffd5b 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -2,21 +2,19 @@ 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, BumpTagFailedError, DryRunExit, ExpectedExit, - GetNextExit, InvalidManualVersion, NoCommitsFoundError, NoneIncrementExit, @@ -30,9 +28,13 @@ Increment, InvalidVersion, Prerelease, + VersionProtocol, get_version_scheme, ) +if TYPE_CHECKING: + from commitizen.config import BaseConfig + logger = getLogger("commitizen") @@ -47,7 +49,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 @@ -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, **{ @@ -94,7 +96,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"] @@ -158,62 +159,110 @@ 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"] - 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: + 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"), - (get_next, "--get-next"), + (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 build_metadata and is_local_version: - raise NotAllowed("--local-version cannot be combined with --build-metadata") + if errors: + raise NotAllowed("\n".join(errors)) - if get_next: + 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`" + ) + + # 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"), (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)) + 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) @@ -221,69 +270,23 @@ 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", - ) - - new_tag_version = rules.normalize_tag(new_version) - message = bump.create_commit_message( - current_version, new_version, self.bump_settings["bump_message"] + increment, new_version = self._resolve_increment_and_new_version( + current_version, current_tag ) - if get_next: + new_tag_version = rules.normalize_tag(new_version) + 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: @@ -302,10 +305,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 +316,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 +368,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 diff --git a/commitizen/commands/changelog.py b/commitizen/commands/changelog.py index 27b8ccb25..215e03206 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, @@ -199,7 +202,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() diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py index a6101f7df..0ea5885eb 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 7144bced8..3894d0b77 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 4a8a69d9e..62678a224 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/commands/version.py b/commitizen/commands/version.py index 7ccadb513..9290e80b8 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 + 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: {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.arguments.get("verbose"): + out.write(f"Installed Commitizen Version: {__version__}") + if not self.arguments.get("commitizen") and ( + self.arguments.get("project") or self.arguments.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.arguments.get("major"): + version = f"{version_scheme.major}" + elif self.arguments.get("minor"): + version = f"{version_scheme.minor}" - 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 self.arguments.get("verbose") + else version + ) + return - out.write(f"Project Version: {version}" if verbose else version) + if self.arguments.get("major") or self.arguments.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/commitizen/config/__init__.py b/commitizen/config/__init__.py index 6cf8b840d..e30f9f789 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 b77aea5f3..d0a212b73 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 4e7097aa1..860ca8ed5 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 4ea1dca7d..b10cf9bd3 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 c048ab272..58722d0f6 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 cb17fe32c..58753036f 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 8466b58bb..e4bf88cc1 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -1,15 +1,17 @@ from __future__ import annotations 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 collections.abc import Iterable, Mapping + + from commitizen import git + from commitizen.config.base_config import BaseConfig + 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 f0b254eb1..1d1930595 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 dde268549..0bc31db30 100644 --- a/commitizen/cz/customize/customize.py +++ b/commitizen/cz/customize/customize.py @@ -1,12 +1,14 @@ from __future__ import annotations -from collections.abc import Mapping from typing import TYPE_CHECKING, Any -from commitizen.question import CzQuestion - if TYPE_CHECKING: + from collections.abc import Mapping + from jinja2 import Template + + from commitizen.config import BaseConfig + from commitizen.question import CzQuestion else: try: from jinja2 import Template @@ -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 4e6024ff7..bbe4fc5ee 100644 --- a/commitizen/cz/jira/jira.py +++ b/commitizen/cz/jira/jira.py @@ -1,8 +1,14 @@ +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 collections.abc import Mapping + + from commitizen.question import CzQuestion __all__ = ["JiraSmartCz"] diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 9b3b76a68..b91fe4879 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -1,12 +1,14 @@ from __future__ import annotations -import pathlib 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: + import pathlib + + from commitizen.question import CzQuestion class CzSettings(TypedDict, total=False): diff --git a/commitizen/exceptions.py b/commitizen/exceptions.py index 75b0ab2fb..52193e6cc 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,36 +72,44 @@ def __init__(self, *args: str, **kwargs: Any) -> None: class DryRunExit(ExpectedExit): - pass - - -class GetNextExit(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" @@ -111,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 diff --git a/commitizen/git.py b/commitizen/git.py index c124cd937..e598ff065 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)"' diff --git a/commitizen/hooks.py b/commitizen/hooks.py index f60bd9b43..10560d5ea 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 3e01fe22f..4cef578ab 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 c91bfdae2..84b745e32 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 3e8c95e22..ca00f05e7 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -3,17 +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 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 +if TYPE_CHECKING: + from tomlkit.items import AoT class CargoProvider(TomlProvider): @@ -30,22 +28,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 +43,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/commitizen/providers/npm_provider.py b/commitizen/providers/npm_provider.py index 312544725..7aeb0ee7d 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 f63b13b79..d9a174a0a 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 21e8322d9..4574dc4b6 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 e3f54370f..68c74a72e 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 0696d85aa..0c71bb06c 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/docs/commands/bump.md b/docs/commands/bump.md index 47e64dfc6..e20a20d5f 100644 --- a/docs/commands/bump.md +++ b/docs/commands/bump.md @@ -2,14 +2,23 @@ ## 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/configuration_file.md) 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 - **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 @@ -21,9 +30,9 @@ 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` -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 @@ -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 file 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 @@ -99,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). @@ -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) -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. +Ensures that bumping pre-releases **maintains linearity**. -Below are some examples that illustrate the difference in behavior: +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. + +#### `--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,128 +195,172 @@ 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. -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` +!!! 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: + + 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`: + ```diff title="setup.py" + from setuptools import setup + + - setup(..., version="1.0.5", ...) + + 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 +``` + +!!! note + By default, Commitizen uses lightweight tags. ### `--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. +!!! note "Useful scenarios" + Pipe the newly created changelog to another tool. -Example: + 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. -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 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: -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. +```text +fix(magic)!: fully deprecate whatever +``` -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. +and you run -### `--version-scheme` +```bash +cz bump --major-version-zero +``` -Choose the version format, options: `pep440`, `semver`. +Then the version of your project will be bumped to `0.2.0` instead of `1.0.0`. -Default: `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 python: `pep440` + 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. -Recommended for other: `semver` +!!! warning + This option is only compatible with projects that have major version number zero, `0.x.x` for example. -You can also set this in the [configuration](#version_scheme) with `version_scheme = "semver"`. + It fails when used with projects that have a version number greater than zero like `1.x.x`. -[pep440][pep440] and [semver][semver] are quite similar, their difference lies in -how the prereleases look. + If used together with a manual version, the command also fails. -| 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` | + ```bash + # This fails + cz bump 0.1.0 --major-version-zero + ``` -Can I transition from one to the other? +### `--gpg-sign` -Yes, you shouldn't have any issues. +Creates gpg signed tags. + +```bash +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` @@ -293,140 +370,99 @@ 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` -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 that Commitizen ignores everything after `+` when it bumps the version. It is therefore safe to write different build-metadata between versions. - -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. - -### `--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`. +!!! note "Example usage" + - Git hash in version + - Labeling the version with additional metadata. -```bash -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. - -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. - -The following output is the result of `cz bump --dry-run`: +!!! note + Commitizen ignores everything after `+` when it bumps the version. -``` -bump: version 3.28.0 → 3.29.0 -tag to create: v3.29.0 -increment detected: MINOR -``` + It is therefore safe to write different build-metadata between versions. -The following output is the result of `cz bump --get-next`: -``` -3.29.0 -``` +!!! warning + Normally, you should not use this functionality, but if you decide to do so, keep in mind that: -The `--get-next` flag will raise a `NoneIncrementExit` if the found commits are not eligible for a version bump. + - 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. -For information on how to suppress this exit, see [avoid raising errors](#avoid-raising-errors). +!!! warning + This parameter is not compatible with `--local-version` as it uses the same part of the version string. -### `--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]` +### `--get-next` -```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 +Similar to `--dry-run` but only outputs the next version. -# 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 +```bash +# outputs 1.0.1 if the current version is 1.0.0 and the increment is PATCH +cz bump --get-next ``` -## Avoid raising errors +Useful for determining the next version based on CI for non-production environments/builds. -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. +!!! 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. -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. + The following is the output of `cz bump --dry-run`: -### Recommended use case + ```text + bump: version 3.28.0 → 3.29.0 + tag to create: v3.29.0 + increment detected: MINOR + ``` -At the moment, we've identified that the most common error code to skip is + The following is the output of `cz bump --get-next`: -| Error name | Exit code | -| ----------------- | --------- | -| NoneIncrementExit | 21 | + ```text + 3.29.0 + ``` -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. +!!! warning + The `--get-next` flag will raise a `NoneIncrementExit` if the found commits are not eligible for a version bump. -```sh -cz -nr 21 bump -``` - -### Easy way - -Check which error code was raised by Commitizen by running in the terminal - -```sh -echo $? -``` + For information on how to suppress this exit, see [Ignoring Exit Codes](../exit_codes.md#ignoring-exit-codes). -The output should be an integer like this +### `--allow-no-commit` -```sh -3 -``` +Allow the project version to be bumped even when there's no eligible version. -And then you can tell Commitizen to ignore it: +Example usage: ```sh -cz --no-raise 3 -``` - -You can tell Commitizen to skip more than one if needed: +# Force to bump a minor version +cz bump --increment MINOR --allow-no-commit -```sh -cz --no-raise 3,4,5 +# 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 ``` -### Longer way - -Check the list of [exit_codes](../exit_codes.md) and understand which one you have -to skip and why. +!!! note "Default increment" + The increment is overridden to `PATCH` if there is no increment detected or specified. -Remember to document somewhere this, because you'll forget. + 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. -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 -``` + ```sh + # will bump to `1.0.1` if the current version is `1.0.0`. + cz bump --allow-no-commit -## Configuration + # 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` 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: @@ -438,7 +474,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 +484,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,205 +497,13 @@ 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. -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`. - -Some examples - -`pyproject.toml`, `.cz.toml` or `cz.toml` - -```toml title="pyproject.toml" -[tool.commitizen] -version_files = [ - "src/__version__.py", - "packages/*/pyproject.toml:version", - "setup.py: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. - -!!! note - Files can be specified using relative (to the execution) paths, absolute paths, or glob patterns. - ---- - -### `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 | - -Some examples - -`pyproject.toml`, `.cz.toml` or `cz.toml` - -```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` - -```toml title="pyproject.toml" -[tool.commitizen] -update_changelog_on_bump = true -``` - ---- - -### `annotated_tag` - -When set to `true`, Commitizen will create annotated tags. - -```toml title="pyproject.toml" -[tool.commitizen] -annotated_tag = true -``` - ---- - -### `gpg_sign` - -When set to `true`, Commitizen will create gpg signed tags. - -```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` - -```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` -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` - -Choose 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` | - -Options: `pep440`, `semver`, `semver2` - -Defaults to: `pep440` - -```toml title="pyproject.toml" -[tool.commitizen] -version_scheme = "semver" -``` - -## Custom bump - -Read the [customizing section](../customization.md). +| `$devrelease`, `${devrelease}` | Development release | [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 aee1a0e07..3f2425a51 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/check.md b/docs/commands/check.md index 320bffb88..ef7f8f5f9 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/commands/commit.md b/docs/commands/commit.md index be9d193b9..54e0c8b07 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 4d92112d3..b673ba127 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 94aa2076b..000000000 --- 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-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 000000000..10ca5bcf8 --- /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 000000000..86d436310 --- /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 000000000..2c8dda27b --- /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 000000000..72fdff947 --- /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 000000000..846910255 --- /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 000000000..5b7ce807b --- /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 000000000..859f84f78 --- /dev/null +++ b/docs/config/version_provider.md @@ -0,0 +1,326 @@ +# 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/contributing.md b/docs/contributing.md index 16db93062..741a13f21 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. @@ -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 9eecc3efa..7b040c295 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/docs/customization.md b/docs/customization.md deleted file mode 100644 index 99ffd39ba..000000000 --- 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-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 " (<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 000000000..60f40ebea --- /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 000000000..a5440342b --- /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 000000000..c698b03de --- /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/exit_codes.md b/docs/exit_codes.md index fd92961d3..1a214e283 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. diff --git a/docs/external_links.md b/docs/external_links.md index a90bbd085..1b5efb05d 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) diff --git a/docs/faq.md b/docs/faq.md index ee9d97068..9de0c43e4 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,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 @@ -28,12 +23,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 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) 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 +44,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 <created_tag> ``` -## 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): +<!-- 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 AFAIK) +- 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 +72,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 +79,7 @@ git revert --no-commit <SHA> 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 +95,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). @@ -132,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) @@ -151,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}" @@ -162,3 +159,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 000000000..9fbd6d5b5 --- /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/docs/images/cli_help/cz_version___help.svg b/docs/images/cli_help/cz_version___help.svg index 7ddec177d..a8e0bd844 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> diff --git a/docs/third-party-commitizen.md b/docs/third-party-commitizen.md deleted file mode 100644 index 0c35a3155..000000000 --- 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 000000000..9711386fc --- /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 + +<!-- TODO: provide more details about the features --> +<!-- We can move the details from customization pages to here --> + +### 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. + +<!-- TODO: complete the following section --> +<!-- ## How do I create a new plugin? --> + +## 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) + + <!-- Description of the plugin. --> + + <!-- What features does the plugin provide? --> + + ## Installation + + ```sh + pip install package-name + ``` + + ## Usage + + ```sh + cz --name package-name commit + ``` + + ## Example + + <!-- Example usage of the plugin. --> 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 000000000..77f7d2e17 --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..e8e265451 --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..99505a274 --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..e9ced907b --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..f4157105e --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..c638f4bfa --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..4f0a2e122 --- /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. + +<!-- TODO: What features does the plugin provide? --> + +## 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 000000000..7a2ba5917 --- /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 000000000..6032b8e7f --- /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` + +<!-- TODO: What features does the plugin provide? --> + +## 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/docs/tutorials/monorepo_guidance.md b/docs/tutorials/monorepo_guidance.md index 6f15a8724..f863a9e53 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 ``` diff --git a/docs/tutorials/tag_format.md b/docs/tutorials/tag_format.md index 8408b4c80..2d439e38c 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 a64480874..a56d6494d 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 dec8d3fd5..9666a203d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,10 +1,10 @@ site_name: Commitizen +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: @@ -14,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 @@ -21,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 @@ -32,31 +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" - - Configuration: "config.md" - - Customization: "customization.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" + - 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" - - 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 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" diff --git a/poetry.lock b/poetry.lock index 49df9dcd5..e7600db5d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,15 +1,15 @@ -# 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" -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"] @@ -390,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] @@ -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] @@ -625,16 +675,102 @@ 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.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 +807,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 +998,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,53 +1040,54 @@ files = [ [[package]] name = "mypy" -version = "1.17.1" +version = "1.19.0" 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.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\""} @@ -1076,14 +1243,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 +1340,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.16.1" +version = "10.18" 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.18-py3-none-any.whl", hash = "sha256:090bca72be43f7d3186374e23c782899dbef9dc153ef24c59dcd3c346f9ffcae"}, + {file = "pymdown_extensions-10.18.tar.gz", hash = "sha256:20252abe6367354b24191431617a072ee6be9f68c5afcc74ea5573508a61f9e5"}, ] [package.dependencies] @@ -1212,14 +1379,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 +1403,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 +1458,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 +1476,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 +1535,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 +1670,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.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.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.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]] @@ -1578,44 +1765,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 +1830,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 +1883,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,41 +1935,41 @@ 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" -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" -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 +2027,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" @@ -1955,4 +2181,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 8211b969d..3e9c45ae6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,12 @@ [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 = [ { 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" @@ -84,13 +85,43 @@ pep440 = "commitizen.version_schemes:Pep440" semver = "commitizen.version_schemes:SemVer" semver2 = "commitizen.version_schemes:SemVer2" +[dependency-groups] +dev = ["ipython>=8.0", "tox>4", "poethepoet>=0.34.0"] + +test = [ + "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", + "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", "mkdocs-material>=9.1.6"] + +script = [ + # for scripts/gen_cli_help_screenshots.py + "rich>=13.7.1", +] + [build-system] -requires = ["poetry-core>=2.0"] +requires = ["poetry-core>=2.2"] 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", @@ -106,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 @@ -174,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}" @@ -207,11 +206,20 @@ select = [ "RUF022", # unused-noqa "RUF100", + # Checks for uses of the assert keyword. + "S101", + # flake8-type-checking (TC) + "TC001", + "TC002", + "TC003", + "TC004", + "TC005", + "TC006", ] ignore = ["E501", "D1", "D415"] [tool.ruff.lint.per-file-ignores] -"tests/*" = ["ANN"] +"tests/*" = ["ANN", "S101"] [tool.ruff.lint.isort] known-first-party = ["commitizen", "tests"] diff --git a/tests/commands/test_bump_command.py b/tests/commands/test_bump_command.py index 59297b172..8dbe8f447 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, @@ -23,7 +20,6 @@ DryRunExit, ExitCode, ExpectedExit, - GetNextExit, InvalidManualVersion, NoCommitsFoundError, NoneIncrementExit, @@ -34,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", @@ -647,13 +650,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 @@ -1456,7 +1457,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 +1477,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 +1487,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") diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py index f147c419b..f2e2ecbd3 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/commands/test_check_command.py b/tests/commands/test_check_command.py index d2a82a903..e7918ca23 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 cfecfebeb..54fa271fd 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/commands/test_version_command.py b/tests/commands/test_version_command.py index 7b5b13a7e..a5faf4e16 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 b1ed94124..a194615a9 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. diff --git a/tests/conftest.py b/tests/conftest.py index 04a448d99..5eaa17440 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,11 +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 ( @@ -17,7 +15,14 @@ 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 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" diff --git a/tests/providers/conftest.py b/tests/providers/conftest.py index f73cdb72a..41b7bd02f 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 482bd698e..782a8ba89 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 5e7b2d8cb..ea15fdbf3 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" @@ -301,3 +304,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) diff --git a/tests/providers/test_commitizen_provider.py b/tests/providers/test_commitizen_provider.py index b8df60da9..c28dc90f7 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 45cbc8afa..22357b7a7 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 bc9399916..785a2cb7f 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 16bb479cc..f44cef38c 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 e26e2a44f..ad998d41c 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 9d955b232..e28a6782a 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 409370937..7cb0782dd 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 4465fcccb..e32a9bcf9 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 cc81a24f2..199c4b972 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 1abc63f29..e09d68cfe 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 ca79620ad..e6eceff4f 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 812fa6bf6..752cf229e 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 e0d99e032..ff7126d34 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_cli.py b/tests/test_cli.py index 31371caea..f91a27373 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) diff --git a/tests/test_git.py b/tests/test_git.py index 2a31d9c0b..45e6028c9 100644 --- a/tests/test_git.py +++ b/tests/test_git.py @@ -4,11 +4,12 @@ import os import platform import shutil +from typing import TYPE_CHECKING 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, @@ -17,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): @@ -110,10 +114,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 +416,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 +504,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() diff --git a/tests/test_incremental_build.py b/tests/test_incremental_build.py new file mode 100644 index 000000000..13f123a65 --- /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 diff --git a/tests/test_version_schemes.py b/tests/test_version_schemes.py index 8e2dae902..afaae7618 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 43e0cf79a..bea7f20a1 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),