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.
- {cave_cli-3.6.0b4/cave_cli.egg-info → cave_cli-3.6.1}/PKG-INFO +1 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/cli.py +1 -2
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/create.py +6 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/doctor.py +4 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/list_cmd.py +3 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/list_versions.py +6 -2
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/purge.py +13 -5
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/reset.py +3 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/run.py +14 -6
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/sync_cmd.py +7 -2
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/uninstall.py +3 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/update.py +11 -3
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/upgrade.py +44 -26
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/version.py +7 -3
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/cache.py +3 -9
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/display.py +55 -27
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/docker.py +3 -7
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/env.py +1 -2
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/sync.py +16 -9
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/validate.py +4 -3
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/version.py +8 -3
- {cave_cli-3.6.0b4 → cave_cli-3.6.1/cave_cli.egg-info}/PKG-INFO +1 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/pyproject.toml +1 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_display.py +68 -16
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_env.py +6 -1
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_sync.py +10 -3
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_upgrade.py +43 -3
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_validate.py +24 -12
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/utils/prettify.py +11 -11
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/LICENSE +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/NOTICE.md +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/README.md +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/__init__.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/__init__.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/kill.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/prettify.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/test.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/commands/theme.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/__init__.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/constants.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/git.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/logger.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/net.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli/utils/subprocess.py +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/SOURCES.txt +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/dependency_links.txt +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/entry_points.txt +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/requires.txt +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/cave_cli.egg-info/top_level.txt +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/setup.cfg +0 -0
- {cave_cli-3.6.0b4 → cave_cli-3.6.1}/test/test_net.py +0 -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
|
|
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 =
|
|
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
|
|
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 +=
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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 = [
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(".")
|
|
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"',
|
|
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'",
|
|
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 =
|
|
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
|
-
|
|
216
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
|