From 67ef8b93477984f076b2c03e76f33f6506f87372 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Sat, 22 Nov 2025 16:35:16 +0800 Subject: [PATCH 1/2] fix(version): fix the behavior of cz version --major --- commitizen/cli.py | 4 +- commitizen/commands/version.py | 47 ++++++++----- tests/commands/test_version_command.py | 69 ++++++++++++------- ...shows_description_when_use_help_option.txt | 6 +- 4 files changed, 80 insertions(+), 46 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index f4f92cb0a..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", }, diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 7ccadb513..338fce076 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -11,6 +11,7 @@ class VersionArgs(TypedDict, total=False): + commitizen: bool report: bool project: bool verbose: bool @@ -19,46 +20,58 @@ class VersionArgs(TypedDict, total=False): class Version: - """Get the version of the installed commitizen or the current project.""" + """Get the version of the installed commitizen or the current project. + Precedence: + 1. report + 2. commitizen + 3. verbose, project + """ def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None: self.config: BaseConfig = config self.parameter = arguments - self.operating_system = platform.system() - self.python_version = sys.version def __call__(self) -> None: if self.parameter.get("report"): out.write(f"Commitizen Version: {__version__}") - out.write(f"Python Version: {self.python_version}") - out.write(f"Operating System: {self.operating_system}") + out.write(f"Python Version: {sys.version}") + out.write(f"Operating System: {platform.system()}") return - if (verbose := self.parameter.get("verbose")) or self.parameter.get("project"): - if verbose: - out.write(f"Installed Commitizen Version: {__version__}") + if self.parameter.get("verbose"): + out.write(f"Installed Commitizen Version: {__version__}") + if not self.parameter.get("commitizen") and ( + self.parameter.get("project") or self.parameter.get("verbose") + ): try: version = get_provider(self.config).get_version() except NoVersionSpecifiedError: out.error("No project information in this project.") return - try: - version_scheme = get_version_scheme(self.config.settings) + version_scheme = get_version_scheme(self.config.settings)(version) except VersionSchemeUnknown: out.error("Unknown version scheme.") return - _version = version_scheme(version) - if self.parameter.get("major"): - version = f"{_version.major}" + version = f"{version_scheme.major}" elif self.parameter.get("minor"): - version = f"{_version.minor}" + version = f"{version_scheme.minor}" + + out.write( + f"Project Version: {version}" + if self.parameter.get("verbose") + else version + ) + return - out.write(f"Project Version: {version}" if verbose else version) + if self.parameter.get("major") or self.parameter.get("minor"): + out.error( + "Major or minor version can only be used with --project or --verbose." + ) return - # if no argument is given, show installed commitizen version - out.write(f"{__version__}") + # If no arguments are provided, just show the installed commitizen version + out.write(__version__) diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 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. From 10f53b74670ee179526caf6ded4ad6390487cd66 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 27 Nov 2025 23:26:34 +0800 Subject: [PATCH 2/2] refactor(version): rename class member to align with other classes --- commitizen/commands/version.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 338fce076..9290e80b8 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -29,20 +29,20 @@ class Version: def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None: self.config: BaseConfig = config - self.parameter = arguments + self.arguments = arguments def __call__(self) -> None: - if self.parameter.get("report"): + if self.arguments.get("report"): out.write(f"Commitizen Version: {__version__}") out.write(f"Python Version: {sys.version}") out.write(f"Operating System: {platform.system()}") return - if self.parameter.get("verbose"): + if self.arguments.get("verbose"): out.write(f"Installed Commitizen Version: {__version__}") - if not self.parameter.get("commitizen") and ( - self.parameter.get("project") or self.parameter.get("verbose") + if not self.arguments.get("commitizen") and ( + self.arguments.get("project") or self.arguments.get("verbose") ): try: version = get_provider(self.config).get_version() @@ -55,19 +55,19 @@ def __call__(self) -> None: out.error("Unknown version scheme.") return - if self.parameter.get("major"): + if self.arguments.get("major"): version = f"{version_scheme.major}" - elif self.parameter.get("minor"): + elif self.arguments.get("minor"): version = f"{version_scheme.minor}" out.write( f"Project Version: {version}" - if self.parameter.get("verbose") + if self.arguments.get("verbose") else version ) return - if self.parameter.get("major") or self.parameter.get("minor"): + if self.arguments.get("major") or self.arguments.get("minor"): out.error( "Major or minor version can only be used with --project or --verbose." )