commitizen 4.13.10__tar.gz → 4.15.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. {commitizen-4.13.10 → commitizen-4.15.0}/PKG-INFO +1 -1
  2. commitizen-4.15.0/commitizen/__version__.py +1 -0
  3. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/bump.py +3 -3
  4. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cli.py +36 -2
  5. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/bump.py +5 -1
  6. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/changelog.py +7 -2
  7. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/init.py +7 -3
  8. commitizen-4.15.0/commitizen/commands/version.py +141 -0
  9. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/out.py +11 -11
  10. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/tags.py +6 -8
  11. commitizen-4.15.0/commitizen/version_increment.py +33 -0
  12. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/version_schemes.py +13 -4
  13. {commitizen-4.13.10 → commitizen-4.15.0}/pyproject.toml +1 -1
  14. commitizen-4.13.10/commitizen/__version__.py +0 -1
  15. commitizen-4.13.10/commitizen/commands/version.py +0 -86
  16. {commitizen-4.13.10 → commitizen-4.15.0}/LICENSE +0 -0
  17. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/__init__.py +0 -0
  18. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/__main__.py +0 -0
  19. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog.py +0 -0
  20. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog_formats/__init__.py +0 -0
  21. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog_formats/asciidoc.py +0 -0
  22. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog_formats/base.py +0 -0
  23. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog_formats/markdown.py +0 -0
  24. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog_formats/restructuredtext.py +0 -0
  25. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/changelog_formats/textile.py +0 -0
  26. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cmd.py +0 -0
  27. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/__init__.py +0 -0
  28. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/check.py +0 -0
  29. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/commit.py +0 -0
  30. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/example.py +0 -0
  31. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/info.py +0 -0
  32. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/list_cz.py +0 -0
  33. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/commands/schema.py +0 -0
  34. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/config/__init__.py +0 -0
  35. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/config/base_config.py +0 -0
  36. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/config/factory.py +0 -0
  37. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/config/json_config.py +0 -0
  38. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/config/toml_config.py +0 -0
  39. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/config/yaml_config.py +0 -0
  40. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/__init__.py +0 -0
  41. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/base.py +0 -0
  42. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/conventional_commits/__init__.py +0 -0
  43. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/conventional_commits/conventional_commits.py +0 -0
  44. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/conventional_commits/conventional_commits_info.txt +0 -0
  45. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/customize/__init__.py +0 -0
  46. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/customize/customize.py +0 -0
  47. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/customize/customize_info.txt +0 -0
  48. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/exceptions.py +0 -0
  49. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/jira/__init__.py +0 -0
  50. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/jira/jira.py +0 -0
  51. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/jira/jira_info.txt +0 -0
  52. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/cz/utils.py +0 -0
  53. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/defaults.py +0 -0
  54. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/exceptions.py +0 -0
  55. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/factory.py +0 -0
  56. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/git.py +0 -0
  57. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/hooks.py +0 -0
  58. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/project_info.py +0 -0
  59. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/__init__.py +0 -0
  60. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/base_provider.py +0 -0
  61. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/cargo_provider.py +0 -0
  62. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/commitizen_provider.py +0 -0
  63. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/composer_provider.py +0 -0
  64. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/npm_provider.py +0 -0
  65. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/pep621_provider.py +0 -0
  66. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/poetry_provider.py +0 -0
  67. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/scm_provider.py +0 -0
  68. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/providers/uv_provider.py +0 -0
  69. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/py.typed +0 -0
  70. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/question.py +0 -0
  71. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/templates/CHANGELOG.adoc.j2 +0 -0
  72. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/templates/CHANGELOG.md.j2 +0 -0
  73. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/templates/CHANGELOG.rst.j2 +0 -0
  74. {commitizen-4.13.10 → commitizen-4.15.0}/commitizen/templates/CHANGELOG.textile.j2 +0 -0
  75. {commitizen-4.13.10 → commitizen-4.15.0}/docs/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: commitizen
3
- Version: 4.13.10
3
+ Version: 4.15.0
4
4
  Summary: Python commitizen client tool
5
5
  Keywords: commitizen,conventional,commits,git
6
6
  Author: Santiago Fraire
@@ -0,0 +1 @@
1
+ __version__ = "4.15.0"
@@ -15,7 +15,7 @@ from commitizen.git import GitCommit, smart_open
15
15
  if TYPE_CHECKING:
16
16
  from collections.abc import Generator, Iterable
17
17
 
18
- from commitizen.version_schemes import Increment, Version
18
+ from commitizen.version_schemes import Increment, VersionProtocol
19
19
 
20
20
  VERSION_TYPES = [None, PATCH, MINOR, MAJOR]
21
21
 
@@ -131,8 +131,8 @@ def _resolve_files_and_regexes(
131
131
 
132
132
 
133
133
  def create_commit_message(
134
- current_version: Version | str,
135
- new_version: Version | str,
134
+ current_version: VersionProtocol | str,
135
+ new_version: VersionProtocol | str,
136
136
  message_template: str | None = None,
137
137
  ) -> str:
138
138
  if message_template is None:
@@ -21,6 +21,7 @@ from commitizen.exceptions import (
21
21
  InvalidCommandArgumentError,
22
22
  NoCommandFoundError,
23
23
  )
24
+ from commitizen.version_increment import VersionIncrement
24
25
 
25
26
  logger = logging.getLogger(__name__)
26
27
 
@@ -542,13 +543,19 @@ data = {
542
543
  },
543
544
  {
544
545
  "name": ["--major"],
545
- "help": "Output just the major version. Must be used with --project or --verbose.",
546
+ "help": (
547
+ "Output just the major version. Must be used with MANUAL_VERSION, "
548
+ "--project, or --verbose."
549
+ ),
546
550
  "action": "store_true",
547
551
  "exclusive_group": "group2",
548
552
  },
549
553
  {
550
554
  "name": ["--minor"],
551
- "help": "Output just the minor version. Must be used with --project or --verbose.",
555
+ "help": (
556
+ "Output just the minor version. Must be used with MANUAL_VERSION, "
557
+ "--project, or --verbose."
558
+ ),
552
559
  "action": "store_true",
553
560
  "exclusive_group": "group2",
554
561
  },
@@ -558,6 +565,33 @@ data = {
558
565
  "action": "store_true",
559
566
  "exclusive_group": "group2",
560
567
  },
568
+ {
569
+ "name": ["--patch"],
570
+ "help": (
571
+ "Output the patch version only. Must be used with MANUAL_VERSION, "
572
+ "--project, or --verbose."
573
+ ),
574
+ "action": "store_true",
575
+ "exclusive_group": "group2",
576
+ },
577
+ {
578
+ "name": ["--next"],
579
+ "help": "Output the next version.",
580
+ "type": str,
581
+ "nargs": "?",
582
+ "default": None,
583
+ "const": "USE_GIT_COMMITS",
584
+ "choices": ["USE_GIT_COMMITS"]
585
+ + [str(increment) for increment in VersionIncrement],
586
+ "exclusive_group": "group2",
587
+ },
588
+ {
589
+ "name": "manual_version",
590
+ "type": str,
591
+ "nargs": "?",
592
+ "help": "Use the version provided instead of the version from the project. Can be used to test the selected version scheme.",
593
+ "metavar": "MANUAL_VERSION",
594
+ },
561
595
  ],
562
596
  },
563
597
  ],
@@ -330,7 +330,11 @@ class Bump:
330
330
 
331
331
  changelog_cmd = Changelog(
332
332
  self.config,
333
- {**changelog_args, "file_name": self.file_name}, # type: ignore[typeddict-item]
333
+ {
334
+ **changelog_args, # type: ignore[typeddict-item]
335
+ "file_name": self.file_name,
336
+ "allow_no_commit": bool(self.arguments["allow_no_commit"]),
337
+ },
334
338
  )
335
339
  changelog_cmd()
336
340
  changelog_file_name = changelog_cmd.file_name
@@ -43,6 +43,7 @@ class ChangelogArgs(TypedDict, total=False):
43
43
  extras: dict[str, Any]
44
44
  export_template: str
45
45
  during_version_bump: bool | None
46
+ allow_no_commit: bool | None # Internal-only when invoked by bump.
46
47
 
47
48
 
48
49
  class Changelog:
@@ -124,6 +125,8 @@ class Changelog:
124
125
  self.export_template_to = arguments.get("export_template")
125
126
 
126
127
  self.during_version_bump: bool = arguments.get("during_version_bump") or False
128
+ # Internal flag used when changelog is invoked from `cz bump --allow-no-commit`.
129
+ self.allow_no_commit: bool = bool(arguments.get("allow_no_commit"))
127
130
 
128
131
  def _find_incremental_rev(self, latest_version: str, tags: Iterable[GitTag]) -> str:
129
132
  """Try to find the 'start_rev'.
@@ -255,8 +258,10 @@ class Changelog:
255
258
  changelog_meta.unreleased_end = latest_full_release_info.index + 1
256
259
 
257
260
  commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order")
258
- if not commits and (
259
- self.current_version is None or not self.current_version.is_prerelease
261
+ if (
262
+ not self.allow_no_commit
263
+ and not commits
264
+ and (self.current_version is None or not self.current_version.is_prerelease)
260
265
  ):
261
266
  raise NoCommitsFoundError("No commits found")
262
267
 
@@ -17,7 +17,11 @@ from commitizen.exceptions import (
17
17
  NoAnswersError,
18
18
  )
19
19
  from commitizen.git import get_latest_tag_name, get_tag_names, smart_open
20
- from commitizen.version_schemes import KNOWN_SCHEMES, Version, get_version_scheme
20
+ from commitizen.version_schemes import (
21
+ KNOWN_SCHEMES,
22
+ VersionProtocol,
23
+ get_version_scheme,
24
+ )
21
25
 
22
26
  if TYPE_CHECKING:
23
27
  from commitizen.config import (
@@ -265,7 +269,7 @@ class Init:
265
269
  ).unsafe_ask()
266
270
  return scheme
267
271
 
268
- def _ask_major_version_zero(self, version: Version) -> bool:
272
+ def _ask_major_version_zero(self, version: VersionProtocol) -> bool:
269
273
  """Ask for setting: major_version_zero"""
270
274
  if version.major > 0:
271
275
  return False
@@ -323,7 +327,7 @@ def _write_config_to_file(
323
327
  cz_name: str,
324
328
  version_provider: str,
325
329
  version_scheme: str,
326
- version: Version,
330
+ version: VersionProtocol,
327
331
  tag_format: str,
328
332
  update_changelog_on_bump: bool,
329
333
  major_version_zero: bool,
@@ -0,0 +1,141 @@
1
+ import platform
2
+ import sys
3
+ from typing import TypedDict
4
+
5
+ from packaging.version import InvalidVersion
6
+
7
+ from commitizen import out
8
+ from commitizen.__version__ import __version__
9
+ from commitizen.config import BaseConfig
10
+ from commitizen.exceptions import NoVersionSpecifiedError, VersionSchemeUnknown
11
+ from commitizen.providers import get_provider
12
+ from commitizen.tags import TagRules
13
+ from commitizen.version_increment import VersionIncrement
14
+ from commitizen.version_schemes import Increment, get_version_scheme
15
+
16
+
17
+ class VersionArgs(TypedDict, total=False):
18
+ manual_version: str | None
19
+ next: str | None
20
+
21
+ # Exclusive groups 1
22
+ commitizen: bool
23
+ report: bool
24
+ project: bool
25
+ verbose: bool
26
+
27
+ # Exclusive groups 2
28
+ major: bool
29
+ minor: bool
30
+ patch: bool
31
+ tag: bool
32
+
33
+
34
+ class Version:
35
+ """Get the version of the installed commitizen or the current project.
36
+ Precedence:
37
+ 1. report
38
+ 2. commitizen
39
+ 3. verbose, project
40
+ """
41
+
42
+ def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None:
43
+ self.config: BaseConfig = config
44
+ self.arguments = arguments
45
+
46
+ def __call__(self) -> None:
47
+ if self.arguments.get("report"):
48
+ out.write(f"Commitizen Version: {__version__}")
49
+ out.write(f"Python Version: {sys.version}")
50
+ out.write(f"Operating System: {platform.system()}")
51
+ return
52
+
53
+ if self.arguments.get("verbose"):
54
+ out.write(f"Installed Commitizen Version: {__version__}")
55
+
56
+ if self.arguments.get("commitizen"):
57
+ out.write(__version__)
58
+ return
59
+
60
+ if (
61
+ self.arguments.get("project")
62
+ or self.arguments.get("verbose")
63
+ or self.arguments.get("next")
64
+ or self.arguments.get("manual_version")
65
+ ):
66
+ version_str = self.arguments.get("manual_version")
67
+ if version_str is None:
68
+ try:
69
+ version_str = get_provider(self.config).get_version()
70
+ except NoVersionSpecifiedError:
71
+ out.error("No project information in this project.")
72
+ return
73
+ try:
74
+ scheme_factory = get_version_scheme(self.config.settings)
75
+ except VersionSchemeUnknown:
76
+ out.error("Unknown version scheme.")
77
+ return
78
+
79
+ try:
80
+ version = scheme_factory(version_str)
81
+ except InvalidVersion:
82
+ out.error(f"Invalid version: '{version_str}'")
83
+ return
84
+
85
+ if next_increment_str := self.arguments.get("next"):
86
+ if next_increment_str == "USE_GIT_COMMITS":
87
+ # TODO: implement USE_GIT_COMMITS by deriving the increment from
88
+ # git history. This requires refactoring the bump logic out of
89
+ # `commitizen/commands/bump.py` so it can be reused here. See #1678.
90
+ out.error("--next USE_GIT_COMMITS is not implemented yet.")
91
+ return
92
+
93
+ next_increment = VersionIncrement.from_value(next_increment_str)
94
+ increment: Increment | None
95
+ if next_increment == VersionIncrement.NONE:
96
+ increment = None
97
+ elif next_increment == VersionIncrement.PATCH:
98
+ increment = "PATCH"
99
+ elif next_increment == VersionIncrement.MINOR:
100
+ increment = "MINOR"
101
+ else:
102
+ increment = "MAJOR"
103
+ version = version.bump(increment=increment)
104
+
105
+ if self.arguments.get("major"):
106
+ out.write(version.major)
107
+ return
108
+ if self.arguments.get("minor"):
109
+ out.write(version.minor)
110
+ return
111
+ if self.arguments.get("patch"):
112
+ out.write(version.micro)
113
+ return
114
+
115
+ display_version: str
116
+ if self.arguments.get("tag"):
117
+ tag_rules = TagRules.from_settings(self.config.settings)
118
+ display_version = tag_rules.normalize_tag(version)
119
+ else:
120
+ display_version = str(version)
121
+
122
+ out.write(
123
+ f"Project Version: {display_version}"
124
+ if self.arguments.get("verbose")
125
+ else display_version
126
+ )
127
+ return
128
+
129
+ for argument in ("major", "minor", "patch"):
130
+ if self.arguments.get(argument):
131
+ out.error(
132
+ f"{argument} can only be used with MANUAL_VERSION, --project or --verbose."
133
+ )
134
+ return
135
+
136
+ if self.arguments.get("tag"):
137
+ out.error("Tag can only be used with --project or --verbose.")
138
+ return
139
+
140
+ # If no arguments are provided, just show the installed commitizen version
141
+ out.write(__version__)
@@ -9,35 +9,35 @@ if sys.platform == "win32":
9
9
  sys.stdout.reconfigure(encoding="utf-8")
10
10
 
11
11
 
12
- def write(value: str, *args: object) -> None:
12
+ def write(value: object, *args: object) -> None:
13
13
  """Intended to be used when value is multiline."""
14
14
  print(value, *args)
15
15
 
16
16
 
17
- def line(value: str, *args: object, **kwargs: Any) -> None:
17
+ def line(value: object, *args: object, **kwargs: Any) -> None:
18
18
  """Wrapper in case I want to do something different later."""
19
19
  print(value, *args, **kwargs)
20
20
 
21
21
 
22
- def error(value: str) -> None:
23
- message = colored(value, "red")
22
+ def error(value: object) -> None:
23
+ message = colored(str(value), "red")
24
24
  line(message, file=sys.stderr)
25
25
 
26
26
 
27
- def success(value: str) -> None:
28
- message = colored(value, "green")
27
+ def success(value: object) -> None:
28
+ message = colored(str(value), "green")
29
29
  line(message)
30
30
 
31
31
 
32
- def info(value: str) -> None:
33
- message = colored(value, "blue")
32
+ def info(value: object) -> None:
33
+ message = colored(str(value), "blue")
34
34
  line(message)
35
35
 
36
36
 
37
- def diagnostic(value: str) -> None:
37
+ def diagnostic(value: object) -> None:
38
38
  line(value, file=sys.stderr)
39
39
 
40
40
 
41
- def warn(value: str) -> None:
42
- message = colored(value, "magenta")
41
+ def warn(value: object) -> None:
42
+ message = colored(str(value), "magenta")
43
43
  line(message, file=sys.stderr)
@@ -14,7 +14,7 @@ from commitizen.git import GitTag
14
14
  from commitizen.version_schemes import (
15
15
  DEFAULT_SCHEME,
16
16
  InvalidVersion,
17
- Version,
17
+ VersionProtocol,
18
18
  VersionScheme,
19
19
  get_version_scheme,
20
20
  )
@@ -23,8 +23,6 @@ if TYPE_CHECKING:
23
23
  import sys
24
24
  from collections.abc import Iterable, Sequence
25
25
 
26
- from commitizen.version_schemes import VersionScheme
27
-
28
26
  # Self is Python 3.11+ but backported in typing-extensions
29
27
  if sys.version_info < (3, 11):
30
28
  from typing_extensions import Self
@@ -75,7 +73,7 @@ class TagRules:
75
73
  assert not rules.is_version_tag("warn1.0.0", warn=True) # Does warn
76
74
 
77
75
  assert rules.search_version("# My v1.0.0 version").version == "1.0.0"
78
- assert rules.extract_version("v1.0.0") == Version("1.0.0")
76
+ assert rules.extract_version("v1.0.0") == rules.scheme("1.0.0")
79
77
  try:
80
78
  assert rules.extract_version("not-a-v1.0.0")
81
79
  except InvalidVersion:
@@ -145,7 +143,7 @@ class TagRules:
145
143
  """Filter in version tags and warn on unexpected tags"""
146
144
  return [tag for tag in tags if self.is_version_tag(tag, warn)]
147
145
 
148
- def extract_version(self, tag: GitTag) -> Version:
146
+ def extract_version(self, tag: GitTag) -> VersionProtocol:
149
147
  """
150
148
  Extract a version from the tag as defined in tag formats.
151
149
 
@@ -195,7 +193,7 @@ class TagRules:
195
193
  return VersionTag(version, match.group(0))
196
194
 
197
195
  def normalize_tag(
198
- self, version: Version | str, tag_format: str | None = None
196
+ self, version: VersionProtocol | str, tag_format: str | None = None
199
197
  ) -> str:
200
198
  """
201
199
  The tag and the software version might be different.
@@ -225,7 +223,7 @@ class TagRules:
225
223
  )
226
224
 
227
225
  def find_tag_for(
228
- self, tags: Iterable[GitTag], version: Version | str
226
+ self, tags: Iterable[GitTag], version: VersionProtocol | str
229
227
  ) -> GitTag | None:
230
228
  """Find the first matching tag for a given version."""
231
229
  version = self.scheme(version) if isinstance(version, str) else version
@@ -234,7 +232,7 @@ class TagRules:
234
232
  # If the requested version is incomplete (e.g., "1.2"), try to find the latest
235
233
  # matching tag that shares the provided prefix.
236
234
  if len(release) < 3:
237
- matching_versions: list[tuple[Version, GitTag]] = []
235
+ matching_versions: list[tuple[VersionProtocol, GitTag]] = []
238
236
  for tag in tags:
239
237
  try:
240
238
  tag_version = self.extract_version(tag)
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import IntEnum
4
+
5
+
6
+ class VersionIncrement(IntEnum):
7
+ """Semantic versioning bump increments.
8
+
9
+ IntEnum keeps a total order compatible with NONE < PATCH < MINOR < MAJOR
10
+ for comparisons across the codebase.
11
+
12
+ - NONE: no bump (docs-only / style commits, etc.)
13
+ - PATCH: backwards-compatible bug fixes
14
+ - MINOR: backwards-compatible features
15
+ - MAJOR: incompatible API changes
16
+ """
17
+
18
+ NONE = 0
19
+ PATCH = 1
20
+ MINOR = 2
21
+ MAJOR = 3
22
+
23
+ def __str__(self) -> str:
24
+ return self.name
25
+
26
+ @classmethod
27
+ def from_value(cls, value: object) -> VersionIncrement:
28
+ if not isinstance(value, str):
29
+ return VersionIncrement.NONE
30
+ try:
31
+ return cls[value]
32
+ except KeyError:
33
+ return VersionIncrement.NONE
@@ -10,6 +10,7 @@ from typing import (
10
10
  ClassVar,
11
11
  Literal,
12
12
  Protocol,
13
+ TypeAlias,
13
14
  cast,
14
15
  runtime_checkable,
15
16
  )
@@ -22,7 +23,6 @@ from commitizen.exceptions import VersionSchemeUnknown
22
23
 
23
24
  if TYPE_CHECKING:
24
25
  import sys
25
- from typing import TypeAlias
26
26
 
27
27
  # Self is Python 3.11+ but backported in typing-extensions
28
28
  if sys.version_info < (3, 11):
@@ -31,7 +31,7 @@ if TYPE_CHECKING:
31
31
  from typing import Self
32
32
 
33
33
 
34
- Increment: TypeAlias = Literal["MAJOR", "MINOR", "PATCH"]
34
+ Increment: TypeAlias = Literal["MAJOR", "MINOR", "PATCH"] # TODO: deprecate
35
35
  Prerelease: TypeAlias = Literal["alpha", "beta", "rc"]
36
36
  _DEFAULT_VERSION_PARSER = re.compile(
37
37
  r"v?(?P<version>([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.]+)?(\w+)?)"
@@ -140,7 +140,7 @@ class VersionProtocol(Protocol):
140
140
  """
141
141
 
142
142
 
143
- # With PEP 440 and SemVer semantic, Scheme is the type, Version is an instance
143
+ # With PEP 440 and SemVer semantics, a scheme is the class; a version is an instance.
144
144
  Version: TypeAlias = VersionProtocol
145
145
  VersionScheme: TypeAlias = type[VersionProtocol]
146
146
 
@@ -422,7 +422,16 @@ def get_version_scheme(settings: Settings, name: str | None = None) -> VersionSc
422
422
  raise VersionSchemeUnknown(f'Version scheme "{name}" unknown.')
423
423
  scheme = cast("VersionScheme", ep.load())
424
424
 
425
- if not isinstance(scheme, VersionProtocol):
425
+ # `VersionProtocol` is a `@runtime_checkable` Protocol, but `issubclass()` is not
426
+ # supported for Protocols with non-method members. We check an instance instead by
427
+ # verifying the loaded object is a class with the expected interface.
428
+ if isinstance(scheme, type):
429
+ # Check for a key method/attribute that VersionProtocol requires
430
+ if not hasattr(scheme, "bump"):
431
+ warnings.warn(
432
+ f"Version scheme {name} does not implement the VersionProtocol"
433
+ )
434
+ else:
426
435
  warnings.warn(f"Version scheme {name} does not implement the VersionProtocol")
427
436
 
428
437
  return scheme
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "commitizen"
3
- version = "4.13.10"
3
+ version = "4.15.0"
4
4
  description = "Python commitizen client tool"
5
5
  authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }]
6
6
  maintainers = [
@@ -1 +0,0 @@
1
- __version__ = "4.13.10"
@@ -1,86 +0,0 @@
1
- import platform
2
- import sys
3
- from typing import TypedDict
4
-
5
- from commitizen import out
6
- from commitizen.__version__ import __version__
7
- from commitizen.config import BaseConfig
8
- from commitizen.exceptions import NoVersionSpecifiedError, VersionSchemeUnknown
9
- from commitizen.providers import get_provider
10
- from commitizen.tags import TagRules
11
- from commitizen.version_schemes import get_version_scheme
12
-
13
-
14
- class VersionArgs(TypedDict, total=False):
15
- commitizen: bool
16
- report: bool
17
- project: bool
18
- verbose: bool
19
- major: bool
20
- minor: bool
21
- tag: bool
22
-
23
-
24
- class Version:
25
- """Get the version of the installed commitizen or the current project.
26
- Precedence:
27
- 1. report
28
- 2. commitizen
29
- 3. verbose, project
30
- """
31
-
32
- def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None:
33
- self.config: BaseConfig = config
34
- self.arguments = arguments
35
-
36
- def __call__(self) -> None:
37
- if self.arguments.get("report"):
38
- out.write(f"Commitizen Version: {__version__}")
39
- out.write(f"Python Version: {sys.version}")
40
- out.write(f"Operating System: {platform.system()}")
41
- return
42
-
43
- if self.arguments.get("verbose"):
44
- out.write(f"Installed Commitizen Version: {__version__}")
45
-
46
- if not self.arguments.get("commitizen") and (
47
- self.arguments.get("project") or self.arguments.get("verbose")
48
- ):
49
- try:
50
- version = get_provider(self.config).get_version()
51
- except NoVersionSpecifiedError:
52
- out.error("No project information in this project.")
53
- return
54
- try:
55
- version_scheme = get_version_scheme(self.config.settings)(version)
56
- except VersionSchemeUnknown:
57
- out.error("Unknown version scheme.")
58
- return
59
-
60
- if self.arguments.get("major"):
61
- version = f"{version_scheme.major}"
62
- elif self.arguments.get("minor"):
63
- version = f"{version_scheme.minor}"
64
- elif self.arguments.get("tag"):
65
- tag_rules = TagRules.from_settings(self.config.settings)
66
- version = tag_rules.normalize_tag(version_scheme)
67
-
68
- out.write(
69
- f"Project Version: {version}"
70
- if self.arguments.get("verbose")
71
- else version
72
- )
73
- return
74
-
75
- if self.arguments.get("major") or self.arguments.get("minor"):
76
- out.error(
77
- "Major or minor version can only be used with --project or --verbose."
78
- )
79
- return
80
-
81
- if self.arguments.get("tag"):
82
- out.error("Tag can only be used with --project or --verbose.")
83
- return
84
-
85
- # If no arguments are provided, just show the installed commitizen version
86
- out.write(__version__)
File without changes
File without changes