snowflake-sandbox-python 0.2.1a1__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.
- snowflake/cli_sandbox/__init__.py +13 -0
- snowflake/cli_sandbox/_adapter.py +170 -0
- snowflake/cli_sandbox/_common.py +77 -0
- snowflake/cli_sandbox/_egress_flags.py +121 -0
- snowflake/cli_sandbox/_get_command.py +109 -0
- snowflake/cli_sandbox/_run_command.py +1091 -0
- snowflake/cli_sandbox/_shell_command.py +666 -0
- snowflake/cli_sandbox/_upload_plan.py +187 -0
- snowflake/cli_sandbox/commands.py +556 -0
- snowflake/cli_sandbox/plugin_spec.py +28 -0
- snowflake/cli_sandbox/py.typed +0 -0
- snowflake/sandbox/__init__.py +317 -0
- snowflake/sandbox/__main__.py +225 -0
- snowflake/sandbox/_ansi.py +206 -0
- snowflake/sandbox/_args.py +208 -0
- snowflake/sandbox/_assemble.py +256 -0
- snowflake/sandbox/_bundle.py +240 -0
- snowflake/sandbox/_connection_resolve.py +328 -0
- snowflake/sandbox/_deploy_spec.py +56 -0
- snowflake/sandbox/_diagnostics.py +501 -0
- snowflake/sandbox/_env.py +143 -0
- snowflake/sandbox/_files_mixin.py +280 -0
- snowflake/sandbox/_fs_ops.py +304 -0
- snowflake/sandbox/_globs.py +176 -0
- snowflake/sandbox/_hosts.py +110 -0
- snowflake/sandbox/_mcp_discovery.py +288 -0
- snowflake/sandbox/_mcp_status.py +183 -0
- snowflake/sandbox/_retry.py +94 -0
- snowflake/sandbox/_runtime/__init__.py +42 -0
- snowflake/sandbox/_runtime/_fs_helper.py +93 -0
- snowflake/sandbox/_runtime/_job_runner.py +111 -0
- snowflake/sandbox/_runtime/_protocol.py +53 -0
- snowflake/sandbox/_runtime/_shims.py +267 -0
- snowflake/sandbox/_sandbox_state.py +303 -0
- snowflake/sandbox/_session_registry.py +222 -0
- snowflake/sandbox/_sse.py +160 -0
- snowflake/sandbox/_stage.py +270 -0
- snowflake/sandbox/_sync_files_mixin.py +272 -0
- snowflake/sandbox/_sync_fs_ops.py +185 -0
- snowflake/sandbox/_sync_transport.py +737 -0
- snowflake/sandbox/_sync_watch.py +99 -0
- snowflake/sandbox/_transport.py +1366 -0
- snowflake/sandbox/_transport_errors.py +270 -0
- snowflake/sandbox/_upload_plan.py +497 -0
- snowflake/sandbox/_version.py +37 -0
- snowflake/sandbox/_watch.py +164 -0
- snowflake/sandbox/_wire.py +348 -0
- snowflake/sandbox/app.py +256 -0
- snowflake/sandbox/client.py +2356 -0
- snowflake/sandbox/config.py +1133 -0
- snowflake/sandbox/connect.py +288 -0
- snowflake/sandbox/deploy.py +499 -0
- snowflake/sandbox/egress.py +388 -0
- snowflake/sandbox/exceptions.py +253 -0
- snowflake/sandbox/exec_stream.py +264 -0
- snowflake/sandbox/files.py +547 -0
- snowflake/sandbox/function.py +567 -0
- snowflake/sandbox/image.py +46 -0
- snowflake/sandbox/jobs.py +649 -0
- snowflake/sandbox/lifecycle.py +67 -0
- snowflake/sandbox/log_stream.py +219 -0
- snowflake/sandbox/mcp.py +480 -0
- snowflake/sandbox/mount.py +161 -0
- snowflake/sandbox/py.typed +0 -0
- snowflake/sandbox/secret.py +244 -0
- snowflake/sandbox/session_app.py +244 -0
- snowflake/sandbox/shell.py +556 -0
- snowflake/sandbox/sync_client.py +2245 -0
- snowflake/sandbox/sync_exec_stream.py +238 -0
- snowflake/sandbox/sync_files.py +377 -0
- snowflake/sandbox/sync_log_stream.py +142 -0
- snowflake/sandbox/sync_shell.py +413 -0
- snowflake/sandbox/types.py +193 -0
- snowflake/sandbox/warm_session.py +700 -0
- snowflake_sandbox_python-0.2.1a1.dist-info/METADATA +339 -0
- snowflake_sandbox_python-0.2.1a1.dist-info/RECORD +80 -0
- snowflake_sandbox_python-0.2.1a1.dist-info/WHEEL +5 -0
- snowflake_sandbox_python-0.2.1a1.dist-info/entry_points.txt +2 -0
- snowflake_sandbox_python-0.2.1a1.dist-info/licenses/LICENSE +202 -0
- snowflake_sandbox_python-0.2.1a1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""Public data types for ``snowflake.sandbox``.
|
|
2
|
+
|
|
3
|
+
Kept import-cheap (stdlib + ``typing`` only — no httpx, no pydantic) so the
|
|
4
|
+
``__init__`` lazy loader can pull these in without breaking the import-time
|
|
5
|
+
budget.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from enum import StrEnum
|
|
11
|
+
from typing import Literal, NamedTuple, get_args
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"ExecResult",
|
|
15
|
+
"StreamLine",
|
|
16
|
+
"MemoryTier",
|
|
17
|
+
"SandboxStatus",
|
|
18
|
+
"SANDBOX_STATUSES",
|
|
19
|
+
"StreamName",
|
|
20
|
+
"RunStatus",
|
|
21
|
+
"JobStatus",
|
|
22
|
+
"TERMINAL_STATUSES",
|
|
23
|
+
"FileInfo",
|
|
24
|
+
"FileWatchEventType",
|
|
25
|
+
"FileWatchEvent",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
MemoryTier = Literal["1g", "4g", "8g", "16g", "32g", "64g"]
|
|
30
|
+
"""Snowflake memory tiers — a closed enum exposed at the SDK surface."""
|
|
31
|
+
|
|
32
|
+
SandboxStatus = Literal["pending", "ready", "dead", "failed", "unknown"]
|
|
33
|
+
"""Sandbox lifecycle state, mapped from the server's own vocabulary.
|
|
34
|
+
|
|
35
|
+
``client._parse_status`` maps the server's word onto one of these five:
|
|
36
|
+
|
|
37
|
+
| this value | server words that map to it |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| ``pending`` | ``starting``, ``pending``, ``not_started``, ``resuming``, ``suspending`` |
|
|
40
|
+
| ``ready`` | ``running``, ``ready``, ``suspended`` |
|
|
41
|
+
| ``dead`` | ``stopped``, ``crashed``, ``dead``, ``stopping`` |
|
|
42
|
+
| ``failed`` | ``failed`` |
|
|
43
|
+
| ``unknown`` | ``unknown``, anything else |
|
|
44
|
+
|
|
45
|
+
Both terminal values mean "this sandbox will do no more work; make a new one".
|
|
46
|
+
They differ only in WHEN it ended: ``failed`` is an async create (202 path) that
|
|
47
|
+
hit a server-side error — platform failure, bad image — so no container ever ran,
|
|
48
|
+
while ``dead`` is one that ran and then ended.
|
|
49
|
+
|
|
50
|
+
Neither says WHETHER something went wrong, because ``dead`` covers a deliberate
|
|
51
|
+
stop and a crash alike. `Sandbox.server_status` keeps the server's own word, so
|
|
52
|
+
``dead`` + ``stopped`` and ``dead`` + ``crashed`` are distinguishable there — and
|
|
53
|
+
``snow sandbox list`` shows it in its REASON column.
|
|
54
|
+
|
|
55
|
+
A transition (``resuming``, ``suspending``) is ``pending`` rather than ``ready``: an exec
|
|
56
|
+
would work -- every exec re-drives StartApp, which is what completes a resume -- but it can
|
|
57
|
+
block for seconds, and a status a caller checks BEFORE acting must not promise a sandbox is
|
|
58
|
+
servable when it is not yet. `Sandbox.server_status` keeps the transition's own word, so it
|
|
59
|
+
stays visible without ``status`` over-promising.
|
|
60
|
+
|
|
61
|
+
``unknown`` covers two cases that are the same answer to the caller: the server said
|
|
62
|
+
``unknown`` (a state it declines to name) or it said a word this SDK does not
|
|
63
|
+
recognize. Only the second warns (`exceptions.SandboxContractWarning`) — advising an
|
|
64
|
+
SDK upgrade for a word the server chose deliberately is noise. Neither is collapsed
|
|
65
|
+
into ``ready``, which is what made a contract drift read as a healthy sandbox.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
SANDBOX_STATUSES: frozenset[str] = frozenset(get_args(SandboxStatus))
|
|
69
|
+
"""The `SandboxStatus` values, as a runtime-checkable set.
|
|
70
|
+
|
|
71
|
+
Derived from the `SandboxStatus` Literal with ``get_args`` rather than written out
|
|
72
|
+
again, so the two can never drift. `Literal` is a static-only construct -- nothing
|
|
73
|
+
enforces it at runtime -- so callers that need to *validate* a caller-supplied
|
|
74
|
+
status (rather than merely annotate one) need this.
|
|
75
|
+
|
|
76
|
+
These are the SDK's mapped statuses, not the server's raw vocabulary: a caller
|
|
77
|
+
filtering by state wants ``ready``, not the server's ``running``. The mapping is
|
|
78
|
+
one-to-many (``ready`` <- running|ready|suspended, ``pending`` <- starting|pending|
|
|
79
|
+
not_started|resuming|suspending, ``dead`` <- crashed|stopped|dead|stopping), which is
|
|
80
|
+
why a single ``?status=`` query param cannot express it and why ``list_sandboxes``
|
|
81
|
+
filters client-side. The authoritative table is ``_wire._SERVER_STATUS``.
|
|
82
|
+
|
|
83
|
+
Every value here is a legitimate filter input, including ``failed``, which describes
|
|
84
|
+
how a status was *arrived at* rather than what the server said: it is produced only by
|
|
85
|
+
the async-create (202) path, where a server-side error makes the create terminal
|
|
86
|
+
without any container running.
|
|
87
|
+
|
|
88
|
+
``unknown`` is a filter input for two different reasons, and both are answerable
|
|
89
|
+
because ``list_sandboxes`` filters locally on the mapped value: the server has its own
|
|
90
|
+
``unknown`` (a state it declines to name), and the SDK produces ``unknown`` for a word
|
|
91
|
+
it does not recognize. So ``status="unknown"`` answers both "which sandboxes is the
|
|
92
|
+
server unsure about" and the occasionally urgent "which is this SDK failing to parse",
|
|
93
|
+
e.g. after a server upgrade.
|
|
94
|
+
|
|
95
|
+
None of that splits the set: a separate FILTERABLE_STATUSES would have been right when
|
|
96
|
+
the filter was applied server-side, and would now wrongly reject answerable queries.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
RunStatus = Literal["succeeded", "failed", "timed_out"]
|
|
100
|
+
"""Terminal outcome of a detached run (`RunResult.status`) -- the states a
|
|
101
|
+
``get``/``wait`` resolves to. A closed enum; unknown wire values are clamped to
|
|
102
|
+
``failed`` at the parse boundary."""
|
|
103
|
+
|
|
104
|
+
JobStatus = Literal["succeeded", "failed", "running"]
|
|
105
|
+
"""Lifecycle status reported by `Job.status()` / `SyncJob.status()`: a finished
|
|
106
|
+
run's ``succeeded``/``failed``, or ``running`` while still live. ``timed_out`` is a
|
|
107
|
+
``get()`` outcome, not a live status, so it is not a member here."""
|
|
108
|
+
|
|
109
|
+
StreamName = Literal["stdout", "stderr"]
|
|
110
|
+
"""SSE stream channel for a streaming exec frame."""
|
|
111
|
+
|
|
112
|
+
TERMINAL_STATUSES: frozenset[str] = frozenset({"dead", "failed"})
|
|
113
|
+
"""Statuses after which a container produces no further output.
|
|
114
|
+
|
|
115
|
+
``failed`` is added for the async create (202) path: a server-side error
|
|
116
|
+
makes the create terminal without the container ever being live.
|
|
117
|
+
|
|
118
|
+
Lives here rather than in ``client`` so ``log_stream`` can read it without an
|
|
119
|
+
import cycle.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ExecResult(NamedTuple):
|
|
124
|
+
"""Result of a non-streaming `Sandbox.exec()`.
|
|
125
|
+
|
|
126
|
+
``stdout`` / ``stderr`` are decoded strings when ``text=True`` (the
|
|
127
|
+
default). ``exit_code`` is the in-container process exit. ``elapsed_ms``
|
|
128
|
+
is wall-clock time on the server side, not including network round-trip.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
stdout: str
|
|
132
|
+
stderr: str
|
|
133
|
+
exit_code: int
|
|
134
|
+
elapsed_ms: int
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class StreamLine(NamedTuple):
|
|
138
|
+
"""One logical line yielded by `Sandbox.exec_stream()`.
|
|
139
|
+
|
|
140
|
+
``data`` has its trailing ``\\n`` stripped. ``stream`` indicates which
|
|
141
|
+
channel (``"stdout"`` or ``"stderr"``) the line came from.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
stream: StreamName
|
|
145
|
+
data: str
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class FileInfo(NamedTuple):
|
|
149
|
+
"""Metadata for one path, returned by `Sandbox.list_files()` / `.stat()`.
|
|
150
|
+
|
|
151
|
+
Mirrors Modal's ``Sandbox.filesystem.stat`` shape. Both producers are
|
|
152
|
+
implemented (``files.py`` runs an in-container ``python3`` helper over
|
|
153
|
+
``exec``); ``modified_at`` is a Unix epoch (seconds, UTC) or ``None`` when the
|
|
154
|
+
server did not report it.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
path: str
|
|
158
|
+
is_dir: bool
|
|
159
|
+
size_bytes: int
|
|
160
|
+
modified_at: float | None = None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class FileWatchEventType(StrEnum):
|
|
164
|
+
"""Coarse change class for a `Sandbox.watch()` event.
|
|
165
|
+
|
|
166
|
+
Mirrors Modal's ``FileWatchEventType``. The sandbox observes raw Linux
|
|
167
|
+
``inotify(7)`` masks and maps them onto this small enum — several inotify
|
|
168
|
+
bits collapse to one class (e.g. ``IN_MODIFY`` and ``IN_CLOSE_WRITE`` both
|
|
169
|
+
read as `Modify`; ``IN_CREATE`` and ``IN_MOVED_TO`` both as `Create`). A
|
|
170
|
+
mask that maps to nothing meaningful surfaces as `Unknown` rather than being
|
|
171
|
+
dropped, so a contract drift is visible instead of silent.
|
|
172
|
+
|
|
173
|
+
``str``-valued so it compares equal to its wire string and JSON-serializes
|
|
174
|
+
cleanly.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
Unknown = "Unknown"
|
|
178
|
+
Access = "Access"
|
|
179
|
+
Create = "Create"
|
|
180
|
+
Modify = "Modify"
|
|
181
|
+
Delete = "Delete"
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class FileWatchEvent(NamedTuple):
|
|
185
|
+
"""One filesystem-change event yielded by `Sandbox.watch()`.
|
|
186
|
+
|
|
187
|
+
Mirrors Modal's ``FileWatchEvent``: ``paths`` are the absolute in-sandbox
|
|
188
|
+
path(s) the change concerns (usually one), and ``type`` is the coarse
|
|
189
|
+
`FileWatchEventType`.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
paths: list[str]
|
|
193
|
+
type: FileWatchEventType
|