devs-cli 4.0.7__py3-none-any.whl → 5.0.0__py3-none-any.whl
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.
- devs/cli.py +69 -58
- devs/core/integration.py +89 -40
- {devs_cli-4.0.7.dist-info → devs_cli-5.0.0.dist-info}/METADATA +1 -1
- devs_cli-5.0.0.dist-info/RECORD +13 -0
- {devs_cli-4.0.7.dist-info → devs_cli-5.0.0.dist-info}/WHEEL +1 -1
- devs_cli-4.0.7.dist-info/RECORD +0 -13
- {devs_cli-4.0.7.dist-info → devs_cli-5.0.0.dist-info}/entry_points.txt +0 -0
- {devs_cli-4.0.7.dist-info → devs_cli-5.0.0.dist-info}/licenses/LICENSE +0 -0
- {devs_cli-4.0.7.dist-info → devs_cli-5.0.0.dist-info}/top_level.txt +0 -0
devs/cli.py
CHANGED
|
@@ -246,12 +246,13 @@ def start(dev_names: tuple, rebuild: bool, rebuild_if_changed: bool, live: bool,
|
|
|
246
246
|
default=None,
|
|
247
247
|
envvar='DEVS_SSH_HOST',
|
|
248
248
|
help=(
|
|
249
|
-
'
|
|
250
|
-
'(e.g. Tailscale
|
|
251
|
-
'
|
|
252
|
-
'
|
|
253
|
-
'
|
|
254
|
-
|
|
249
|
+
'Open VS Code via direct Remote-SSH into a container ALREADY RUNNING and '
|
|
250
|
+
'reachable at this SSH host (e.g. its Tailscale name). The container is its '
|
|
251
|
+
'own ssh host, so this opens its /workspaces folder directly — no attach. '
|
|
252
|
+
'Connection-only: it does NOT create, start, or sync the container — start it '
|
|
253
|
+
'yourself first (e.g. `devs start` on the host). '
|
|
254
|
+
'Usually unnecessary: without --ssh, `devs vscode <dev>` auto-discovers the '
|
|
255
|
+
"container's tailnet name via the handshake start-tailscale.sh writes. "
|
|
255
256
|
'Can also be set via the DEVS_SSH_HOST env var or ssh_host in DEVS.yml.'
|
|
256
257
|
),
|
|
257
258
|
)
|
|
@@ -264,7 +265,8 @@ def vscode(dev_names: tuple, delay: float, live: bool, env: tuple, ssh_host: str
|
|
|
264
265
|
Example: devs vscode sally bob
|
|
265
266
|
Example: devs vscode sally --live # Start with current directory mounted
|
|
266
267
|
Example: devs vscode sally --env QUART_PORT=5001
|
|
267
|
-
Example: devs vscode sally
|
|
268
|
+
Example: devs vscode sally # Auto: direct Remote-SSH if sally's container is on the tailnet, else local
|
|
269
|
+
Example: devs vscode sally --ssh devs-myorg-myrepo-sally # Force direct Remote-SSH into that node
|
|
268
270
|
"""
|
|
269
271
|
check_dependencies()
|
|
270
272
|
project = get_project()
|
|
@@ -275,79 +277,88 @@ def vscode(dev_names: tuple, delay: float, live: bool, env: tuple, ssh_host: str
|
|
|
275
277
|
|
|
276
278
|
vscode_integration = VSCodeIntegration(project)
|
|
277
279
|
|
|
280
|
+
# Decide, per dev, whether to open via direct Remote-SSH (the container is its
|
|
281
|
+
# own tailnet ssh host) or to manage it locally. An explicit --ssh / env / DEVS.yml
|
|
282
|
+
# host forces SSH for every dev; otherwise auto-discover via the tailnet handshake
|
|
283
|
+
# that start-tailscale.sh writes (set only when the container is up + Tailscale SSH
|
|
284
|
+
# is on). Devs that don't resolve fall through to normal local mode.
|
|
278
285
|
if ssh_host:
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
# WorkspaceManager entirely and only need the workspace path to construct the
|
|
283
|
-
# URI; derive it from the project name and dev name (no filesystem access needed).
|
|
284
|
-
workspace_dirs = []
|
|
285
|
-
valid_dev_names = []
|
|
286
|
+
ssh_hosts = {dev_name: ssh_host for dev_name in dev_names}
|
|
287
|
+
else:
|
|
288
|
+
ssh_hosts = {}
|
|
286
289
|
for dev_name in dev_names:
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
host = vscode_integration.resolve_tailnet_ssh_host(dev_name)
|
|
291
|
+
if host:
|
|
292
|
+
ssh_hosts[dev_name] = host
|
|
293
|
+
|
|
294
|
+
ssh_dev_names = [d for d in dev_names if d in ssh_hosts]
|
|
295
|
+
local_dev_names = [d for d in dev_names if d not in ssh_hosts]
|
|
296
|
+
|
|
297
|
+
# --- Direct Remote-SSH (attach-only: container already running on its host) ---
|
|
298
|
+
if ssh_dev_names:
|
|
299
|
+
for dev_name in ssh_dev_names:
|
|
300
|
+
console.print(f" 🔗 {dev_name} → ssh://{ssh_hosts[dev_name]} (direct Remote-SSH into container)")
|
|
301
|
+
# Synthetic workspace Paths: only the name is used to build the URI; the path
|
|
302
|
+
# is never accessed locally in SSH mode.
|
|
303
|
+
workspace_dirs = [config.workspaces_dir / project.get_workspace_name(d) for d in ssh_dev_names]
|
|
293
304
|
try:
|
|
294
305
|
success_count = vscode_integration.launch_multiple_devcontainers(
|
|
295
306
|
workspace_dirs,
|
|
296
|
-
|
|
307
|
+
ssh_dev_names,
|
|
297
308
|
delay_between_windows=delay,
|
|
298
309
|
live=live,
|
|
299
|
-
|
|
310
|
+
ssh_hosts=ssh_hosts,
|
|
300
311
|
)
|
|
301
312
|
if success_count == 0:
|
|
302
|
-
console.print("❌ Failed to open any VS Code windows")
|
|
313
|
+
console.print("❌ Failed to open any VS Code windows (Remote-SSH)")
|
|
303
314
|
except VSCodeError as e:
|
|
304
315
|
console.print(f"❌ VS Code integration error: {e}")
|
|
305
|
-
return
|
|
306
316
|
|
|
307
|
-
# Local mode: manage containers and workspaces as normal
|
|
308
|
-
|
|
309
|
-
|
|
317
|
+
# --- Local mode: manage containers and workspaces as normal ---
|
|
318
|
+
if local_dev_names:
|
|
319
|
+
container_manager = ContainerManager(project, config)
|
|
320
|
+
workspace_manager = WorkspaceManager(project, config)
|
|
310
321
|
|
|
311
|
-
|
|
312
|
-
|
|
322
|
+
workspace_dirs = []
|
|
323
|
+
valid_dev_names = []
|
|
313
324
|
|
|
314
|
-
|
|
315
|
-
|
|
325
|
+
for dev_name in local_dev_names:
|
|
326
|
+
console.print(f" Preparing: {dev_name}")
|
|
316
327
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
devs_env = DevsConfigLoader.load_env_vars(dev_name, project.info.name)
|
|
329
|
+
cli_env = parse_env_vars(env) if env else {}
|
|
330
|
+
extra_env = merge_env_vars(devs_env, cli_env) if devs_env or cli_env else None
|
|
320
331
|
|
|
321
|
-
|
|
322
|
-
|
|
332
|
+
if extra_env:
|
|
333
|
+
console.print(f"🔧 Environment variables: {', '.join(f'{k}={v}' for k, v in extra_env.items())}")
|
|
323
334
|
|
|
324
|
-
|
|
325
|
-
|
|
335
|
+
try:
|
|
336
|
+
workspace_dir = workspace_manager.create_workspace(dev_name, live=live)
|
|
326
337
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
338
|
+
if container_manager.ensure_container_running(dev_name, workspace_dir, check_rebuild=False, debug=debug, live=live, extra_env=extra_env):
|
|
339
|
+
workspace_dirs.append(workspace_dir)
|
|
340
|
+
valid_dev_names.append(dev_name)
|
|
341
|
+
else:
|
|
342
|
+
console.print(f" ❌ Failed to start container for {dev_name}, skipping...")
|
|
332
343
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
344
|
+
except (ContainerError, WorkspaceError) as e:
|
|
345
|
+
console.print(f" ❌ Error preparing {dev_name}: {e}")
|
|
346
|
+
continue
|
|
336
347
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
348
|
+
if workspace_dirs:
|
|
349
|
+
try:
|
|
350
|
+
success_count = vscode_integration.launch_multiple_devcontainers(
|
|
351
|
+
workspace_dirs,
|
|
352
|
+
valid_dev_names,
|
|
353
|
+
delay_between_windows=delay,
|
|
354
|
+
live=live,
|
|
355
|
+
)
|
|
345
356
|
|
|
346
|
-
|
|
347
|
-
|
|
357
|
+
if success_count == 0:
|
|
358
|
+
console.print("❌ Failed to open any VS Code windows")
|
|
348
359
|
|
|
349
|
-
|
|
350
|
-
|
|
360
|
+
except VSCodeError as e:
|
|
361
|
+
console.print(f"❌ VS Code integration error: {e}")
|
|
351
362
|
|
|
352
363
|
|
|
353
364
|
@cli.command()
|
devs/core/integration.py
CHANGED
|
@@ -11,6 +11,7 @@ from rich.console import Console
|
|
|
11
11
|
|
|
12
12
|
from ..exceptions import VSCodeError
|
|
13
13
|
from devs_common.core.project import Project
|
|
14
|
+
from devs_common.utils.config_hash import get_env_mount_path
|
|
14
15
|
from devs_common.utils.devcontainer import prepare_devcontainer_environment
|
|
15
16
|
|
|
16
17
|
console = Console()
|
|
@@ -51,6 +52,41 @@ class VSCodeIntegration:
|
|
|
51
52
|
except FileNotFoundError:
|
|
52
53
|
return False
|
|
53
54
|
|
|
55
|
+
def resolve_tailnet_ssh_host(self, dev_name: str) -> Optional[str]:
|
|
56
|
+
"""Discover a container's own tailnet SSH name via the writeback handshake.
|
|
57
|
+
|
|
58
|
+
Joins docker <-> tailnet by docker container id, WITHOUT `docker exec`:
|
|
59
|
+
``docker inspect`` the container for its hostname (== its short container id,
|
|
60
|
+
== the ``$HOSTNAME`` start-tailscale.sh keyed its handshake file by), then read
|
|
61
|
+
that file out of the host-shared env mount. Returns the short MagicDNS name
|
|
62
|
+
(e.g. ``devs-acme-app-eamonn-1``) only when the container is up AND Tailscale
|
|
63
|
+
SSH is on; otherwise None (caller falls back to local mode).
|
|
64
|
+
"""
|
|
65
|
+
container_name = self.project.get_container_name(dev_name)
|
|
66
|
+
try:
|
|
67
|
+
inspect = subprocess.run(
|
|
68
|
+
["docker", "inspect", "--format", "{{.Config.Hostname}}", container_name],
|
|
69
|
+
capture_output=True, text=True, check=False,
|
|
70
|
+
)
|
|
71
|
+
except FileNotFoundError:
|
|
72
|
+
return None # no docker here
|
|
73
|
+
if inspect.returncode != 0:
|
|
74
|
+
return None # container doesn't exist / not inspectable
|
|
75
|
+
container_id = inspect.stdout.strip()
|
|
76
|
+
if not container_id:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
handshake = get_env_mount_path(self.project.info.name) / "ts-nodes" / f"{container_id}.json"
|
|
80
|
+
if not handshake.exists():
|
|
81
|
+
return None
|
|
82
|
+
try:
|
|
83
|
+
data = json.loads(handshake.read_text())
|
|
84
|
+
except (OSError, ValueError):
|
|
85
|
+
return None
|
|
86
|
+
if not data.get("ssh"):
|
|
87
|
+
return None # on the tailnet but not accepting SSH
|
|
88
|
+
return data.get("short") or None
|
|
89
|
+
|
|
54
90
|
def generate_devcontainer_uri(
|
|
55
91
|
self,
|
|
56
92
|
workspace_dir: Path,
|
|
@@ -66,38 +102,34 @@ class VSCodeIntegration:
|
|
|
66
102
|
dev_name: Development environment name
|
|
67
103
|
live: Whether to use live mode (mount current directory)
|
|
68
104
|
attach_to_existing: Whether to attach to existing container (vs create new one)
|
|
69
|
-
ssh_host: If set, generate a Remote-SSH
|
|
70
|
-
|
|
105
|
+
ssh_host: If set, generate a plain Remote-SSH folder URI for this host.
|
|
106
|
+
In the devs+Tailscale model the container IS its own SSH host
|
|
107
|
+
(you SSH straight into it — there's no separate Docker daemon to
|
|
108
|
+
attach through), so this is NOT an attached-container URI.
|
|
71
109
|
|
|
72
110
|
Returns:
|
|
73
111
|
VS Code devcontainer URI
|
|
74
112
|
"""
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
113
|
+
# IMPORTANT: In live mode, use the actual host folder name because devcontainer CLI
|
|
114
|
+
# mounts the host directory directly and VS Code must match that path.
|
|
115
|
+
workspace_name = workspace_dir.name if live else self.project.get_workspace_name(dev_name)
|
|
78
116
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
container_hex = json.dumps(container_info, separators=(",", ":")).encode("utf-8").hex()
|
|
88
|
-
else:
|
|
89
|
-
container_hex = container_name.encode("utf-8").hex()
|
|
117
|
+
if ssh_host:
|
|
118
|
+
# Direct Remote-SSH INTO the container. With Tailscale the container is its
|
|
119
|
+
# own tailnet node running Tailscale SSH, so VS Code opens the in-container
|
|
120
|
+
# workspace folder over SSH — no Docker host, no attach. Wrapping this in an
|
|
121
|
+
# attached-container URI would make VS Code SSH in and then hunt for a Docker
|
|
122
|
+
# daemon that isn't there.
|
|
123
|
+
return f"vscode-remote://ssh-remote+{ssh_host}/workspaces/{workspace_name}"
|
|
90
124
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# IMPORTANT: In live mode, use the actual host folder name because devcontainer CLI
|
|
96
|
-
# mounts the host directory directly and VS Code must match that path.
|
|
97
|
-
workspace_name = workspace_dir.name if live else self.project.get_workspace_name(dev_name)
|
|
98
|
-
vscode_uri = f"vscode-remote://dev-container+{workspace_hex}/workspaces/{workspace_name}"
|
|
125
|
+
if attach_to_existing:
|
|
126
|
+
container_name = self.project.get_container_name(dev_name)
|
|
127
|
+
container_hex = container_name.encode("utf-8").hex()
|
|
128
|
+
return f"vscode-remote://attached-container+{container_hex}/workspaces/{workspace_name}"
|
|
99
129
|
|
|
100
|
-
|
|
130
|
+
# Create new container from devcontainer.json
|
|
131
|
+
workspace_hex = workspace_dir.as_posix().encode("utf-8").hex()
|
|
132
|
+
return f"vscode-remote://dev-container+{workspace_hex}/workspaces/{workspace_name}"
|
|
101
133
|
|
|
102
134
|
def _format_code_command(
|
|
103
135
|
self,
|
|
@@ -129,15 +161,17 @@ class VSCodeIntegration:
|
|
|
129
161
|
new_window: bool,
|
|
130
162
|
ssh_host: Optional[str],
|
|
131
163
|
) -> None:
|
|
132
|
-
"""Print the 'code' command
|
|
164
|
+
"""Print the 'code' command for this container.
|
|
133
165
|
|
|
134
|
-
|
|
135
|
-
|
|
166
|
+
When an SSH host is set we print only the Remote-SSH command (the plain
|
|
167
|
+
attached-container command wouldn't work from another machine and is just
|
|
168
|
+
noise). Otherwise we print the local attached-container command.
|
|
136
169
|
"""
|
|
137
170
|
if ssh_host:
|
|
138
171
|
ssh_cmd = self._format_code_command(workspace_dir, dev_name, live, new_window, ssh_host)
|
|
139
|
-
console.print(f" 📋 VS Code command (
|
|
172
|
+
console.print(f" 📋 VS Code command (Remote-SSH: {ssh_host}):")
|
|
140
173
|
console.print(f" {ssh_cmd}")
|
|
174
|
+
return
|
|
141
175
|
|
|
142
176
|
plain_cmd = self._format_code_command(workspace_dir, dev_name, live, new_window, None)
|
|
143
177
|
console.print(f" 📋 VS Code command:")
|
|
@@ -182,14 +216,23 @@ class VSCodeIntegration:
|
|
|
182
216
|
self._print_code_commands(workspace_dir, dev_name, live, new_window, ssh_host)
|
|
183
217
|
|
|
184
218
|
# No local 'code' command (e.g. a headless remote dev box reached over SSH):
|
|
185
|
-
# don't fail —
|
|
186
|
-
# command printed above and stop here.
|
|
219
|
+
# don't fail — just point to the command printed above and stop here.
|
|
187
220
|
if not self.code_available:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
221
|
+
if ssh_host:
|
|
222
|
+
# SSH mode is attach-only: we never created/started the container,
|
|
223
|
+
# so we can't claim it's ready. The user must ensure it's running
|
|
224
|
+
# on the remote host themselves.
|
|
225
|
+
console.print(
|
|
226
|
+
f" ⚠️ VS Code 'code' command not found here — printed the attach "
|
|
227
|
+
f"URI only. Make sure the container is already running on '{ssh_host}', "
|
|
228
|
+
"then run the command above from a machine with VS Code installed."
|
|
229
|
+
)
|
|
230
|
+
else:
|
|
231
|
+
console.print(
|
|
232
|
+
f" ⚠️ VS Code 'code' command not found here — container is ready, "
|
|
233
|
+
"but VS Code can't be launched from this machine. "
|
|
234
|
+
"Run the command above from a machine with VS Code installed."
|
|
235
|
+
)
|
|
193
236
|
return True
|
|
194
237
|
|
|
195
238
|
if ssh_host:
|
|
@@ -235,6 +278,7 @@ class VSCodeIntegration:
|
|
|
235
278
|
delay_between_windows: float = 2.0,
|
|
236
279
|
live: bool = False,
|
|
237
280
|
ssh_host: Optional[str] = None,
|
|
281
|
+
ssh_hosts: Optional[dict] = None,
|
|
238
282
|
) -> int:
|
|
239
283
|
"""Launch multiple devcontainers in separate VS Code windows.
|
|
240
284
|
|
|
@@ -243,7 +287,10 @@ class VSCodeIntegration:
|
|
|
243
287
|
dev_names: List of development environment names
|
|
244
288
|
delay_between_windows: Delay between opening windows (seconds)
|
|
245
289
|
live: Whether to use live mode (mount current directory)
|
|
246
|
-
ssh_host: If set, connect via Remote-SSH to this host
|
|
290
|
+
ssh_host: If set, connect every dev via direct Remote-SSH to this host.
|
|
291
|
+
ssh_hosts: Optional per-dev override mapping ``dev_name -> ssh host``
|
|
292
|
+
(each container is its own tailnet host, so they differ). Falls back
|
|
293
|
+
to ``ssh_host`` for any dev not present in the map.
|
|
247
294
|
|
|
248
295
|
Returns:
|
|
249
296
|
Number of successfully launched windows
|
|
@@ -251,10 +298,11 @@ class VSCodeIntegration:
|
|
|
251
298
|
if len(workspace_dirs) != len(dev_names):
|
|
252
299
|
raise VSCodeError("Workspace directories and dev names lists must have same length")
|
|
253
300
|
|
|
254
|
-
|
|
301
|
+
ssh_hosts = ssh_hosts or {}
|
|
302
|
+
if ssh_host or ssh_hosts:
|
|
255
303
|
console.print(
|
|
256
304
|
f"📂 Opening {len(dev_names)} devcontainers in VS Code "
|
|
257
|
-
f"(via SSH
|
|
305
|
+
f"(via Remote-SSH) for project: {self.project.info.name}"
|
|
258
306
|
)
|
|
259
307
|
else:
|
|
260
308
|
console.print(f"📂 Opening {len(dev_names)} devcontainers in VS Code for project: {self.project.info.name}")
|
|
@@ -262,9 +310,10 @@ class VSCodeIntegration:
|
|
|
262
310
|
success_count = 0
|
|
263
311
|
|
|
264
312
|
for workspace_dir, dev_name in zip(workspace_dirs, dev_names):
|
|
313
|
+
host = ssh_hosts.get(dev_name, ssh_host)
|
|
265
314
|
try:
|
|
266
315
|
if self.launch_devcontainer(
|
|
267
|
-
workspace_dir, dev_name, new_window=True, live=live, ssh_host=
|
|
316
|
+
workspace_dir, dev_name, new_window=True, live=live, ssh_host=host
|
|
268
317
|
):
|
|
269
318
|
success_count += 1
|
|
270
319
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
devs/__init__.py,sha256=dMk0J_JrmBmknPvt6HNUa04qxgHYpxhnIXa3PZFk_N0,571
|
|
2
|
+
devs/cli.py,sha256=inWDnumsDeaQcvY8y42HcNPY-HJxYkCOUGHgsjYx4nI,44985
|
|
3
|
+
devs/config.py,sha256=DaS2_1x0h63cHn34RmWbEhUx_1u3-sAo16tM3AXMKfQ,1561
|
|
4
|
+
devs/exceptions.py,sha256=7xO7ihJu_U6CupZPMv89B4N5EBSUcdj2OdA6GPAFPEE,490
|
|
5
|
+
devs/core/__init__.py,sha256=TPy3eZi-AEztci_QZ37YAAl2zvUQlwBALpyiQx2ED7Q,363
|
|
6
|
+
devs/core/integration.py,sha256=_zT5kJi_L34uU3yhLinLI7bbjI5Q27dX9ABxgwHkx2Y,16557
|
|
7
|
+
devs/utils/__init__.py,sha256=f-sEWETPfW2Xkaxgd-l6FS-jIQAorLlQZOicIZvp-W0,638
|
|
8
|
+
devs_cli-5.0.0.dist-info/licenses/LICENSE,sha256=bi2EUiv-lmC_quQVkNqzTYXJpjVarkPsVKfqhJl7ccQ,1067
|
|
9
|
+
devs_cli-5.0.0.dist-info/METADATA,sha256=3YGHAfTQZrjl-5eJ7w2a_49LqHjPhcdO6Z2bRdF1orQ,5282
|
|
10
|
+
devs_cli-5.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
11
|
+
devs_cli-5.0.0.dist-info/entry_points.txt,sha256=s8-pgqZ1QvzPJgHP9vNxwBYdezmGsFdRUHacJPZ4WOs,39
|
|
12
|
+
devs_cli-5.0.0.dist-info/top_level.txt,sha256=9RIVUPVGuOdO84qkBh_9XcKoTV7773o3py78wz2-IZk,5
|
|
13
|
+
devs_cli-5.0.0.dist-info/RECORD,,
|
devs_cli-4.0.7.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
devs/__init__.py,sha256=dMk0J_JrmBmknPvt6HNUa04qxgHYpxhnIXa3PZFk_N0,571
|
|
2
|
-
devs/cli.py,sha256=wRqKwdyGYAqemrabrH7NhMpBYX4iFJpowWxwDqptYmk,44125
|
|
3
|
-
devs/config.py,sha256=DaS2_1x0h63cHn34RmWbEhUx_1u3-sAo16tM3AXMKfQ,1561
|
|
4
|
-
devs/exceptions.py,sha256=7xO7ihJu_U6CupZPMv89B4N5EBSUcdj2OdA6GPAFPEE,490
|
|
5
|
-
devs/core/__init__.py,sha256=TPy3eZi-AEztci_QZ37YAAl2zvUQlwBALpyiQx2ED7Q,363
|
|
6
|
-
devs/core/integration.py,sha256=cM3bIok06Z4faIkTyF8h35FeKdHpnx3_h2mXnJ1SaW0,13935
|
|
7
|
-
devs/utils/__init__.py,sha256=f-sEWETPfW2Xkaxgd-l6FS-jIQAorLlQZOicIZvp-W0,638
|
|
8
|
-
devs_cli-4.0.7.dist-info/licenses/LICENSE,sha256=bi2EUiv-lmC_quQVkNqzTYXJpjVarkPsVKfqhJl7ccQ,1067
|
|
9
|
-
devs_cli-4.0.7.dist-info/METADATA,sha256=kak8KcJlQeXQGLObaeobYBGZWS9CsCFOOaRYMu9j6B0,5282
|
|
10
|
-
devs_cli-4.0.7.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
11
|
-
devs_cli-4.0.7.dist-info/entry_points.txt,sha256=s8-pgqZ1QvzPJgHP9vNxwBYdezmGsFdRUHacJPZ4WOs,39
|
|
12
|
-
devs_cli-4.0.7.dist-info/top_level.txt,sha256=9RIVUPVGuOdO84qkBh_9XcKoTV7773o3py78wz2-IZk,5
|
|
13
|
-
devs_cli-4.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|