Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4e18ff9

Browse files
refactor(question): strict type with pydantic for questions
1 parent a3919c9 commit 4e18ff9

File tree

14 files changed

+259
-32
lines changed

14 files changed

+259
-32
lines changed

‎commitizen/commands/commit.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
NothingToCommitError,
2525
)
2626
from commitizen.git import smart_open
27+
from commitizen.question import ListQuestion
2728

2829

2930
class Commit:
@@ -52,10 +53,12 @@ def prompt_commit_questions(self) -> str:
5253
# Prompt user for the commit message
5354
cz = self.cz
5455
questions = cz.questions()
55-
for question in filter(lambdaq: q["type"] =="list", questions):
56-
question["use_shortcuts"] = self.config.settings["use_shortcuts"]
56+
for question in (qforqinquestionsifisinstance(q, ListQuestion)):
57+
question.use_shortcuts = self.config.settings["use_shortcuts"]
5758
try:
58-
answers = questionary.prompt(questions, style=cz.style)
59+
answers = questionary.prompt(
60+
(q.model_dump() for q in questions), style=cz.style
61+
)
5962
except ValueError as err:
6063
root_err = err.__context__
6164
if isinstance(root_err, CzException):

‎commitizen/cz/base.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from commitizen import git
1111
from commitizen.config.base_config import BaseConfig
12-
from commitizen.defaults import Questions
12+
from commitizen.question import CzQuestion
1313

1414

1515
class MessageBuilderHook(Protocol):
@@ -68,7 +68,7 @@ def __init__(self, config: BaseConfig) -> None:
6868
self.config.settings.update({"style": BaseCommitizen.default_style_config})
6969

7070
@abstractmethod
71-
def questions(self) -> Questions:
71+
def questions(self) -> list[CzQuestion]:
7272
"""Questions regarding the commit message."""
7373

7474
@abstractmethod

‎commitizen/cz/conventional_commits/conventional_commits.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from commitizen import defaults
55
from commitizen.cz.base import BaseCommitizen
66
from commitizen.cz.utils import multiple_line_breaker, required_validator
7-
from commitizen.defaults import Questions
7+
from commitizen.question import CzQuestion, CzQuestionModel
88

99
__all__ = ["ConventionalCommitsCz"]
1010

@@ -40,8 +40,8 @@ class ConventionalCommitsCz(BaseCommitizen):
4040
}
4141
changelog_pattern = defaults.BUMP_PATTERN
4242

43-
def questions(self) -> Questions:
44-
return [
43+
def questions(self) -> list[CzQuestion]:
44+
questions= [
4545
{
4646
"type": "list",
4747
"name": "prefix",
@@ -146,6 +146,9 @@ def questions(self) -> Questions:
146146
),
147147
},
148148
]
149+
return [
150+
CzQuestionModel.model_validate({"question": q}).question for q in questions
151+
]
149152

150153
def message(self, answers: dict) -> str:
151154
prefix = answers["prefix"]

‎commitizen/cz/customize/customize.py‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from typing import TYPE_CHECKING
44

5+
from commitizen.question import CzQuestion, CzQuestionModel
6+
57
if TYPE_CHECKING:
68
from jinja2 import Template
79
else:
@@ -14,7 +16,6 @@
1416
from commitizen import defaults
1517
from commitizen.config import BaseConfig
1618
from commitizen.cz.base import BaseCommitizen
17-
from commitizen.defaults import Questions
1819
from commitizen.exceptions import MissingCzCustomizeConfigError
1920

2021
__all__ = ["CustomizeCommitsCz"]
@@ -45,8 +46,11 @@ def __init__(self, config: BaseConfig):
4546
if value := self.custom_settings.get(attr_name):
4647
setattr(self, attr_name, value)
4748

48-
def questions(self) -> Questions:
49-
return self.custom_settings.get("questions", [{}])
49+
def questions(self) -> list[CzQuestion]:
50+
questions = self.custom_settings.get("questions", [{}])
51+
return [
52+
CzQuestionModel.model_validate({"question": q}).question for q in questions
53+
]
5054

5155
def message(self, answers: dict) -> str:
5256
message_template = Template(self.custom_settings.get("message_template", ""))

‎commitizen/cz/jira/jira.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import os
22

33
from commitizen.cz.base import BaseCommitizen
4-
from commitizen.defaults import Questions
4+
from commitizen.question import CzQuestion, CzQuestionModel
55

66
__all__ = ["JiraSmartCz"]
77

88

99
class JiraSmartCz(BaseCommitizen):
10-
def questions(self) -> Questions:
11-
return [
10+
def questions(self) -> list[CzQuestion]:
11+
questions= [
1212
{
1313
"type": "input",
1414
"name": "message",
@@ -42,6 +42,9 @@ def questions(self) -> Questions:
4242
"filter": lambda x: "#comment " + x if x else "",
4343
},
4444
]
45+
return [
46+
CzQuestionModel.model_validate({"question": q}).question for q in questions
47+
]
4548

4649
def message(self, answers: dict) -> str:
4750
return " ".join(

‎commitizen/defaults.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import Any, TypedDict
88

99
# Type
10-
Questions = Iterable[MutableMapping[str, Any]]
10+
Questions = Iterable[MutableMapping[str, Any]]# TODO: deprecate this?
1111

1212

1313
class CzSettings(TypedDict, total=False):

‎commitizen/question.py‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from typing import Callable, Literal, Optional, Union
2+
3+
from pydantic import BaseModel, Field
4+
5+
6+
class CzModel(BaseModel):
7+
def model_dump(self, **kwargs):
8+
return super().model_dump(exclude_unset=True, **kwargs)
9+
10+
11+
class Choice(CzModel):
12+
value: str
13+
name: str
14+
key: Optional[str] = None
15+
16+
17+
class QuestionBase(CzModel):
18+
name: str
19+
message: str
20+
21+
22+
class ListQuestion(QuestionBase):
23+
type: Literal["list"]
24+
choices: list[Choice]
25+
use_shortcuts: Optional[bool] = None
26+
27+
28+
class SelectQuestion(QuestionBase):
29+
type: Literal["select"]
30+
choices: list[Choice]
31+
use_search_filter: Optional[bool] = None # TODO: confirm type
32+
use_jk_keys: Optional[bool] = None
33+
34+
35+
class InputQuestion(QuestionBase):
36+
type: Literal["input"]
37+
filter: Optional[Callable[[str], str]] = None
38+
39+
40+
class ConfirmQuestion(QuestionBase):
41+
type: Literal["confirm"]
42+
default: Optional[bool] = None
43+
44+
45+
CzQuestion = Union[ListQuestion, SelectQuestion, InputQuestion, ConfirmQuestion]
46+
47+
48+
class CzQuestionModel(CzModel):
49+
question: CzQuestion = Field(discriminator="type")

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /