cave-cli 3.6.0b4__tar.gz → 3.6.1__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 (51) hide show
  1. {cave_cli-3.6.0b4/cave_cli.egg-info → cave_cli-3.6.1}/PKG-INFO +1 -1
  2. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/cli.py +1 -2
  3. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/create.py +6 -1
  4. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/doctor.py +4 -1
  5. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/list_cmd.py +3 -1
  6. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/list_versions.py +6 -2
  7. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/purge.py +13 -5
  8. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/reset.py +3 -1
  9. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/run.py +14 -6
  10. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/sync_cmd.py +7 -2
  11. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/uninstall.py +3 -1
  12. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/update.py +11 -3
  13. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/upgrade.py +44 -26
  14. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/version.py +7 -3
  15. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/cache.py +3 -9
  16. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/display.py +55 -27
  17. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/docker.py +3 -7
  18. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/env.py +1 -2
  19. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/sync.py +16 -9
  20. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/validate.py +4 -3
  21. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/version.py +8 -3
  22. {cave_cli-3.6.0b4 → cave_cli-3.6.1/cave_cli.egg-info}/PKG-INFO +1 -1
  23. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/pyproject.toml +1 -1
  24. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_display.py +68 -16
  25. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_env.py +6 -1
  26. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_sync.py +10 -3
  27. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_upgrade.py +43 -3
  28. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_validate.py +24 -12
  29. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/utils/prettify.py +11 -11
  30. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/LICENSE +0 -0
  31. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/NOTICE.md +0 -0
  32. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/README.md +0 -0
  33. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/__init__.py +0 -0
  34. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/__init__.py +0 -0
  35. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/kill.py +0 -0
  36. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/prettify.py +0 -0
  37. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/test.py +0 -0
  38. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/theme.py +0 -0
  39. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/__init__.py +0 -0
  40. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/constants.py +0 -0
  41. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/git.py +0 -0
  42. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/logger.py +0 -0
  43. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/net.py +0 -0
  44. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/subprocess.py +0 -0
  45. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/SOURCES.txt +0 -0
  46. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/dependency_links.txt +0 -0
  47. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/entry_points.txt +0 -0
  48. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/requires.txt +0 -0
  49. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/top_level.txt +0 -0
  50. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/setup.cfg +0 -0
  51. {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_net.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cave_cli
3
- Version: 3.6.0b4
3
+ Version: 3.6.1
4
4
  Summary: CLI for creating and managing Docker-based CAVE web applications.
5
5
  Author-email: MIT-CAVE <cave-contact@mit.edu>
6
6
  License: Apache-2.0
@@ -164,8 +164,7 @@ def main():
164
164
  "reset",
165
165
  aliases=["reset-db"],
166
166
  help=(
167
- "Remove Docker containers and volumes, "
168
- "then rebuild from scratch"
167
+ "Remove Docker containers and volumes, " "then rebuild from scratch"
169
168
  ),
170
169
  )
171
170
  add_global_args(p_reset)
@@ -8,7 +8,12 @@ from pathlib import Path
8
8
  from cave_cli.commands.reset import reset
9
9
  from cave_cli.commands.run import run_cave
10
10
  from cave_cli.utils.constants import HTTPS_URL
11
- from cave_cli.utils.display import print_section, step_done, step_fail, step_start
11
+ from cave_cli.utils.display import (
12
+ print_section,
13
+ step_done,
14
+ step_fail,
15
+ step_start,
16
+ )
12
17
  from cave_cli.utils.docker import build_image, generate_secret_key
13
18
  from cave_cli.utils.env import create_env_interactive
14
19
  from cave_cli.utils.git import add, branch_rename, clone, commit, init
@@ -59,7 +59,10 @@ def check_uv(return_path: bool = True) -> tuple[bool, str, str | None]:
59
59
  return output
60
60
  except Exception:
61
61
  pass
62
- output = False, "uv is not installed. Please install uv: https://github.com/astral-sh/uv"
62
+ output = (
63
+ False,
64
+ "uv is not installed. Please install uv: https://github.com/astral-sh/uv",
65
+ )
63
66
  if return_path:
64
67
  return output + (None,)
65
68
  return output
@@ -21,6 +21,7 @@ def list_cmd(args: argparse.Namespace) -> None:
21
21
  if show_all:
22
22
  print_section("CAVE App Containers (All)")
23
23
  from cave_cli.utils.display import _QUIET
24
+
24
25
  for suffix in ("_django", "_db_host", "_redis_host", "_nginx_host"):
25
26
  for name in get_all_containers(suffix):
26
27
  if not _QUIET:
@@ -42,7 +43,8 @@ def list_cmd(args: argparse.Namespace) -> None:
42
43
  else:
43
44
  port = get_container_host_port(f"{app_name}_django")
44
45
  print_key_value(app_name, f"http://localhost:{port}")
45
-
46
+
46
47
  from cave_cli.utils.display import _QUIET
48
+
47
49
  if not _QUIET:
48
50
  print("")
@@ -48,7 +48,8 @@ def list_versions(args: argparse.Namespace) -> None:
48
48
 
49
49
  all_versions = sorted(
50
50
  (
51
- v for v in set().union(*repo_tags.values())
51
+ v
52
+ for v in set().union(*repo_tags.values())
52
53
  if not pattern or fnmatch.fnmatch(v, pattern)
53
54
  ),
54
55
  key=version_tuple,
@@ -88,7 +89,10 @@ def list_versions(args: argparse.Namespace) -> None:
88
89
  row = indent + f"{v:<{version_w}}"
89
90
  for r, w in zip(repos, col_w):
90
91
  mark = f"{GREEN}✓{RESET}" if v in repo_tags[r] else ""
91
- row += " " * pad + f"{mark:^{w + len(GREEN) + len(RESET) if mark else w}}"
92
+ row += (
93
+ " " * pad
94
+ + f"{mark:^{w + len(GREEN) + len(RESET) if mark else w}}"
95
+ )
92
96
  print(row)
93
97
 
94
98
  if hidden:
@@ -64,11 +64,19 @@ def purge(args: argparse.Namespace) -> None:
64
64
  "Some files are owned by root (created by Docker). "
65
65
  "Removing via Docker..."
66
66
  )
67
- run_and_log([
68
- "docker", "run", "--rm",
69
- "-v", f"{abs_path}:/purge",
70
- "alpine", "rm", "-rf", "/purge",
71
- ])
67
+ run_and_log(
68
+ [
69
+ "docker",
70
+ "run",
71
+ "--rm",
72
+ "-v",
73
+ f"{abs_path}:/purge",
74
+ "alpine",
75
+ "rm",
76
+ "-rf",
77
+ "/purge",
78
+ ]
79
+ )
72
80
  if os.path.isdir(abs_path):
73
81
  try:
74
82
  shutil.rmtree(abs_path)
@@ -46,5 +46,7 @@ def reset(
46
46
  verbose=getattr(args, "verbose", False),
47
47
  loglevel=getattr(args, "loglevel", "INFO"),
48
48
  )
49
- run_cave(app_dir, app_name, reset_args, skip_header=True, skip_build=skip_build)
49
+ run_cave(
50
+ app_dir, app_name, reset_args, skip_header=True, skip_build=skip_build
51
+ )
50
52
  step_done("Reset complete")
@@ -49,14 +49,21 @@ def run_cave(
49
49
  interactive = getattr(args, "interactive", False) or getattr(
50
50
  args, "it", False
51
51
  )
52
- show_all = getattr(args, "show_all", False) or getattr(args, "verbose", False) or getattr(args, "loglevel", "INFO").upper() == "DEBUG"
52
+ show_all = (
53
+ getattr(args, "show_all", False)
54
+ or getattr(args, "verbose", False)
55
+ or getattr(args, "loglevel", "INFO").upper() == "DEBUG"
56
+ )
53
57
  entrypoint = getattr(args, "entrypoint", None) or "./utils/run_server.sh"
54
58
  docker_args_str = getattr(args, "docker_args", "") or ""
55
59
  extra_docker_args = shlex.split(docker_args_str) if docker_args_str else []
56
60
  ip_port_arg = getattr(args, "ip_port", None)
57
61
  command_args = getattr(args, "command_args", []) or []
58
62
  extra_env = getattr(args, "extra_env", {}) or {}
59
- quiet = getattr(args, "quiet", False) or getattr(args, "loglevel", "INFO").upper() == "SILENT"
63
+ quiet = (
64
+ getattr(args, "quiet", False)
65
+ or getattr(args, "loglevel", "INFO").upper() == "SILENT"
66
+ )
60
67
 
61
68
  is_server_run = entrypoint == "./utils/run_server.sh" and not interactive
62
69
  use_tui = is_server_run and not show_all
@@ -180,7 +187,10 @@ def run_cave(
180
187
  else:
181
188
  step_done("Checking database")
182
189
  else:
183
- step_fail("Checking database", "Database container failed to become ready.")
190
+ step_fail(
191
+ "Checking database",
192
+ "Database container failed to become ready.",
193
+ )
184
194
  remove_containers(app_name)
185
195
  sys.exit(1)
186
196
 
@@ -190,9 +200,7 @@ def run_cave(
190
200
  if parsed:
191
201
  ip, port = parsed
192
202
  if not is_port_available(port):
193
- logger.error(
194
- "The specified port is in use. Please try another."
195
- )
203
+ logger.error("The specified port is in use. Please try another.")
196
204
  sys.exit(1)
197
205
 
198
206
  if is_server_run and not interactive:
@@ -5,14 +5,19 @@ import tempfile
5
5
 
6
6
  from cave_cli.commands.reset import reset
7
7
  from cave_cli.utils.constants import HTTPS_URL
8
- from cave_cli.utils.display import print_section, step_done, step_start, print_key_value
8
+ from cave_cli.utils.display import (
9
+ print_section,
10
+ step_done,
11
+ step_start,
12
+ print_key_value,
13
+ )
9
14
  from cave_cli.utils.git import clone
10
15
  from cave_cli.utils.logger import logger
11
16
  from cave_cli.utils.sync import sync_files
12
17
  from cave_cli.utils.validate import confirm_action, find_app_dir
13
18
 
14
19
 
15
- def sync_cmd(args: argparse.Namespace, do_reset: bool=True) -> None:
20
+ def sync_cmd(args: argparse.Namespace, do_reset: bool = True) -> None:
16
21
  """
17
22
  Usage:
18
23
 
@@ -30,7 +30,9 @@ def uninstall(args: argparse.Namespace) -> None:
30
30
  has_uv, uv_message, uv_path = check_uv()
31
31
  if not has_uv:
32
32
  logger.error(uv_message)
33
- logger.error(f"You may need to uninstall CAVE CLI manually based on how it was installed.")
33
+ logger.error(
34
+ f"You may need to uninstall CAVE CLI manually based on how it was installed."
35
+ )
34
36
  sys.exit(1)
35
37
 
36
38
  step_start("Removing installation")
@@ -26,16 +26,24 @@ def update(args: argparse.Namespace) -> None:
26
26
  - On Windows, the update runs in a new console window because Windows
27
27
  locks running executables and cave.exe cannot replace itself.
28
28
  """
29
- has_uv, uv_message, uv_path= check_uv()
29
+ has_uv, uv_message, uv_path = check_uv()
30
30
  if not has_uv:
31
31
  logger.error(uv_message)
32
- logger.error(f"The cave_cli package may need to be updated manually based on how it was installed.")
32
+ logger.error(
33
+ f"The cave_cli package may need to be updated manually based on how it was installed."
34
+ )
33
35
  sys.exit(1)
34
36
 
35
37
  version = getattr(args, "version", None)
36
38
  if version:
37
39
  label = f"Reinstalling CAVE CLI ({version})"
38
- cmd = [uv_path, "tool", "install", "--reinstall", f"cave_cli @ git+{CLI_REPO_URL}@{version}"]
40
+ cmd = [
41
+ uv_path,
42
+ "tool",
43
+ "install",
44
+ "--reinstall",
45
+ f"cave_cli @ git+{CLI_REPO_URL}@{version}",
46
+ ]
39
47
  else:
40
48
  label = "Updating CAVE CLI"
41
49
  cmd = [uv_path, "tool", "upgrade", "cave_cli"]
@@ -53,7 +53,9 @@ def migrate_3_6_0(app_dir: str) -> None:
53
53
  if utils_pyproject.exists():
54
54
  shutil.move(utils_pyproject, legacy_utils_dir / "pyproject.toml")
55
55
  if utils_extra_req.exists():
56
- shutil.move(utils_extra_req, legacy_utils_dir / "extra_requirements.txt")
56
+ shutil.move(
57
+ utils_extra_req, legacy_utils_dir / "extra_requirements.txt"
58
+ )
57
59
 
58
60
  # Remove VERSION file
59
61
  version_file = app_path / "VERSION"
@@ -68,12 +70,14 @@ def migrate_3_6_0(app_dir: str) -> None:
68
70
  legacy_cave_core.mkdir(exist_ok=True)
69
71
  shutil.move(models_file, legacy_cave_core / "models.py")
70
72
  except Exception as e:
71
- logger.warn(f"Failed to move cave_core/models.py to legacy/cave_core/models.py: {e}")
73
+ logger.warn(
74
+ f"Failed to move cave_core/models.py to legacy/cave_core/models.py: {e}"
75
+ )
72
76
 
73
77
  # Collect api requirements from cave_api/requirements.txt and cave_api/pyproject.toml
74
78
  # before moving/restructuring the cave_api directory
75
79
  api_requirements = []
76
-
80
+
77
81
  # 1. Pull from cave_api/requirements.txt
78
82
  cave_api_req = app_path / "cave_api" / "requirements.txt"
79
83
  if cave_api_req.exists():
@@ -91,7 +95,9 @@ def migrate_3_6_0(app_dir: str) -> None:
91
95
  try:
92
96
  with open(cave_api_pyproject, "rb") as f:
93
97
  cave_api_pyproject_data = tomllib.loads(f.read().decode())
94
- deps = cave_api_pyproject_data.get("project", {}).get("dependencies", [])
98
+ deps = cave_api_pyproject_data.get("project", {}).get(
99
+ "dependencies", []
100
+ )
95
101
  for dep in deps:
96
102
  dep = dep.strip()
97
103
  if dep and dep not in api_requirements:
@@ -116,23 +122,23 @@ def migrate_3_6_0(app_dir: str) -> None:
116
122
  content = content_bytes.decode()
117
123
 
118
124
  deps_str = "\n".join(f' "{dep}",' for dep in cleaned_requirements)
119
-
125
+
120
126
  if "[project.optional-dependencies]" in content:
121
- if re.search(r"api\s*=\s*\[", content):
127
+ if re.search(r"(?<![\w-])api\s*=\s*\[", content):
122
128
  content = re.sub(
123
- r"(api\s*=\s*\[)[^\]]*(\])",
129
+ r"(?<![\w-])(api\s*=\s*\[)[^\]]*(\])",
124
130
  f"\\1\n{deps_str}\n\\2",
125
131
  content,
126
- flags=re.DOTALL
132
+ flags=re.DOTALL,
127
133
  )
128
134
  else:
129
135
  content = re.sub(
130
136
  r"(\[project\.optional-dependencies\])",
131
137
  f"\\1\napi = [\n{deps_str}\n]",
132
- content
138
+ content,
133
139
  )
134
140
  else:
135
- content += f'\n[project.optional-dependencies]\napi = [\n{deps_str}\n]\n'
141
+ content += f"\n[project.optional-dependencies]\napi = [\n{deps_str}\n]\n"
136
142
 
137
143
  with open(pyproject_path, "wb") as f:
138
144
  f.write(content.encode())
@@ -157,12 +163,15 @@ def migrate_3_6_0(app_dir: str) -> None:
157
163
  shutil.move(cave_api, legacy_cave_api)
158
164
  shutil.copytree(legacy_cave_api / "cave_api", cave_api)
159
165
  else:
160
- logger.warn("Expected cave_api/cave_api directory not found, skipping API migration steps.")
166
+ logger.warn(
167
+ "Expected cave_api/cave_api directory not found, skipping API migration steps."
168
+ )
161
169
 
162
170
  # Update code references, skipping legacy/ and tool directories
163
171
  for py_file in app_path.rglob("*.py"):
164
172
  if any(
165
- part.startswith(".") or part in ("__pycache__", "venv", ".venv", ".nox", "legacy")
173
+ part.startswith(".")
174
+ or part in ("__pycache__", "venv", ".venv", ".nox", "legacy")
166
175
  for part in py_file.parts
167
176
  ):
168
177
  continue
@@ -171,10 +180,12 @@ def migrate_3_6_0(app_dir: str) -> None:
171
180
  new_content = content.replace("cave_api.cave_api", "cave_api")
172
181
  new_content = new_content.replace("cave_api/cave_api", "cave_api")
173
182
  new_content = new_content.replace(
174
- 'importlib.resources.files("cave_api") / "cave_api"', 'importlib.resources.files("cave_api")'
183
+ 'importlib.resources.files("cave_api") / "cave_api"',
184
+ 'importlib.resources.files("cave_api")',
175
185
  )
176
186
  new_content = new_content.replace(
177
- "importlib.resources.files('cave_api') / 'cave_api'", "importlib.resources.files('cave_api')"
187
+ "importlib.resources.files('cave_api') / 'cave_api'",
188
+ "importlib.resources.files('cave_api')",
178
189
  )
179
190
 
180
191
  if new_content != content:
@@ -203,17 +214,22 @@ def upgrade(args: argparse.Namespace) -> None:
203
214
  if os.path.exists(pyproject_path):
204
215
  try:
205
216
  import tomllib
217
+
206
218
  with open(pyproject_path, "rb") as f:
207
219
  pyproject = tomllib.load(f)
208
- api_deps = pyproject.get("project", {}).get("optional-dependencies", {}).get("api", [])
220
+ api_deps = (
221
+ pyproject.get("project", {})
222
+ .get("optional-dependencies", {})
223
+ .get("api", [])
224
+ )
209
225
  except Exception:
210
226
  pass
211
227
 
212
228
  current_v = get_app_version(app_dir)
213
229
  current_version = version_tuple(current_v)
214
- is_pre_3_6 = (
215
- (current_version and current_version < (3, 6, 0)) or
216
- (not current_version and os.path.exists(os.path.join(app_dir, "requirements.txt")))
230
+ is_pre_3_6 = (current_version and current_version < (3, 6, 0)) or (
231
+ not current_version
232
+ and os.path.exists(os.path.join(app_dir, "requirements.txt"))
217
233
  )
218
234
  target_v = version or "main"
219
235
 
@@ -230,7 +246,9 @@ def upgrade(args: argparse.Namespace) -> None:
230
246
  msg = "This will potentially update all files not in 'cave_api/', 'tests/' or '.env' and reset your database"
231
247
  if is_breaking_change(current_v, target_v):
232
248
  instructions = get_breaking_instructions(current_v, target_v)
233
- instruction_text = "\n" + "\n".join(instructions) if instructions else ""
249
+ instruction_text = (
250
+ "\n" + "\n".join(instructions) if instructions else ""
251
+ )
234
252
  msg = f"Upgrading from {current_v} to {target_v} is a BREAKING CHANGE.{instruction_text}\n\n{msg}"
235
253
 
236
254
  confirm_action(msg, auto_yes=auto_yes)
@@ -258,9 +276,9 @@ def upgrade(args: argparse.Namespace) -> None:
258
276
  deps_list_str = "\n".join(f' "{dep}",' for dep in api_deps)
259
277
 
260
278
  if "[project.optional-dependencies]" in content:
261
- if re.search(r"api\s*=\s*\[", content):
279
+ if re.search(r"(?<![\w-])api\s*=\s*\[", content):
262
280
  content = re.sub(
263
- r"(api\s*=\s*\[)[^\]]*(\])",
281
+ r"(?<![\w-])(api\s*=\s*\[)[^\]]*(\])",
264
282
  f"\\1\n{deps_list_str}\n \\2",
265
283
  content,
266
284
  flags=re.DOTALL,
@@ -272,13 +290,13 @@ def upgrade(args: argparse.Namespace) -> None:
272
290
  content,
273
291
  )
274
292
  else:
275
- content += (
276
- f"\n[project.optional-dependencies]\napi = [\n{deps_list_str}\n]\n"
277
- )
293
+ content += f"\n[project.optional-dependencies]\napi = [\n{deps_list_str}\n]\n"
278
294
 
279
295
  with open(pyproject_path, "w") as f:
280
296
  f.write(content)
281
- logger.info("Preserved 'api' optional dependencies in pyproject.toml")
297
+ logger.info(
298
+ "Preserved 'api' optional dependencies in pyproject.toml"
299
+ )
282
300
  except Exception as e:
283
301
  logger.warn(f"Failed to preserve 'api' optional dependencies: {e}")
284
302
 
@@ -293,7 +311,7 @@ def upgrade(args: argparse.Namespace) -> None:
293
311
  )
294
312
  if should_migrate:
295
313
  migrate_3_6_0(app_dir)
296
-
314
+
297
315
  reset_args = argparse.Namespace(
298
316
  yes=True,
299
317
  verbose=getattr(args, "verbose", False),
@@ -19,6 +19,7 @@ def version(args: argparse.Namespace) -> None:
19
19
  print_key_value("CLI Version", __version__)
20
20
  print_app_versions()
21
21
 
22
+
22
23
  def print_app_versions() -> None:
23
24
  try:
24
25
  app_dir, app_name = get_app()
@@ -35,20 +36,23 @@ def print_app_versions() -> None:
35
36
  cave_app_version = get_app_version(app_dir)
36
37
  cave_static_version = "Unknown"
37
38
  cave_utils_version = "Unknown"
38
-
39
+
39
40
  if pyproject_file.is_file():
40
41
  try:
41
42
  import tomllib
43
+
42
44
  with open(pyproject_file, "rb") as f:
43
45
  pyproject_data = tomllib.load(f)
44
46
  deps = pyproject_data.get("project", {}).get("dependencies", [])
45
47
  cave_utils_version = get_version_from_req_list("cave_utils", deps)
46
- except Exception:
48
+ except Exception:
47
49
  pass
48
50
  if req_file.is_file() and cave_utils_version == "Unknown":
49
51
  try:
50
52
  req_strings = req_file.read_text().splitlines()
51
- cave_utils_version = get_version_from_req_list("cave_utils", req_strings)
53
+ cave_utils_version = get_version_from_req_list(
54
+ "cave_utils", req_strings
55
+ )
52
56
  except Exception:
53
57
  pass
54
58
 
@@ -97,9 +97,7 @@ def save_entry(name: str, label: str, value: str) -> None:
97
97
  entries = load_entries(name)
98
98
  entries = [e for e in entries if e["value"] != value]
99
99
  entries.append({"label": label, "value": value})
100
- Path(cache_path(name)).write_text(
101
- json.dumps(entries, indent=2) + "\n"
102
- )
100
+ Path(cache_path(name)).write_text(json.dumps(entries, indent=2) + "\n")
103
101
 
104
102
 
105
103
  def set_setting(name: str, value: str) -> None:
@@ -241,9 +239,7 @@ def prompt_cached_entry(
241
239
  print(f"\n{prompt_new}")
242
240
  print(f"Saved entries:")
243
241
  for i, entry in enumerate(entries, 1):
244
- display = (
245
- _mask_value(entry["value"]) if mask else entry["value"]
246
- )
242
+ display = _mask_value(entry["value"]) if mask else entry["value"]
247
243
  suffix = " (default)" if i == 1 else ""
248
244
  print(f" [{i}] {entry['label']} ({display}){suffix}")
249
245
  print(f" [N] Enter a new value")
@@ -277,9 +273,7 @@ def prompt_cached_entry(
277
273
  except (EOFError, KeyboardInterrupt):
278
274
  label = ""
279
275
  if not label:
280
- label = (
281
- value if not mask else f"entry-{len(entries) + 1}"
282
- )
276
+ label = value if not mask else f"entry-{len(entries) + 1}"
283
277
  save_entry(name, label, value)
284
278
  return value
285
279