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.
Files changed (80) hide show
  1. snowflake/cli_sandbox/__init__.py +13 -0
  2. snowflake/cli_sandbox/_adapter.py +170 -0
  3. snowflake/cli_sandbox/_common.py +77 -0
  4. snowflake/cli_sandbox/_egress_flags.py +121 -0
  5. snowflake/cli_sandbox/_get_command.py +109 -0
  6. snowflake/cli_sandbox/_run_command.py +1091 -0
  7. snowflake/cli_sandbox/_shell_command.py +666 -0
  8. snowflake/cli_sandbox/_upload_plan.py +187 -0
  9. snowflake/cli_sandbox/commands.py +556 -0
  10. snowflake/cli_sandbox/plugin_spec.py +28 -0
  11. snowflake/cli_sandbox/py.typed +0 -0
  12. snowflake/sandbox/__init__.py +317 -0
  13. snowflake/sandbox/__main__.py +225 -0
  14. snowflake/sandbox/_ansi.py +206 -0
  15. snowflake/sandbox/_args.py +208 -0
  16. snowflake/sandbox/_assemble.py +256 -0
  17. snowflake/sandbox/_bundle.py +240 -0
  18. snowflake/sandbox/_connection_resolve.py +328 -0
  19. snowflake/sandbox/_deploy_spec.py +56 -0
  20. snowflake/sandbox/_diagnostics.py +501 -0
  21. snowflake/sandbox/_env.py +143 -0
  22. snowflake/sandbox/_files_mixin.py +280 -0
  23. snowflake/sandbox/_fs_ops.py +304 -0
  24. snowflake/sandbox/_globs.py +176 -0
  25. snowflake/sandbox/_hosts.py +110 -0
  26. snowflake/sandbox/_mcp_discovery.py +288 -0
  27. snowflake/sandbox/_mcp_status.py +183 -0
  28. snowflake/sandbox/_retry.py +94 -0
  29. snowflake/sandbox/_runtime/__init__.py +42 -0
  30. snowflake/sandbox/_runtime/_fs_helper.py +93 -0
  31. snowflake/sandbox/_runtime/_job_runner.py +111 -0
  32. snowflake/sandbox/_runtime/_protocol.py +53 -0
  33. snowflake/sandbox/_runtime/_shims.py +267 -0
  34. snowflake/sandbox/_sandbox_state.py +303 -0
  35. snowflake/sandbox/_session_registry.py +222 -0
  36. snowflake/sandbox/_sse.py +160 -0
  37. snowflake/sandbox/_stage.py +270 -0
  38. snowflake/sandbox/_sync_files_mixin.py +272 -0
  39. snowflake/sandbox/_sync_fs_ops.py +185 -0
  40. snowflake/sandbox/_sync_transport.py +737 -0
  41. snowflake/sandbox/_sync_watch.py +99 -0
  42. snowflake/sandbox/_transport.py +1366 -0
  43. snowflake/sandbox/_transport_errors.py +270 -0
  44. snowflake/sandbox/_upload_plan.py +497 -0
  45. snowflake/sandbox/_version.py +37 -0
  46. snowflake/sandbox/_watch.py +164 -0
  47. snowflake/sandbox/_wire.py +348 -0
  48. snowflake/sandbox/app.py +256 -0
  49. snowflake/sandbox/client.py +2356 -0
  50. snowflake/sandbox/config.py +1133 -0
  51. snowflake/sandbox/connect.py +288 -0
  52. snowflake/sandbox/deploy.py +499 -0
  53. snowflake/sandbox/egress.py +388 -0
  54. snowflake/sandbox/exceptions.py +253 -0
  55. snowflake/sandbox/exec_stream.py +264 -0
  56. snowflake/sandbox/files.py +547 -0
  57. snowflake/sandbox/function.py +567 -0
  58. snowflake/sandbox/image.py +46 -0
  59. snowflake/sandbox/jobs.py +649 -0
  60. snowflake/sandbox/lifecycle.py +67 -0
  61. snowflake/sandbox/log_stream.py +219 -0
  62. snowflake/sandbox/mcp.py +480 -0
  63. snowflake/sandbox/mount.py +161 -0
  64. snowflake/sandbox/py.typed +0 -0
  65. snowflake/sandbox/secret.py +244 -0
  66. snowflake/sandbox/session_app.py +244 -0
  67. snowflake/sandbox/shell.py +556 -0
  68. snowflake/sandbox/sync_client.py +2245 -0
  69. snowflake/sandbox/sync_exec_stream.py +238 -0
  70. snowflake/sandbox/sync_files.py +377 -0
  71. snowflake/sandbox/sync_log_stream.py +142 -0
  72. snowflake/sandbox/sync_shell.py +413 -0
  73. snowflake/sandbox/types.py +193 -0
  74. snowflake/sandbox/warm_session.py +700 -0
  75. snowflake_sandbox_python-0.2.1a1.dist-info/METADATA +339 -0
  76. snowflake_sandbox_python-0.2.1a1.dist-info/RECORD +80 -0
  77. snowflake_sandbox_python-0.2.1a1.dist-info/WHEEL +5 -0
  78. snowflake_sandbox_python-0.2.1a1.dist-info/entry_points.txt +2 -0
  79. snowflake_sandbox_python-0.2.1a1.dist-info/licenses/LICENSE +202 -0
  80. 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