deepctl-cmd-update 0.2.6__tar.gz → 0.2.8__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.
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/PKG-INFO +2 -2
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/pyproject.toml +2 -2
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/command.py +27 -8
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/installation.py +31 -5
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/plugin_update_check.py +2 -2
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/startup_check.py +15 -1
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/version_check.py +4 -2
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/PKG-INFO +2 -2
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/requires.txt +1 -1
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/README.md +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/setup.cfg +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/__init__.py +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/models.py +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/SOURCES.txt +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/dependency_links.txt +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/entry_points.txt +0 -0
- {deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepctl-cmd-update
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Update command for deepctl
|
|
5
5
|
Author-email: Deepgram <devrel@deepgram.com>
|
|
6
6
|
Maintainer-email: Deepgram <devrel@deepgram.com>
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: deepctl-core>=0.1
|
|
18
|
+
Requires-Dist: deepctl-core>=0.3.1
|
|
19
19
|
Requires-Dist: click>=8.0.0
|
|
20
20
|
Requires-Dist: pydantic>=2.0.0
|
|
21
21
|
Requires-Dist: rich>=13.0.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deepctl-cmd-update"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.8" # x-release-please-version
|
|
8
8
|
description = "Update command for deepctl"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -22,7 +22,7 @@ classifiers = [
|
|
|
22
22
|
keywords = ["deepgram", "cli", "update", "self-update"]
|
|
23
23
|
requires-python = ">=3.10"
|
|
24
24
|
dependencies = [
|
|
25
|
-
"deepctl-core>=0.1
|
|
25
|
+
"deepctl-core>=0.3.1",
|
|
26
26
|
"click>=8.0.0",
|
|
27
27
|
"pydantic>=2.0.0",
|
|
28
28
|
"rich>=13.0.0",
|
|
@@ -69,8 +69,16 @@ class UpdateCommand(BaseCommand):
|
|
|
69
69
|
auth_manager: Any, # Not used for update command
|
|
70
70
|
client: Any, # Not used for update command
|
|
71
71
|
**kwargs: Any,
|
|
72
|
-
) -> dict[str, Any]:
|
|
73
|
-
"""Handle the update command execution.
|
|
72
|
+
) -> UpdateResult | dict[str, Any]:
|
|
73
|
+
"""Handle the update command execution.
|
|
74
|
+
|
|
75
|
+
Returns the model rather than a dict wherever the exit code has to
|
|
76
|
+
be non-zero: BaseCommand.exit_code_for reads `.status` off the
|
|
77
|
+
result, and a dict has none, so a dict always exits 0. The three
|
|
78
|
+
failure paths carry status="error" (exit 1) and the decline path
|
|
79
|
+
status="cancelled" (exit 2). output_result unwraps either, so the
|
|
80
|
+
JSON payload is the same shape from both.
|
|
81
|
+
"""
|
|
74
82
|
console = get_console()
|
|
75
83
|
|
|
76
84
|
# Extract arguments from kwargs
|
|
@@ -93,10 +101,13 @@ class UpdateCommand(BaseCommand):
|
|
|
93
101
|
version_info = asyncio.run(version_checker.check_version(force=True))
|
|
94
102
|
except Exception as e:
|
|
95
103
|
print_error(f"Failed to check for updates: {e}")
|
|
104
|
+
# status="error" on the model, not a dict: see the docstring.
|
|
105
|
+
# A command that failed has to exit 1, as the README says.
|
|
96
106
|
return UpdateResult(
|
|
107
|
+
status="error",
|
|
97
108
|
success=False,
|
|
98
109
|
message=f"Failed to check for updates: {e}",
|
|
99
|
-
)
|
|
110
|
+
)
|
|
100
111
|
|
|
101
112
|
# Display version info
|
|
102
113
|
message = format_version_message(version_info)
|
|
@@ -136,7 +147,7 @@ class UpdateCommand(BaseCommand):
|
|
|
136
147
|
"update.installation_method", install_info.method.value
|
|
137
148
|
)
|
|
138
149
|
config._set_config_value("update.installation_path", install_info.path)
|
|
139
|
-
config.save()
|
|
150
|
+
config.save(implicit=True)
|
|
140
151
|
|
|
141
152
|
# Display installation info
|
|
142
153
|
console.print(f"Installation method: [cyan]{install_info.method}[/cyan]")
|
|
@@ -167,14 +178,20 @@ class UpdateCommand(BaseCommand):
|
|
|
167
178
|
# Confirm update
|
|
168
179
|
if not yes and not Confirm.ask("\nDo you want to proceed with the update?"):
|
|
169
180
|
print_info("Update cancelled")
|
|
181
|
+
# Return the model, not .model_dump(): BaseCommand.exit_code_for
|
|
182
|
+
# reads `.status` off the result, and a plain dict has none -- a
|
|
183
|
+
# declined update used to exit 0 while its own payload said
|
|
184
|
+
# "Update cancelled by user". status="cancelled" is the documented
|
|
185
|
+
# exit 2.
|
|
170
186
|
return UpdateResult(
|
|
187
|
+
status="cancelled",
|
|
171
188
|
success=False,
|
|
172
189
|
message="Update cancelled by user",
|
|
173
190
|
current_version=version_info.current_version,
|
|
174
191
|
latest_version=version_info.latest_version,
|
|
175
192
|
update_available=version_info.update_available,
|
|
176
193
|
installation_method=install_info.method.value,
|
|
177
|
-
)
|
|
194
|
+
)
|
|
178
195
|
|
|
179
196
|
# Execute update
|
|
180
197
|
print_info("Updating deepctl...")
|
|
@@ -193,7 +210,7 @@ class UpdateCommand(BaseCommand):
|
|
|
193
210
|
|
|
194
211
|
# Clear version cache
|
|
195
212
|
config._set_config_value("update.cached_version_info", None)
|
|
196
|
-
config.save()
|
|
213
|
+
config.save(implicit=True)
|
|
197
214
|
|
|
198
215
|
return UpdateResult(
|
|
199
216
|
success=True,
|
|
@@ -212,13 +229,14 @@ class UpdateCommand(BaseCommand):
|
|
|
212
229
|
console.print(f"[yellow]{shlex.join(update_command)}[/yellow]")
|
|
213
230
|
|
|
214
231
|
return UpdateResult(
|
|
232
|
+
status="error",
|
|
215
233
|
success=False,
|
|
216
234
|
message=f"Update failed: {error_msg}",
|
|
217
235
|
current_version=version_info.current_version,
|
|
218
236
|
latest_version=version_info.latest_version,
|
|
219
237
|
update_available=version_info.update_available,
|
|
220
238
|
installation_method=install_info.method.value,
|
|
221
|
-
)
|
|
239
|
+
)
|
|
222
240
|
|
|
223
241
|
except Exception as e:
|
|
224
242
|
print_error(f"Failed to execute update: {e}")
|
|
@@ -228,10 +246,11 @@ class UpdateCommand(BaseCommand):
|
|
|
228
246
|
console.print(f"[yellow]{update_command}[/yellow]")
|
|
229
247
|
|
|
230
248
|
return UpdateResult(
|
|
249
|
+
status="error",
|
|
231
250
|
success=False,
|
|
232
251
|
message=f"Failed to execute update: {e}",
|
|
233
252
|
current_version=version_info.current_version,
|
|
234
253
|
latest_version=version_info.latest_version,
|
|
235
254
|
update_available=version_info.update_available,
|
|
236
255
|
installation_method=install_info.method.value,
|
|
237
|
-
)
|
|
256
|
+
)
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/installation.py
RENAMED
|
@@ -7,6 +7,7 @@ import sys
|
|
|
7
7
|
from enum import Enum
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
+
from deepctl_core._launcher import get_launcher, launched_via_npm
|
|
10
11
|
from pydantic import BaseModel
|
|
11
12
|
|
|
12
13
|
|
|
@@ -20,6 +21,7 @@ class InstallMethod(str, Enum):
|
|
|
20
21
|
UV_TOOL = "uv_tool"
|
|
21
22
|
UVX = "uvx"
|
|
22
23
|
PIPX_RUN = "pipx_run"
|
|
24
|
+
NPM = "npm"
|
|
23
25
|
SYSTEM = "system"
|
|
24
26
|
DEVELOPMENT = "development"
|
|
25
27
|
UNKNOWN = "unknown"
|
|
@@ -96,7 +98,7 @@ class InstallationDetector:
|
|
|
96
98
|
"--upgrade",
|
|
97
99
|
"deepctl",
|
|
98
100
|
],
|
|
99
|
-
InstallMethod.HOMEBREW: ["brew", "upgrade", "
|
|
101
|
+
InstallMethod.HOMEBREW: ["brew", "upgrade", "deepgram"],
|
|
100
102
|
InstallMethod.UV_TOOL: [
|
|
101
103
|
"uv",
|
|
102
104
|
"tool",
|
|
@@ -105,6 +107,7 @@ class InstallationDetector:
|
|
|
105
107
|
],
|
|
106
108
|
InstallMethod.UVX: None, # Ephemeral, no update needed
|
|
107
109
|
InstallMethod.PIPX_RUN: None, # Ephemeral, no update needed
|
|
110
|
+
InstallMethod.NPM: None, # Updated through npm, see instructions
|
|
108
111
|
InstallMethod.SYSTEM: None, # Handled separately
|
|
109
112
|
InstallMethod.DEVELOPMENT: None, # Can't auto-update
|
|
110
113
|
InstallMethod.UNKNOWN: None,
|
|
@@ -121,7 +124,23 @@ class InstallationDetector:
|
|
|
121
124
|
Human-readable update instructions
|
|
122
125
|
"""
|
|
123
126
|
if info.method == InstallMethod.HOMEBREW:
|
|
124
|
-
return "Please update using Homebrew: brew upgrade
|
|
127
|
+
return "Please update using Homebrew: brew update && brew upgrade deepgram"
|
|
128
|
+
|
|
129
|
+
# The launcher's venv or uv cache is private to it, so pip/uv run
|
|
130
|
+
# from inside would update the wrong thing; only npm can update it.
|
|
131
|
+
if info.method == InstallMethod.NPM:
|
|
132
|
+
if get_launcher() == "npx":
|
|
133
|
+
return (
|
|
134
|
+
"Running via npx. Use the latest version with: "
|
|
135
|
+
"npx @deepgram/cli@latest"
|
|
136
|
+
)
|
|
137
|
+
return (
|
|
138
|
+
"Installed via npm. Update with: "
|
|
139
|
+
"npm install -g @deepgram/cli@latest "
|
|
140
|
+
"(or run npx @deepgram/cli@latest). "
|
|
141
|
+
"If @deepgram/cli is a dependency of your project, update it "
|
|
142
|
+
"there instead: npm install @deepgram/cli@latest"
|
|
143
|
+
)
|
|
125
144
|
|
|
126
145
|
if info.method == InstallMethod.UVX:
|
|
127
146
|
return (
|
|
@@ -138,7 +157,9 @@ class InstallationDetector:
|
|
|
138
157
|
if info.method == InstallMethod.SYSTEM:
|
|
139
158
|
# Try to detect the system package manager
|
|
140
159
|
if sys.platform.startswith("darwin"):
|
|
141
|
-
return
|
|
160
|
+
return (
|
|
161
|
+
"Please update using Homebrew: brew update && brew upgrade deepgram"
|
|
162
|
+
)
|
|
142
163
|
elif sys.platform.startswith("linux"):
|
|
143
164
|
# Check for common package managers
|
|
144
165
|
if Path("/etc/debian_version").exists():
|
|
@@ -261,8 +282,8 @@ class InstallationDetector:
|
|
|
261
282
|
) -> InstallMethod:
|
|
262
283
|
"""Detect the installation method.
|
|
263
284
|
|
|
264
|
-
Priority: development > oneshot > homebrew > uv_tool >
|
|
265
|
-
uv > system > pip > unknown
|
|
285
|
+
Priority: npm > development > oneshot > homebrew > uv_tool >
|
|
286
|
+
pipx > uv > system > pip > unknown
|
|
266
287
|
|
|
267
288
|
Args:
|
|
268
289
|
package_location: Path to package
|
|
@@ -272,6 +293,11 @@ class InstallationDetector:
|
|
|
272
293
|
Returns:
|
|
273
294
|
Detected installation method
|
|
274
295
|
"""
|
|
296
|
+
# The npm launcher runs deepctl through uv or its own venv, which
|
|
297
|
+
# would otherwise be detected as uvx or pip.
|
|
298
|
+
if launched_via_npm():
|
|
299
|
+
return InstallMethod.NPM
|
|
300
|
+
|
|
275
301
|
# Development installation
|
|
276
302
|
if is_editable:
|
|
277
303
|
return InstallMethod.DEVELOPMENT
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/plugin_update_check.py
RENAMED
|
@@ -261,7 +261,7 @@ def print_pending_plugin_notifications() -> None:
|
|
|
261
261
|
u = updates[0]
|
|
262
262
|
sys.stderr.write(
|
|
263
263
|
f"\033[33mPlugin update available: {u['name']} {u['current']} → {u['latest']}"
|
|
264
|
-
f" — run '
|
|
264
|
+
f" — run 'dg plugin update {u['name']}' to upgrade\033[0m\n"
|
|
265
265
|
)
|
|
266
266
|
else:
|
|
267
267
|
sys.stderr.write("\033[33mPlugin updates available:\033[0m\n")
|
|
@@ -270,7 +270,7 @@ def print_pending_plugin_notifications() -> None:
|
|
|
270
270
|
f"\033[33m {u['name']} {u['current']} → {u['latest']}\033[0m\n"
|
|
271
271
|
)
|
|
272
272
|
sys.stderr.write(
|
|
273
|
-
"\033[33mRun '
|
|
273
|
+
"\033[33mRun 'dg plugin update <name>' to upgrade\033[0m\n"
|
|
274
274
|
)
|
|
275
275
|
except (BrokenPipeError, OSError, ValueError):
|
|
276
276
|
# The output stream closed (e.g. an MCP host disconnected stdio
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/startup_check.py
RENAMED
|
@@ -15,6 +15,8 @@ import time
|
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
from typing import Any
|
|
17
17
|
|
|
18
|
+
from deepctl_core._launcher import launched_via_npm, npm_upgrade_command
|
|
19
|
+
|
|
18
20
|
# Sentinel used when the background check is suppressed or has no result
|
|
19
21
|
_NO_RESULT: dict[str, Any] = {}
|
|
20
22
|
|
|
@@ -42,8 +44,20 @@ def _is_ci() -> bool:
|
|
|
42
44
|
return any(os.environ.get(v) for v in _CI_ENV_VARS)
|
|
43
45
|
|
|
44
46
|
|
|
47
|
+
def upgrade_hint() -> str:
|
|
48
|
+
"""Return the command a user should run to upgrade deepctl."""
|
|
49
|
+
if launched_via_npm():
|
|
50
|
+
return npm_upgrade_command()
|
|
51
|
+
return "dg update"
|
|
52
|
+
|
|
53
|
+
|
|
45
54
|
def _is_oneshot() -> bool:
|
|
46
55
|
"""Return True if running in an ephemeral one-shot environment."""
|
|
56
|
+
# The npm launcher often runs deepctl through `uv tool run`, which looks
|
|
57
|
+
# one-shot, but the npm install itself persists and is pinned to one
|
|
58
|
+
# version, so its users do need to hear about updates.
|
|
59
|
+
if launched_via_npm():
|
|
60
|
+
return False
|
|
47
61
|
# uvx
|
|
48
62
|
if "UV_INTERNAL__PARENT_INTERPRETER" in os.environ:
|
|
49
63
|
return True
|
|
@@ -200,7 +214,7 @@ def print_pending_notification() -> None:
|
|
|
200
214
|
try:
|
|
201
215
|
sys.stderr.write(
|
|
202
216
|
f"\n\033[33m Update available: {current} → {latest}"
|
|
203
|
-
f" — run \033[
|
|
217
|
+
f" — run \033[1m{upgrade_hint()}\033[0m\033[33m to upgrade\033[0m\n\n"
|
|
204
218
|
)
|
|
205
219
|
except (BrokenPipeError, OSError, ValueError):
|
|
206
220
|
# The output stream closed (e.g. an MCP host disconnected stdio
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update/version_check.py
RENAMED
|
@@ -7,6 +7,8 @@ from deepctl_core import Config
|
|
|
7
7
|
from packaging import version
|
|
8
8
|
from pydantic import BaseModel, Field
|
|
9
9
|
|
|
10
|
+
from .startup_check import upgrade_hint
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
class VersionInfo(BaseModel):
|
|
12
14
|
"""Version information from PyPI."""
|
|
@@ -245,7 +247,7 @@ class VersionChecker:
|
|
|
245
247
|
self.config._set_config_value(
|
|
246
248
|
"update.cached_version_info", info.model_dump(mode="json")
|
|
247
249
|
)
|
|
248
|
-
self.config.save()
|
|
250
|
+
self.config.save(implicit=True)
|
|
249
251
|
|
|
250
252
|
|
|
251
253
|
def format_version_message(info: VersionInfo) -> str:
|
|
@@ -270,5 +272,5 @@ def format_version_message(info: VersionInfo) -> str:
|
|
|
270
272
|
else:
|
|
271
273
|
message += f" (released {days_old} days ago)"
|
|
272
274
|
|
|
273
|
-
message += "\nRun '
|
|
275
|
+
message += f"\nRun '{upgrade_hint()}' to upgrade"
|
|
274
276
|
return message
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepctl-cmd-update
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Update command for deepctl
|
|
5
5
|
Author-email: Deepgram <devrel@deepgram.com>
|
|
6
6
|
Maintainer-email: Deepgram <devrel@deepgram.com>
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: deepctl-core>=0.1
|
|
18
|
+
Requires-Dist: deepctl-core>=0.3.1
|
|
19
19
|
Requires-Dist: click>=8.0.0
|
|
20
20
|
Requires-Dist: pydantic>=2.0.0
|
|
21
21
|
Requires-Dist: rich>=13.0.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepctl_cmd_update-0.2.6 → deepctl_cmd_update-0.2.8}/src/deepctl_cmd_update.egg-info/top_level.txt
RENAMED
|
File without changes
|