1
1
import os
2
- from typing import TypedDict
2
+ from collections .abc import Iterable
3
+ from typing import TYPE_CHECKING , TypedDict
3
4
4
5
from commitizen import defaults
6
+ from commitizen .config import BaseConfig
5
7
from commitizen .cz .base import BaseCommitizen
6
8
from commitizen .cz .utils import multiple_line_breaker , required_validator
7
9
from commitizen .question import CzQuestion
8
10
11
+ if TYPE_CHECKING :
12
+ from jinja2 import Template
13
+ else :
14
+ try :
15
+ from jinja2 import Template
16
+ except ImportError :
17
+ from string import Template
18
+
9
19
__all__ = ["ConventionalCommitsCz" ]
10
20
11
21
@@ -39,8 +49,31 @@ class ConventionalCommitsCz(BaseCommitizen):
39
49
}
40
50
changelog_pattern = defaults .BUMP_PATTERN
41
51
42
- def questions (self ) -> list [CzQuestion ]:
43
- return [
52
+ def __init__ (self , config : BaseConfig ) -> None :
53
+ super ().__init__ (config )
54
+
55
+ self .custom_settings : defaults .CzSettings = self .config .settings .get (
56
+ "customize" , {}
57
+ )
58
+
59
+ if self .custom_settings :
60
+ for attr_name in [
61
+ "bump_pattern" ,
62
+ "bump_map" ,
63
+ "bump_map_major_version_zero" ,
64
+ "change_type_order" ,
65
+ "commit_parser" ,
66
+ "change_type_map" ,
67
+ ]:
68
+ if value := self .custom_settings .get (attr_name ):
69
+ setattr (self , attr_name , value )
70
+
71
+ self .changelog_pattern = (
72
+ self .custom_settings .get ("changelog_pattern" ) or self .bump_pattern
73
+ )
74
+
75
+ def questions (self ) -> Iterable [CzQuestion ]:
76
+ return self .custom_settings .get ("questions" ) or [
44
77
{
45
78
"type" : "list" ,
46
79
"name" : "prefix" ,
@@ -147,6 +180,12 @@ def questions(self) -> list[CzQuestion]:
147
180
]
148
181
149
182
def message (self , answers : ConventionalCommitsAnswers ) -> str : # type: ignore[override]
183
+ if _message_template := self .custom_settings .get ("message_template" ):
184
+ message_template = Template (_message_template )
185
+ if getattr (Template , "substitute" , None ):
186
+ return message_template .substitute (** answers ) # type: ignore[attr-defined,no-any-return] # pragma: no cover # TODO: check if we can fix this
187
+ return message_template .render (** answers )
188
+
150
189
prefix = answers ["prefix" ]
151
190
scope = answers ["scope" ]
152
191
subject = answers ["subject" ]
@@ -166,7 +205,7 @@ def message(self, answers: ConventionalCommitsAnswers) -> str: # type: ignore[o
166
205
return f"{ prefix } { scope } : { subject } { body } { footer } "
167
206
168
207
def example (self ) -> str :
169
- return (
208
+ return self . custom_settings . get ( "example" ) or (
170
209
"fix: correct minor typos in code\n "
171
210
"\n "
172
211
"see the issue for details on the typos fixed\n "
@@ -175,7 +214,7 @@ def example(self) -> str:
175
214
)
176
215
177
216
def schema (self ) -> str :
178
- return (
217
+ return self . custom_settings . get ( "schema" ) or (
179
218
"<type>(<scope>): <subject>\n "
180
219
"<BLANK LINE>\n "
181
220
"<body>\n "
@@ -184,6 +223,8 @@ def schema(self) -> str:
184
223
)
185
224
186
225
def schema_pattern (self ) -> str :
226
+ if schema_pattern := self .custom_settings .get ("schema_pattern" ):
227
+ return schema_pattern
187
228
change_types = (
188
229
"build" ,
189
230
"bump" ,
@@ -209,6 +250,11 @@ def schema_pattern(self) -> str:
209
250
)
210
251
211
252
def info (self ) -> str :
253
+ if info_path := self .custom_settings .get ("info_path" ):
254
+ with open (info_path , encoding = self .config .settings ["encoding" ]) as f :
255
+ return f .read ()
256
+ if info := self .custom_settings .get ("info" ):
257
+ return info
212
258
dir_path = os .path .dirname (os .path .realpath (__file__ ))
213
259
filepath = os .path .join (dir_path , "conventional_commits_info.txt" )
214
260
with open (filepath , encoding = self .config .settings ["encoding" ]) as f :
0 commit comments