tgit 0.10.0__tar.gz → 0.10.2__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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: tgit
3
- Version: 0.10.0
3
+ Version: 0.10.2
4
4
  Summary: Tool for Git Interaction Temptation (tgit): An elegant CLI tool that simplifies and streamlines your Git workflow, making version control a breeze.
5
5
  Author-email: Jannchie <jannchie@gmail.com>
6
6
  License-Expression: MIT
@@ -15,6 +15,7 @@ Classifier: Typing :: Typed
15
15
  Requires-Python: >=3.11
16
16
  Requires-Dist: gitpython>=3.1.43
17
17
  Requires-Dist: inquirer>=3.4.0
18
+ Requires-Dist: jinja2>=3.1.4
18
19
  Requires-Dist: openai>=1.52.0
19
20
  Requires-Dist: pyyaml>=6.0.2
20
21
  Requires-Dist: rich>=13.9.2
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tgit"
3
- version = "0.10.0"
3
+ version = "0.10.2"
4
4
  description = "Tool for Git Interaction Temptation (tgit): An elegant CLI tool that simplifies and streamlines your Git workflow, making version control a breeze."
5
5
  authors = [{ name = "Jannchie", email = "jannchie@gmail.com" }]
6
6
  dependencies = [
@@ -9,6 +9,7 @@ dependencies = [
9
9
  "inquirer>=3.4.0",
10
10
  "gitpython>=3.1.43",
11
11
  "openai>=1.52.0",
12
+ "jinja2>=3.1.4",
12
13
  ]
13
14
  readme = { content-type = "text/markdown", file = "README.md" }
14
15
  requires-python = ">= 3.11"
@@ -28,10 +29,6 @@ license = "MIT"
28
29
  requires = ["hatchling"]
29
30
  build-backend = "hatchling.build"
30
31
 
31
- [tool.rye]
32
- managed = true
33
- dev-dependencies = ["black>=24.10.0", "isort>=5.13.2"]
34
-
35
32
  [tool.black]
36
33
  line-length = 160
37
34
 
@@ -43,3 +40,19 @@ packages = ["tgit"]
43
40
 
44
41
  [project.scripts]
45
42
  tgit = "tgit:cli.main"
43
+
44
+ [tool.ruff]
45
+ line-length = 140
46
+ select = ["ALL"]
47
+
48
+ ignore = [
49
+ "PGH",
50
+ "RUF003",
51
+ "BLE001",
52
+ "ERA001",
53
+ "FIX002",
54
+ "TD002",
55
+ "TD003",
56
+ "D",
57
+ "TRY300",
58
+ ]
@@ -1,13 +1,15 @@
1
+ import argparse
2
+
1
3
  from tgit.utils import simple_run_command
2
4
 
3
5
 
4
- def define_add_parser(subparsers):
6
+ def define_add_parser(subparsers: argparse._SubParsersAction) -> None:
5
7
  parser_add = subparsers.add_parser("add", help="same as git add")
6
8
  parser_add.add_argument("files", help="files to add", nargs="*")
7
9
  parser_add.set_defaults(func=handle_add)
8
10
 
9
11
 
10
- def handle_add(args):
12
+ def handle_add(args: argparse.Namespace) -> None:
11
13
  files = " ".join(args.files)
12
14
  command = f"git add {files}"
13
15
  simple_run_command(command)
@@ -1,23 +1,27 @@
1
+ import logging
1
2
  import re
2
3
  import warnings
4
+ from argparse import _SubParsersAction
3
5
  from collections import defaultdict
4
6
  from dataclasses import dataclass
7
+ from pathlib import Path
5
8
 
6
9
  import git
7
10
 
11
+ logger = logging.getLogger("tgit")
8
12
 
9
- def get_latest_git_tag(repo: git.Repo):
13
+
14
+ def get_latest_git_tag(repo: git.Repo) -> str:
10
15
  return get_tag_by_idx(repo, -1)
11
16
 
12
17
 
13
- def get_tag_by_idx(repo: git.Repo, idx: int):
18
+ def get_tag_by_idx(repo: git.Repo, idx: int) -> str:
14
19
  try:
15
20
  if tags := sorted(repo.tags, key=lambda t: t.commit.committed_datetime):
16
21
  return tags[idx].name
17
- else:
18
- return None
19
- except Exception as e:
20
- print(f"Error: {e}")
22
+ return None
23
+ except Exception:
24
+ logger.exception("Can't find tag by index %s", idx)
21
25
  return None
22
26
 
23
27
 
@@ -28,15 +32,15 @@ def get_first_commit_hash(repo: git.Repo) -> str:
28
32
  )
29
33
 
30
34
 
31
- def get_commit_hash_from_tag(repo: git.Repo, tag):
35
+ def get_commit_hash_from_tag(repo: git.Repo, tag: str) -> str:
32
36
  try:
33
37
  return repo.tags[tag].commit.hexsha
34
- except Exception as e:
35
- print(f"Error: {e}")
38
+ except Exception:
39
+ logger.exception("Can't find tag %s", tag)
36
40
  return None
37
41
 
38
42
 
39
- def define_changelog_parser(subparsers):
43
+ def define_changelog_parser(subparsers: _SubParsersAction) -> None:
40
44
  parser_changelog = subparsers.add_parser("changelog", help="generate changelogs")
41
45
  parser_changelog.add_argument("-f", "--from", help="From hash/tag", type=str, dest="from_raw")
42
46
  parser_changelog.add_argument("-t", "--to", help="To hash/tag", type=str, dest="to_raw")
@@ -64,29 +68,29 @@ class ChangelogArgs:
64
68
  output: str
65
69
 
66
70
 
67
- def get_simple_hash(repo: git.Repo, hash, length=7):
71
+ def get_simple_hash(repo: git.Repo, git_hash: str, length: int = 7) -> str:
68
72
  try:
69
- return repo.git.rev_parse(hash, short=length)
70
- except Exception as e:
71
- print(f"Error: {e}")
73
+ return repo.git.rev_parse(git_hash, short=length)
74
+ except Exception:
75
+ logger.exception("Can't find hash %s", git_hash)
72
76
  return None
73
77
 
74
78
 
75
- def ref_to_hash(repo: git.Repo, ref: str, length=7):
79
+ def ref_to_hash(repo: git.Repo, ref: str, length: int = 7) -> str:
76
80
  try:
77
81
  return repo.git.rev_parse(ref, short=length)
78
- except Exception as e:
79
- print(f"Error: {e}")
82
+ except Exception:
83
+ logger.exception("Can't find ref %s", ref)
80
84
  return None
81
85
 
82
86
 
83
87
  commit_pattern = re.compile(
84
- r"(?P<emoji>:.+:|(\uD83C[\uDF00-\uDFFF])|(\uD83D[\uDC00-\uDE4F\uDE80-\uDEFF])|[\u2600-\u2B55])?( *)?(?P<type>[a-z]+)(\((?P<scope>.+?)\))?(?P<breaking>!)?: (?P<description>.+)",
88
+ r"(?P<emoji>:.+:|(\uD83C[\uDF00-\uDFFF])|(\uD83D[\uDC00-\uDE4F\uDE80-\uDEFF])|[\u2600-\u2B55])?( *)?(?P<type>[a-z]+)(\((?P<scope>.+?)\))?(?P<breaking>!)?: (?P<description>.+)", # noqa: E501
85
89
  re.IGNORECASE,
86
90
  )
87
91
 
88
92
 
89
- def resolve_from_ref(repo, from_raw):
93
+ def resolve_from_ref(repo: git.Repo, from_raw: str) -> str:
90
94
  if from_raw is not None:
91
95
  return from_raw
92
96
  last_tag = get_latest_git_tag(repo)
@@ -98,18 +102,18 @@ class Author:
98
102
  name: str
99
103
  email: str
100
104
 
101
- def __str__(self):
105
+ def __str__(self) -> str:
102
106
  return f"{self.name} <{self.email}>"
103
107
 
104
108
 
105
109
  class TGITCommit:
106
- def __init__(self, repo: git.Repo, commit: git.Commit, message_dict: dict):
110
+ def __init__(self, repo: git.Repo, commit: git.Commit, message_dict: dict) -> None:
107
111
  commit_date = commit.committed_datetime
108
112
 
109
113
  co_author_raws = [line for line in commit.message.split("\n") if line.lower().startswith("co-authored-by:")]
110
114
  co_author_pattern = re.compile(r"Co-authored-by: (?P<name>.+?) <(?P<email>.+?)>", re.IGNORECASE)
111
115
  co_authors = [co_author_pattern.match(co_author).groupdict() for co_author in co_author_raws]
112
- authors = [{"name": commit.author.name, "email": commit.author.email}] + co_authors
116
+ authors = [{"name": commit.author.name, "email": commit.author.email}, *co_authors]
113
117
  self.authors: list[Author] = [Author(**kwargs) for kwargs in authors]
114
118
  self.date = commit_date
115
119
  self.emoji = message_dict.get("emoji")
@@ -131,14 +135,14 @@ class TGITCommit:
131
135
  )
132
136
 
133
137
 
134
- def format_names(names):
138
+ def format_names(names: list[str]) -> str:
135
139
  if not names:
136
140
  return ""
137
141
 
138
142
  if len(names) == 1:
139
143
  return f"By {names[0]}"
140
144
 
141
- if len(names) == 2:
145
+ if len(names) == 2: # noqa: PLR2004
142
146
  return f"By {names[0]} and {names[1]}"
143
147
 
144
148
  formatted_names = ", ".join(names[:-1])
@@ -147,7 +151,7 @@ def format_names(names):
147
151
  return f"By {formatted_names}"
148
152
 
149
153
 
150
- def get_remote_uri(url: str):
154
+ def get_remote_uri(url: str) -> str:
151
155
  # SSH URL regex, with groups for domain, namespace and repo name
152
156
  ssh_pattern = re.compile(r"git@([\w\.]+):(.+)/(.+)\.git")
153
157
  # HTTPS URL regex, with groups for domain, namespace and repo name
@@ -184,7 +188,7 @@ def group_commits_by_type(commits: list[TGITCommit]) -> dict[str, list[TGITCommi
184
188
  return commits_by_type
185
189
 
186
190
 
187
- def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: str, to_ref: str, remote_uri: str = None) -> str:
191
+ def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: str, to_ref: str, remote_uri: str | None = None) -> str:
188
192
  order = ["breaking", "feat", "fix", "refactor", "perf", "style", "docs", "chore"]
189
193
  names = [
190
194
  ":rocket: Breaking Changes",
@@ -203,7 +207,7 @@ def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: s
203
207
  else:
204
208
  out_str += f"{from_ref}...{to_ref}\n\n"
205
209
 
206
- def get_hash_link(commit: TGITCommit):
210
+ def get_hash_link(commit: TGITCommit) -> str:
207
211
  if remote_uri:
208
212
  return f"[{commit.hash}](https://{remote_uri}/commit/{commit.hash})"
209
213
  return commit.hash
@@ -215,7 +219,6 @@ def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: s
215
219
  # Sort commits by scope, if scope is None, put it to last
216
220
  commits.sort(key=lambda c: c.scope or "zzzzz")
217
221
  for commit in commits:
218
-
219
222
  authors_str = format_names([f"[{a.name}](mailto:{a.email})" for a in commit.authors])
220
223
  if commit.scope:
221
224
  line = f"- **{commit.scope}**: {commit.description} - {authors_str} in {get_hash_link(commit)}\n"
@@ -226,39 +229,39 @@ def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: s
226
229
  return out_str
227
230
 
228
231
 
229
- def handle_changelog(args: ChangelogArgs):
232
+ def handle_changelog(args: ChangelogArgs) -> None:
230
233
  repo = git.Repo(args.path)
231
234
 
232
235
  if args.output:
233
- output_file = open(args.output, "w")
234
- # 获取所有 tags
235
- tags = repo.tags
236
- # 获取第一个 commit
237
- first_commit = get_first_commit_hash(repo)
238
- points = [first_commit] + [tag.name for tag in tags]
239
- points.reverse()
240
- changelogs = ""
241
- for i in range(len(points) - 1):
242
- to_ref = points[i]
243
- from_ref = points[i + 1]
244
- changelog = get_changelog_by_range(repo, from_ref, to_ref)
245
- changelogs += changelog
246
- output_file.write(changelogs.strip("\n") + "\n")
236
+ with Path(args.output).open("w") as output_file:
237
+ # 获取所有 tags
238
+ tags = repo.tags
239
+ # 获取第一个 commit
240
+ first_commit = get_first_commit_hash(repo)
241
+ points = [first_commit] + [tag.name for tag in tags]
242
+ points.reverse()
243
+ changelogs = ""
244
+ for i in range(len(points) - 1):
245
+ to_ref = points[i]
246
+ from_ref = points[i + 1]
247
+ changelog = get_changelog_by_range(repo, from_ref, to_ref)
248
+ changelogs += changelog
249
+ output_file.write(changelogs.strip("\n") + "\n")
247
250
  from_raw = args.from_raw
248
251
  to_raw = args.to_raw
249
252
 
250
253
  from_ref, to_ref = get_git_commits_range(repo, from_raw, to_raw)
251
254
  changelog = get_changelog_by_range(repo, from_ref, to_ref)
252
- print()
253
- print(changelog)
255
+ print() # noqa: T201
256
+ print(changelog) # noqa: T201
254
257
 
255
258
 
256
- def get_changelog_by_range(repo: git.Repo, from_ref: str, to_ref: str):
259
+ def get_changelog_by_range(repo: git.Repo, from_ref: str, to_ref: str) -> str:
257
260
  try:
258
261
  origin_url = repo.remote().url
259
262
  remote_uri = get_remote_uri(origin_url)
260
263
  except ValueError:
261
- warnings.warn("Origin not found, some of the link generation functions could not be enabled.")
264
+ warnings.warn("Origin not found, some of the link generation functions could not be enabled.", stacklevel=2)
262
265
  remote_uri = None
263
266
 
264
267
  tgit_commits = get_commits(repo, from_ref, to_ref)
@@ -266,7 +269,7 @@ def get_changelog_by_range(repo: git.Repo, from_ref: str, to_ref: str):
266
269
  return generate_changelog(commits_by_type, from_ref, to_ref, remote_uri)
267
270
 
268
271
 
269
- def get_git_commits_range(repo: git.Repo, from_raw: str, to_raw: str):
272
+ def get_git_commits_range(repo: git.Repo, from_raw: str, to_raw: str) -> tuple[str, str]:
270
273
  from_ref = resolve_from_ref(repo, from_raw)
271
274
  to_ref = "HEAD" if to_raw is None else to_raw
272
275
  if to_ref == "HEAD":
@@ -13,7 +13,7 @@ from tgit.version import define_version_parser
13
13
  rich.traceback.install()
14
14
 
15
15
 
16
- def main():
16
+ def main() -> None:
17
17
  parser = argparse.ArgumentParser(
18
18
  description="TGIT cli",
19
19
  prog="tgit",
@@ -31,7 +31,7 @@ def main():
31
31
  handle(parser, args)
32
32
 
33
33
 
34
- def handle(parser, args):
34
+ def handle(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
35
35
  if hasattr(args, "func"):
36
36
  args.func(args)
37
37
  elif args.version:
@@ -1,21 +1,27 @@
1
1
  import argparse
2
+ import importlib.resources
2
3
  import itertools
3
- import os
4
4
  from dataclasses import dataclass
5
- from typing import Optional
5
+ from pathlib import Path
6
6
 
7
7
  import git
8
+ from jinja2 import Environment, FileSystemLoader
8
9
  from openai import AuthenticationError, OpenAI
9
10
  from pydantic import BaseModel
10
- from rich import print
11
+ from rich import print # noqa: A004
11
12
 
12
13
  from tgit.settings import settings
13
14
  from tgit.utils import get_commit_command, run_command, type_emojis
14
15
 
15
- commit_type = ["feat", "fix", "chore", "docs", "style", "refactor", "perf", "wip"]
16
+ with importlib.resources.path("tgit", "prompts") as prompt_path:
17
+ env = Environment(loader=FileSystemLoader(prompt_path), autoescape=True)
16
18
 
19
+ commit_types = ["feat", "fix", "chore", "docs", "style", "refactor", "perf", "wip"]
20
+ commit_file = "commit.txt"
21
+ commit_prompt_template = env.get_template("commit.txt")
17
22
 
18
- def define_commit_parser(subparsers: argparse._SubParsersAction):
23
+
24
+ def define_commit_parser(subparsers: argparse._SubParsersAction) -> None:
19
25
  commit_type = ["feat", "fix", "chore", "docs", "style", "refactor", "perf"]
20
26
  commit_settings = settings.get("commit", {})
21
27
  types_settings = commit_settings.get("types", [])
@@ -26,7 +32,7 @@ def define_commit_parser(subparsers: argparse._SubParsersAction):
26
32
  parser_commit = subparsers.add_parser("commit", help="commit changes following the conventional commit format")
27
33
  parser_commit.add_argument(
28
34
  "message",
29
- help="commit message, the first word should be the type, if the message is more than two parts, the second part should be the scope",
35
+ help="the first word should be the type, if the message is more than two parts, the second part should be the scope",
30
36
  nargs="*",
31
37
  )
32
38
  parser_commit.add_argument("-v", "--verbose", action="count", default=0, help="increase output verbosity")
@@ -46,35 +52,29 @@ class CommitArgs:
46
52
 
47
53
  class CommitData(BaseModel):
48
54
  type: str
49
- scope: Optional[str]
55
+ scope: str | None
50
56
  msg: str
51
57
  is_breaking: bool
52
58
 
53
59
 
54
60
  def get_ai_command() -> str | None:
55
61
  client = OpenAI()
56
- # 获取用户执行该脚本所在的目录
57
- current_dir = os.getcwd()
62
+ current_dir = Path.cwd()
58
63
  try:
59
64
  repo = git.Repo(current_dir, search_parent_directories=True)
60
65
  except git.InvalidGitRepositoryError:
61
66
  print("[yellow]Not a git repository[/yellow]")
62
- return
67
+ return None
63
68
  diff = repo.git.diff("--cached")
64
69
  if not diff:
65
70
  print("[yellow]No changes to commit, please add some changes before using AI[/yellow]")
66
- return
67
- types = "|".join(commit_type)
71
+ return None
68
72
  try:
69
73
  chat_completion = client.beta.chat.completions.parse(
70
74
  messages=[
71
75
  {
72
76
  "role": "system",
73
- "content": "You are a git bot. You should read the diff and suggest a commit message. "
74
- + "Only if the changes are not compatible with previous versions (change the API, break the build, etc.), you should suggest a breaking change. "
75
- + f"The type should be one of {types}. The message should in all lowercase. And it shoud be short, in just few words. "
76
- + "The scope should be short, it is better to be a single word. "
77
- + "The message should cover all the changes in the diff. It should be in present tense. If the change has many parts, you can && to separate them, and you should also shorten the message. ",
77
+ "content": commit_prompt_template.render(types=commit_types),
78
78
  },
79
79
  {"role": "user", "content": diff},
80
80
  ],
@@ -84,16 +84,20 @@ def get_ai_command() -> str | None:
84
84
  )
85
85
  except AuthenticationError:
86
86
  print("[red]Could not authenticate with OpenAI, please check your API key.[/red]")
87
- return
87
+ return None
88
88
  resp = chat_completion.choices[0].message.parsed
89
- return get_commit_command(resp.type, resp.scope, resp.msg, settings.get("commit", {}).get("emoji", False), resp.is_breaking)
90
-
89
+ return get_commit_command(
90
+ resp.type,
91
+ resp.scope,
92
+ resp.msg,
93
+ use_emoji=settings.get("commit", {}).get("emoji", False),
94
+ is_breaking=resp.is_breaking,
95
+ )
91
96
 
92
- def handle_commit(args: CommitArgs):
93
97
 
94
- global commit_type
98
+ def handle_commit(args: CommitArgs) -> None:
95
99
  prefix = ["", "!"]
96
- choices = ["".join(data) for data in itertools.product(commit_type, prefix)] + ["ci", "test", "version"]
100
+ choices = ["".join(data) for data in itertools.product(commit_types, prefix)] + ["ci", "test", "version"]
97
101
 
98
102
  if args.ai:
99
103
  command = get_ai_command()
@@ -105,7 +109,7 @@ def handle_commit(args: CommitArgs):
105
109
  print("Please provide a commit message, or use --ai to generate by AI")
106
110
  return
107
111
  commit_type = messages[0]
108
- if len(messages) > 2:
112
+ if len(messages) > 2: # noqa: PLR2004
109
113
  commit_scope = messages[1]
110
114
  commit_msg = " ".join(messages[2:])
111
115
  else:
@@ -116,8 +120,8 @@ def handle_commit(args: CommitArgs):
116
120
  print(f"Valid types: {choices}")
117
121
  return
118
122
  use_emoji = args.emoji
119
- if use_emoji == False:
123
+ if use_emoji is False:
120
124
  use_emoji = settings.get("commit", {}).get("emoji", False)
121
125
  is_breaking = args.breaking
122
- command = get_commit_command(commit_type, commit_scope, commit_msg, use_emoji, is_breaking)
126
+ command = get_commit_command(commit_type, commit_scope, commit_msg, use_emoji=use_emoji, is_breaking=is_breaking)
123
127
  run_command(command)
@@ -0,0 +1,26 @@
1
+ You are a git bot. You should read the diff and suggest a commit message.
2
+
3
+ Type:
4
+
5
+ The type should be one of {{ types | join(', ') }}.
6
+
7
+ Scope:
8
+
9
+ The scope should be short, it is better to be a single word, if there are more than one word, you should use '-'
10
+
11
+ Message:
12
+
13
+ The message should in all lowercase.
14
+ The message should be short, in just few words.
15
+ The message should cover all the changes in the diff.
16
+ The message should be in present tense.
17
+ If the change has many parts, you can '&&' to separate them, and you should also shorten the message.
18
+
19
+ Breaking Change:
20
+
21
+ Only if the changes are not compatible with previous versions (change the API, break the build, etc.), you should suggest a breaking change.
22
+
23
+ Additional Considerations:
24
+
25
+ Search the name and instruction online for the copyright content check.
26
+ Make sure to search the name and instruction online for the copyright content check.
@@ -26,7 +26,7 @@ type_emojis = {
26
26
  }
27
27
 
28
28
 
29
- def get_commit_command(commit_type: str, commit_scope: Optional[str], commit_msg: str, use_emoji=False, is_breaking=False):
29
+ def get_commit_command(commit_type: str, commit_scope: str | None, commit_msg: str, *, use_emoji: bool = False, is_breaking: bool = False):
30
30
  if commit_type.endswith("!"):
31
31
  commit_type = commit_type[:-1]
32
32
  is_breaking = True
@@ -42,8 +42,8 @@ def get_commit_command(commit_type: str, commit_scope: Optional[str], commit_msg
42
42
  return f'git commit -m "{msg}"'
43
43
 
44
44
 
45
- def simple_run_command(command: str):
46
- process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
45
+ def simple_run_command(command: str) -> None:
46
+ process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # noqa: S602
47
47
  stdout, stderr = process.communicate()
48
48
  if stderr != b"" and process.returncode != 0:
49
49
  sys.stderr.write(stderr.decode())
@@ -51,7 +51,7 @@ def simple_run_command(command: str):
51
51
  sys.stdout.write(stdout.decode())
52
52
 
53
53
 
54
- def run_command(command: str):
54
+ def run_command(command: str) -> None:
55
55
  if settings.get("show_command", True):
56
56
  panel = Panel.fit(
57
57
  Syntax(command, "bash", line_numbers=False, theme="github-dark", background_color="default", word_wrap=True),
@@ -62,11 +62,10 @@ def run_command(command: str):
62
62
  title_align="left",
63
63
  subtitle_align="right",
64
64
  )
65
- print()
65
+ print() # noqa: T201
66
66
  console.print(panel)
67
67
 
68
68
  if not settings.get("skip_confirm", False):
69
-
70
69
  ok = inquirer.prompt([inquirer.Confirm("continue", message="Do you want to continue?", default=True)])
71
70
  if not ok or not ok["continue"]:
72
71
  return