Skip to content
Open
Prev Previous commit
Next Next commit
fix(cli): use argparse for top-level --version/-v and --report flags
Replace raw sys.argv checks with proper argparse-based handling by making
subcommands optional. This fixes three issues:

- cz version --report was intercepted by the top-level handler instead of
  routing to the Version command
- cz -v did not work despite being registered as a shorthand for --version
- cz version --report and cz version --commitizen now emit deprecation
  warnings directing users to use cz --report and cz --version instead

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Loading branch information
bearomorphism and Copilot committed May 6, 2026
commit 0d600844cfe539a7b724af22855c2815262de0dc
25 changes: 12 additions & 13 deletions commitizen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def __call__(
],
"subcommands": {
"title": "commands",
"required": True,
"required": False,
"commands": [
{
"name": ["init"],
Expand Down Expand Up @@ -689,18 +689,6 @@ def main() -> None:
parser.print_help(sys.stderr)
raise ExpectedExit()

# TODO(bearomorphism): mark `cz version --commitizen` as deprecated after `cz version` feature is stable
if "--version" in sys.argv:
out.write(__version__)
raise ExpectedExit()

# TODO(bearomorphism): mark `cz version --report` as deprecated after `cz version` feature is stable
if "--report" in sys.argv:
out.write(f"Commitizen Version: {__version__}")
out.write(f"Python Version: {sys.version}")
out.write(f"Operating System: {platform.system()}")
raise ExpectedExit()

# This is for the command required constraint in 2.0
try:
args, unknown_args = parser.parse_known_args()
Expand All @@ -709,6 +697,17 @@ def main() -> None:
raise NoCommandFoundError()
raise e

if not hasattr(args, "func"):
if getattr(args, "version", False):
out.write(__version__)
raise ExpectedExit()
if getattr(args, "report", False):
out.write(f"Commitizen Version: {__version__}")
out.write(f"Python Version: {sys.version}")
out.write(f"Operating System: {platform.system()}")
raise ExpectedExit()
raise NoCommandFoundError()

arguments = vars(args)
if unknown_args:
# Raise error for extra-args without -- separation
Expand Down
13 changes: 13 additions & 0 deletions commitizen/commands/version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import platform
import sys
import warnings
from typing import TypedDict

from packaging.version import InvalidVersion
Expand Down Expand Up @@ -45,6 +46,12 @@ def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None:

def __call__(self) -> None:
if self.arguments.get("report"):
warnings.warn(
"`cz version --report` is deprecated and will be removed in v5. "
"Use `cz --report` instead.",
DeprecationWarning,
stacklevel=2,
)
out.write(f"Commitizen Version: {__version__}")
out.write(f"Python Version: {sys.version}")
out.write(f"Operating System: {platform.system()}")
Expand All @@ -54,6 +61,12 @@ def __call__(self) -> None:
out.write(f"Installed Commitizen Version: {__version__}")

if self.arguments.get("commitizen"):
warnings.warn(
"`cz version --commitizen` is deprecated and will be removed in v5. "
"Use `cz --version` instead.",
DeprecationWarning,
stacklevel=2,
)
out.write(__version__)
return

Expand Down
20 changes: 20 additions & 0 deletions tests/commands/test_version_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,23 @@ def test_version_no_arguments_shows_commitizen_version(config, capsys):
commands.Version(config, {})()
captured = capsys.readouterr()
assert captured.out.strip() == __version__


def test_version_report_emits_deprecation_warning(config, capsys):
with pytest.warns(
DeprecationWarning,
match=r"`cz version --report` is deprecated.*Use `cz --report` instead",
):
commands.Version(config, {"report": True})()
captured = capsys.readouterr()
assert f"Commitizen Version: {__version__}" in captured.out


def test_version_commitizen_emits_deprecation_warning(config, capsys):
with pytest.warns(
DeprecationWarning,
match=r"`cz version --commitizen` is deprecated.*Use `cz --version` instead",
):
commands.Version(config, {"commitizen": True})()
captured = capsys.readouterr()
assert __version__ in captured.out
8 changes: 8 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ def test_cz_with_version_arg(util: UtilFixture, capsys):
assert __version__ in out


def test_cz_with_version_short_arg(util: UtilFixture, capsys):
"""Test that cz shows the version when -v is used."""
with pytest.raises(ExpectedExit):
util.run_cli("-v")
out, _ = capsys.readouterr()
assert __version__ in out


def test_cz_with_report_arg(util: UtilFixture, capsys):
"""Test that cz shows the report when --report is used."""
with pytest.raises(ExpectedExit):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v]
[--report]
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
...
cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v]
[--report]
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
...
cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v]
[--report]
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
...
cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v]
[--report]
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ...
cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v]
[--report]
{init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ...
cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}