withruntime 0.5.0__tar.gz → 0.5.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.
Files changed (96) hide show
  1. {withruntime-0.5.0 → withruntime-0.5.1}/PKG-INFO +1 -1
  2. {withruntime-0.5.0 → withruntime-0.5.1}/pyproject.toml +1 -1
  3. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_daytona.py +10 -0
  4. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_e2b_sandbox.py +7 -0
  5. withruntime-0.5.1/withruntime/_version.py +1 -0
  6. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/daytona/_async_daytona.py +5 -3
  7. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/daytona/_core.py +7 -0
  8. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/daytona/_sync_daytona.py +5 -3
  9. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/_async_sandbox.py +2 -2
  10. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/_core.py +7 -0
  11. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/_sync_sandbox.py +2 -2
  12. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime.egg-info/PKG-INFO +1 -1
  13. withruntime-0.5.0/withruntime/_version.py +0 -1
  14. {withruntime-0.5.0 → withruntime-0.5.1}/README.md +0 -0
  15. {withruntime-0.5.0 → withruntime-0.5.1}/setup.cfg +0 -0
  16. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_audit.py +0 -0
  17. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_capacity_wait.py +0 -0
  18. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_client.py +0 -0
  19. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_deepagents.py +0 -0
  20. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_e2b_code_interpreter.py +0 -0
  21. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_images_v2.py +0 -0
  22. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_images_volumes_interpreter.py +0 -0
  23. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_lifecycle_settings.py +0 -0
  24. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_limits.py +0 -0
  25. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_observability.py +0 -0
  26. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_openai_agents.py +0 -0
  27. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_previews_network_desktop.py +0 -0
  28. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_proxy.py +0 -0
  29. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_referrals.py +0 -0
  30. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_secrets.py +0 -0
  31. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_switching.py +0 -0
  32. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_tools.py +0 -0
  33. {withruntime-0.5.0 → withruntime-0.5.1}/tests/test_vercel.py +0 -0
  34. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/__init__.py +0 -0
  35. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_client.py +0 -0
  36. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/__init__.py +0 -0
  37. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/audit.py +0 -0
  38. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/desktop.py +0 -0
  39. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/images.py +0 -0
  40. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/interpreter.py +0 -0
  41. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/limits.py +0 -0
  42. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/network.py +0 -0
  43. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/observability.py +0 -0
  44. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/previews.py +0 -0
  45. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/referrals.py +0 -0
  46. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/secrets.py +0 -0
  47. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/switching.py +0 -0
  48. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_async_products/volumes.py +0 -0
  49. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_clock.py +0 -0
  50. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_connection.py +0 -0
  51. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_errors.py +0 -0
  52. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_http.py +0 -0
  53. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_proxy.py +0 -0
  54. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_client.py +0 -0
  55. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/__init__.py +0 -0
  56. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/audit.py +0 -0
  57. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/desktop.py +0 -0
  58. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/images.py +0 -0
  59. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/interpreter.py +0 -0
  60. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/limits.py +0 -0
  61. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/network.py +0 -0
  62. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/observability.py +0 -0
  63. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/previews.py +0 -0
  64. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/referrals.py +0 -0
  65. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/secrets.py +0 -0
  66. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/switching.py +0 -0
  67. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_sync_products/volumes.py +0 -0
  68. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_tunnel.py +0 -0
  69. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/_ws.py +0 -0
  70. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/daytona/__init__.py +0 -0
  71. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/daytona/_async_io.py +0 -0
  72. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/daytona/_sync_io.py +0 -0
  73. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/deepagents.py +0 -0
  74. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/__init__.py +0 -0
  75. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/_async_io.py +0 -0
  76. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/_sync_io.py +0 -0
  77. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/code_interpreter/__init__.py +0 -0
  78. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/code_interpreter/_async_ci.py +0 -0
  79. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/code_interpreter/_models.py +0 -0
  80. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/e2b/code_interpreter/_sync_ci.py +0 -0
  81. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/openai_agents.py +0 -0
  82. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/tools.py +0 -0
  83. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/__init__.py +0 -0
  84. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/_async_io.py +0 -0
  85. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/_async_sandbox.py +0 -0
  86. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/_core.py +0 -0
  87. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/_sync_io.py +0 -0
  88. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/_sync_sandbox.py +0 -0
  89. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/api.py +0 -0
  90. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/sandbox/__init__.py +0 -0
  91. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/vercel/sandbox/sync.py +0 -0
  92. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime/webhooks.py +0 -0
  93. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime.egg-info/SOURCES.txt +0 -0
  94. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime.egg-info/dependency_links.txt +0 -0
  95. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime.egg-info/requires.txt +0 -0
  96. {withruntime-0.5.0 → withruntime-0.5.1}/withruntime.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: withruntime
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "withruntime"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -159,6 +159,16 @@ class Process(Base):
159
159
  self.assertEqual(command, "{ ls\n} 2>&1")
160
160
  self.assertEqual(options, {"cwd": "/workspace/src", "env": {"A": "1", "B": "2"}, "timeout_ms": 5000})
161
161
 
162
+ def test_whole_output_past_the_64_kib_an_exec_result_holds(self):
163
+ big = "x" * 70_000 + "\n"
164
+ self.world.exec = lambda command, _: (Result(0, "/workspace/a.py:1:x\n" * 4_000)
165
+ if str(command).startswith("['grep'") else Result(0, big))
166
+ sandbox = self.daytona.create()
167
+ # A timeout of a minute or less is an exec that is not otherwise streamed.
168
+ self.assertEqual(sandbox.process.exec("cat big", timeout=30).result, big)
169
+ self.assertEqual(sandbox.process.code_run("print('x'*70000)", timeout=30).result, big)
170
+ self.assertEqual(len(sandbox.fs.find_files(".", "x")), 4_000)
171
+
162
172
  def test_timeout(self):
163
173
  self.world.exec = lambda command, _: Result(None, timed_out=True)
164
174
  sandbox = self.daytona.create()
@@ -138,6 +138,13 @@ class Commands(Base):
138
138
  self.assertEqual(self.world.called("sandbox.exec")[-1],
139
139
  ("echo hi", {"cwd": "/tmp", "env": {"A": "1", "B": "3"}, "timeout_ms": 60_000}))
140
140
 
141
+ def test_whole_output_past_the_64_kib_an_exec_result_holds(self):
142
+ # The judge panel's reproduction: python3 -c 'print("x"*70000)'.
143
+ self.world.exec = lambda *_: Result(0, "x" * 70_000 + "\n", "y" * 70_000)
144
+ sbx = self.create()
145
+ result = sbx.commands.run("python3 -c 'print(\"x\"*70000)'", timeout=60)
146
+ self.assertEqual((result.exit_code, len(result.stdout), len(result.stderr)), (0, 70_001, 70_000))
147
+
141
148
  def test_non_zero_exit(self):
142
149
  self.world.exec = lambda *_: Result(3, "partial\n", "boom\n")
143
150
  sbx = self.create()
@@ -0,0 +1 @@
1
+ VERSION = "0.5.1"
@@ -75,7 +75,7 @@ class AsyncProcess:
75
75
  timeout_ms = int(timeout * 1000) if timeout else core.LONGEST_MS
76
76
  result = await _guard("sandbox", lambda: runtime.exec(
77
77
  f"{{ {command}\n}} 2>&1", cwd=core.HOME if cwd is None else core.resolve_path(cwd), env=self._env(env),
78
- timeout_ms=timeout_ms))
78
+ timeout_ms=timeout_ms, on_stdout=core.whole_output))
79
79
  if result.timed_out:
80
80
  raise DaytonaProcessExecutionTimeoutError(f"Command timed out after {timeout} s.", 408)
81
81
  output = result.stdout + result.stderr
@@ -93,7 +93,8 @@ class AsyncProcess:
93
93
  argv = ["sh", "-c", 'exec "$@" 2>&1', "sh", *interpreter, *((params.argv if params else None) or [])]
94
94
  timeout_ms = int(timeout * 1000) if timeout else core.LONGEST_MS
95
95
  result = await _guard("sandbox", lambda: runtime.exec(
96
- argv, cwd=core.HOME, env=self._env(params.env if params else None), timeout_ms=timeout_ms))
96
+ argv, cwd=core.HOME, env=self._env(params.env if params else None), timeout_ms=timeout_ms,
97
+ on_stdout=core.whole_output))
97
98
  if result.timed_out:
98
99
  raise DaytonaProcessExecutionTimeoutError(f"Code run timed out after {timeout} s.", 408)
99
100
  return ExecuteResponse(exit_code=-1 if result.exit_code is None else result.exit_code, result=result.stdout,
@@ -325,7 +326,8 @@ class AsyncFileSystem:
325
326
  async def find_files(self, path: str, pattern: str) -> List[Match]:
326
327
  target = await self._path(path)
327
328
  runtime = await self._sandbox._live()
328
- result = await _guard("sandbox", lambda: runtime.exec(["grep", "-rnI", "--", pattern, target]))
329
+ result = await _guard("sandbox", lambda: runtime.exec(
330
+ ["grep", "-rnI", "--", pattern, target], on_stdout=core.whole_output))
329
331
  if result.exit_code not in (0, 1):
330
332
  raise DaytonaError(result.stderr.strip() or "grep failed", 400)
331
333
  return core.parse_matches(result.stdout)
@@ -522,6 +522,13 @@ HOME = "/workspace"
522
522
  DAYTONA_HOME = "/home/daytona"
523
523
  HOME_LINK = f"[ -e {DAYTONA_HOME} ] || sudo ln -s {HOME} {DAYTONA_HOME}"
524
524
  LONGEST_MS = 86_400_000
525
+
526
+
527
+ def whole_output(_text: str) -> None:
528
+ """Given to exec as an output callback so it streams and returns the whole
529
+ output: an exec with no callback returns at most 64 KiB of each stream."""
530
+
531
+
525
532
  UUID = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", re.I)
526
533
  STOCK_SNAPSHOT = re.compile(r"^daytona(io)?[-/:]|^daytona$")
527
534
  LANGUAGE_LABEL = "code-toolbox-language"
@@ -73,7 +73,7 @@ class Process:
73
73
  timeout_ms = int(timeout * 1000) if timeout else core.LONGEST_MS
74
74
  result = _guard("sandbox", lambda: runtime.exec(
75
75
  f"{{ {command}\n}} 2>&1", cwd=core.HOME if cwd is None else core.resolve_path(cwd), env=self._env(env),
76
- timeout_ms=timeout_ms))
76
+ timeout_ms=timeout_ms, on_stdout=core.whole_output))
77
77
  if result.timed_out:
78
78
  raise DaytonaProcessExecutionTimeoutError(f"Command timed out after {timeout} s.", 408)
79
79
  output = result.stdout + result.stderr
@@ -91,7 +91,8 @@ class Process:
91
91
  argv = ["sh", "-c", 'exec "$@" 2>&1', "sh", *interpreter, *((params.argv if params else None) or [])]
92
92
  timeout_ms = int(timeout * 1000) if timeout else core.LONGEST_MS
93
93
  result = _guard("sandbox", lambda: runtime.exec(
94
- argv, cwd=core.HOME, env=self._env(params.env if params else None), timeout_ms=timeout_ms))
94
+ argv, cwd=core.HOME, env=self._env(params.env if params else None), timeout_ms=timeout_ms,
95
+ on_stdout=core.whole_output))
95
96
  if result.timed_out:
96
97
  raise DaytonaProcessExecutionTimeoutError(f"Code run timed out after {timeout} s.", 408)
97
98
  return ExecuteResponse(exit_code=-1 if result.exit_code is None else result.exit_code, result=result.stdout,
@@ -323,7 +324,8 @@ class FileSystem:
323
324
  def find_files(self, path: str, pattern: str) -> List[Match]:
324
325
  target = self._path(path)
325
326
  runtime = self._sandbox._live()
326
- result = _guard("sandbox", lambda: runtime.exec(["grep", "-rnI", "--", pattern, target]))
327
+ result = _guard("sandbox", lambda: runtime.exec(
328
+ ["grep", "-rnI", "--", pattern, target], on_stdout=core.whole_output))
327
329
  if result.exit_code not in (0, 1):
328
330
  raise DaytonaError(result.stderr.strip() or "grep failed", 400)
329
331
  return core.parse_matches(result.stdout)
@@ -160,8 +160,8 @@ class AsyncCommands:
160
160
  handle = await self._start(cmd, envs, cwd, bool(stdin), timeout_ms, on_stdout, on_stderr)
161
161
  return handle if background else await handle.wait()
162
162
  result = await _guard("sandbox", lambda: self._sandbox.runtime.exec(
163
- cmd, cwd=cwd, env=self._env(envs), timeout_ms=timeout_ms, on_stdout=wrap(on_stdout),
164
- on_stderr=wrap(on_stderr)))
163
+ cmd, cwd=cwd, env=self._env(envs), timeout_ms=timeout_ms,
164
+ on_stdout=wrap(on_stdout) or core.whole_output, on_stderr=wrap(on_stderr)))
165
165
  return core.settle(result.exit_code, result.stdout, result.stderr, result.timed_out, timeout_ms)
166
166
 
167
167
  async def _start(self, cmd: str, envs: Optional[Dict[str, str]], cwd: Optional[str], stdin: bool,
@@ -190,6 +190,13 @@ DEFAULT_TIMEOUT = 300
190
190
  MIN_LEASE, MAX_LEASE = 60, 3600
191
191
  COMMAND_TIMEOUT = 60
192
192
  LONGEST_MS = 86_400_000
193
+
194
+
195
+ def whole_output(_text: str) -> None:
196
+ """Given to exec as an output callback so it streams and returns the whole
197
+ output: an exec with no callback returns at most 64 KiB of each stream."""
198
+
199
+
193
200
  STOCK_TEMPLATES = frozenset({"base", "code-interpreter-v1", "code-interpreter"})
194
201
  UUID = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", re.I)
195
202
  HOME = "/workspace"
@@ -159,8 +159,8 @@ class Commands:
159
159
  handle = self._start(cmd, envs, cwd, bool(stdin), timeout_ms, on_stdout, on_stderr)
160
160
  return handle if background else handle.wait()
161
161
  result = _guard("sandbox", lambda: self._sandbox.runtime.exec(
162
- cmd, cwd=cwd, env=self._env(envs), timeout_ms=timeout_ms, on_stdout=wrap(on_stdout),
163
- on_stderr=wrap(on_stderr)))
162
+ cmd, cwd=cwd, env=self._env(envs), timeout_ms=timeout_ms,
163
+ on_stdout=wrap(on_stdout) or core.whole_output, on_stderr=wrap(on_stderr)))
164
164
  return core.settle(result.exit_code, result.stdout, result.stderr, result.timed_out, timeout_ms)
165
165
 
166
166
  def _start(self, cmd: str, envs: Optional[Dict[str, str]], cwd: Optional[str], stdin: bool,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: withruntime
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1 +0,0 @@
1
- VERSION = "0.5.0"
File without changes
File without changes