scalebox-sdk 1.0.1__py3-none-any.whl → 1.0.3__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 (44) hide show
  1. scalebox/__init__.py +1 -1
  2. scalebox/api/client/api/sandboxes/get_sandboxes.py +1 -1
  3. scalebox/api/client/models/error.py +1 -1
  4. scalebox/api/client/models/listed_sandbox.py +6 -3
  5. scalebox/api/client/models/sandbox.py +2 -2
  6. scalebox/code_interpreter/code_interpreter_async.py +3 -1
  7. scalebox/code_interpreter/code_interpreter_sync.py +3 -1
  8. scalebox/connection_config.py +2 -0
  9. scalebox/generated/api_pb2_connect.py +3 -3
  10. scalebox/sandbox/main.py +1 -1
  11. scalebox/sandbox_async/main.py +1 -1
  12. scalebox/sandbox_sync/main.py +1 -1
  13. scalebox/test/bedrock_openai_adapter.py +8 -2
  14. scalebox/test/run_stress_code_interpreter_sync.py +18 -6
  15. scalebox/test/simple_upload_example.py +39 -31
  16. scalebox/test/stabitiy_test.py +82 -69
  17. scalebox/test/test_browser_use.py +4 -2
  18. scalebox/test/test_browser_use_scalebox.py +5 -4
  19. scalebox/test/test_code_interpreter_execcode.py +289 -211
  20. scalebox/test/test_code_interpreter_sync_comprehensive.py +2 -5
  21. scalebox/test/test_connect_pause_async.py +34 -11
  22. scalebox/test/test_connect_pause_sync.py +49 -16
  23. scalebox/test/test_csx_desktop_examples.py +3 -3
  24. scalebox/test/test_desktop_sandbox_sf.py +18 -23
  25. scalebox/test/test_download_url.py +6 -14
  26. scalebox/test/test_existing_sandbox.py +1037 -0
  27. scalebox/test/test_sandbox_async_comprehensive.py +4 -2
  28. scalebox/test/test_sandbox_object_storage_example.py +14 -9
  29. scalebox/test/test_sandbox_object_storage_example_async.py +6 -3
  30. scalebox/test/test_sandbox_sync_comprehensive.py +1 -1
  31. scalebox/test/test_sf.py +12 -8
  32. scalebox/test/test_watch_dir_async.py +6 -4
  33. scalebox/test/testagetinfo.py +1 -3
  34. scalebox/test/testsandbox_api.py +5 -3
  35. scalebox/test/testsandbox_async.py +17 -47
  36. scalebox/test/testsandbox_sync.py +18 -14
  37. scalebox/test/upload_100mb_example.py +77 -55
  38. scalebox/version.py +2 -2
  39. {scalebox_sdk-1.0.1.dist-info → scalebox_sdk-1.0.3.dist-info}/METADATA +1 -1
  40. {scalebox_sdk-1.0.1.dist-info → scalebox_sdk-1.0.3.dist-info}/RECORD +44 -43
  41. {scalebox_sdk-1.0.1.dist-info → scalebox_sdk-1.0.3.dist-info}/WHEEL +0 -0
  42. {scalebox_sdk-1.0.1.dist-info → scalebox_sdk-1.0.3.dist-info}/entry_points.txt +0 -0
  43. {scalebox_sdk-1.0.1.dist-info → scalebox_sdk-1.0.3.dist-info}/licenses/LICENSE +0 -0
  44. {scalebox_sdk-1.0.1.dist-info → scalebox_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -106,7 +106,7 @@ result = {"x": x, "y": y}
106
106
  print(result)
107
107
  """
108
108
 
109
- execution = self.sandbox.run_code(code,envs={"CI_TEST": "sync_test1"})
109
+ execution = self.sandbox.run_code(code, envs={"CI_TEST": "sync_test1"})
110
110
  print(execution.to_json())
111
111
  # time.sleep(1000)
112
112
  assert isinstance(execution, Execution)
@@ -366,10 +366,7 @@ print(f"结果: {result}")
366
366
  assert self.sandbox is not None
367
367
 
368
368
  # 创建Python上下文
369
- python_context = self.sandbox.create_code_context(
370
- language="python",
371
- cwd="/tmp"
372
- )
369
+ python_context = self.sandbox.create_code_context(language="python", cwd="/tmp")
373
370
  print(python_context)
374
371
  assert isinstance(python_context, Context)
375
372
  assert python_context.id is not None
@@ -78,7 +78,9 @@ class ConnectPauseAsyncTest:
78
78
  # 4. 创建目录和文件
79
79
  print("Step 4: Creating directory and nested files...")
80
80
  await self.sandbox.files.make_dir("/tmp/test_dir")
81
- await self.sandbox.files.write("/tmp/test_dir/nested_file.txt", "Nested file content")
81
+ await self.sandbox.files.write(
82
+ "/tmp/test_dir/nested_file.txt", "Nested file content"
83
+ )
82
84
  assert await self.sandbox.files.exists("/tmp/test_dir")
83
85
  assert await self.sandbox.files.exists("/tmp/test_dir/nested_file.txt")
84
86
  print("Created directory and nested file")
@@ -106,13 +108,17 @@ class ConnectPauseAsyncTest:
106
108
  # 校验应该存在的文件
107
109
  exists = await connected_sandbox.files.exists("/tmp/test_file1.txt")
108
110
  assert exists, "test_file1.txt should exist"
109
- file1_content = await connected_sandbox.files.read("/tmp/test_file1.txt", format="text")
111
+ file1_content = await connected_sandbox.files.read(
112
+ "/tmp/test_file1.txt", format="text"
113
+ )
110
114
  assert "Content of test file 1" in file1_content
111
115
  print("✅ Verified test_file1.txt exists and content is correct")
112
116
 
113
117
  exists = await connected_sandbox.files.exists("/tmp/test_file3.bin")
114
118
  assert exists, "test_file3.bin should exist"
115
- file3_content = await connected_sandbox.files.read("/tmp/test_file3.bin", format="bytes")
119
+ file3_content = await connected_sandbox.files.read(
120
+ "/tmp/test_file3.bin", format="bytes"
121
+ )
116
122
  assert bytes(file3_content) == b"Binary content for test file 3"
117
123
  print("✅ Verified test_file3.bin exists and content is correct")
118
124
 
@@ -124,15 +130,21 @@ class ConnectPauseAsyncTest:
124
130
  # 校验目录和嵌套文件
125
131
  exists = await connected_sandbox.files.exists("/tmp/test_dir")
126
132
  assert exists, "test_dir should exist"
127
- exists = await connected_sandbox.files.exists("/tmp/test_dir/nested_file.txt")
133
+ exists = await connected_sandbox.files.exists(
134
+ "/tmp/test_dir/nested_file.txt"
135
+ )
128
136
  assert exists, "nested_file.txt should exist"
129
- nested_content = await connected_sandbox.files.read("/tmp/test_dir/nested_file.txt", format="text")
137
+ nested_content = await connected_sandbox.files.read(
138
+ "/tmp/test_dir/nested_file.txt", format="text"
139
+ )
130
140
  assert "Nested file content" in nested_content
131
141
  print("✅ Verified directory and nested file exist and content is correct")
132
142
 
133
143
  # 8. 在connect后的沙箱中执行一些操作验证功能正常
134
144
  print("Step 8: Verifying sandbox functionality after connect...")
135
- result = await connected_sandbox.commands.run("echo 'Test command after connect'")
145
+ result = await connected_sandbox.commands.run(
146
+ "echo 'Test command after connect'"
147
+ )
136
148
  assert result.exit_code == 0
137
149
  assert "Test command after connect" in result.stdout
138
150
  print("✅ Verified sandbox commands work after connect")
@@ -140,20 +152,27 @@ class ConnectPauseAsyncTest:
140
152
  # 9. 创建新文件验证写入功能正常
141
153
  print("Step 9: Testing file write after connect...")
142
154
  new_file_path = "/tmp/new_file_after_connect.txt"
143
- await connected_sandbox.files.write(new_file_path, "New file created after connect")
155
+ await connected_sandbox.files.write(
156
+ new_file_path, "New file created after connect"
157
+ )
144
158
  exists = await connected_sandbox.files.exists(new_file_path)
145
159
  assert exists
146
- new_content = await connected_sandbox.files.read(new_file_path, format="text")
160
+ new_content = await connected_sandbox.files.read(
161
+ new_file_path, format="text"
162
+ )
147
163
  assert "New file created after connect" in new_content
148
164
  print("✅ Verified file write works after connect")
149
165
 
150
- self.log_test_result("Connect and Pause with Files", True, "All verifications passed")
166
+ self.log_test_result(
167
+ "Connect and Pause with Files", True, "All verifications passed"
168
+ )
151
169
  return True
152
170
 
153
171
  except Exception as e:
154
172
  self.log_test_result("Connect and Pause with Files", False, str(e))
155
173
  print(f"Test failed with error: {e}")
156
174
  import traceback
175
+
157
176
  traceback.print_exc()
158
177
  return False
159
178
 
@@ -217,13 +236,18 @@ class ConnectPauseAsyncTest:
217
236
  # 清理
218
237
  await sandbox.kill()
219
238
 
220
- self.log_test_result("Multiple Connect and Pause Operations", True, "All verifications passed")
239
+ self.log_test_result(
240
+ "Multiple Connect and Pause Operations",
241
+ True,
242
+ "All verifications passed",
243
+ )
221
244
  return True
222
245
 
223
246
  except Exception as e:
224
247
  self.log_test_result("Multiple Connect and Pause Operations", False, str(e))
225
248
  print(f"Test failed with error: {e}")
226
249
  import traceback
250
+
227
251
  traceback.print_exc()
228
252
  return False
229
253
 
@@ -274,4 +298,3 @@ async def main():
274
298
 
275
299
  if __name__ == "__main__":
276
300
  asyncio.run(main())
277
-
@@ -76,7 +76,9 @@ class ConnectPauseSyncTest:
76
76
  # 4. 创建目录和文件
77
77
  print("Step 4: Creating directory and nested files...")
78
78
  self.sandbox.files.make_dir("/tmp/test_dir")
79
- self.sandbox.files.write("/tmp/test_dir/nested_file.txt", "Nested file content")
79
+ self.sandbox.files.write(
80
+ "/tmp/test_dir/nested_file.txt", "Nested file content"
81
+ )
80
82
  assert self.sandbox.files.exists("/tmp/test_dir")
81
83
  assert self.sandbox.files.exists("/tmp/test_dir/nested_file.txt")
82
84
  print("Created directory and nested file")
@@ -103,24 +105,40 @@ class ConnectPauseSyncTest:
103
105
  print("Step 7: Verifying file operations after connect...")
104
106
 
105
107
  # 校验应该存在的文件
106
- assert connected_sandbox.files.exists("/tmp/test_file1.txt"), "test_file1.txt should exist"
107
- file1_content = connected_sandbox.files.read("/tmp/test_file1.txt", format="text")
108
+ assert connected_sandbox.files.exists(
109
+ "/tmp/test_file1.txt"
110
+ ), "test_file1.txt should exist"
111
+ file1_content = connected_sandbox.files.read(
112
+ "/tmp/test_file1.txt", format="text"
113
+ )
108
114
  assert "Content of test file 1" in file1_content
109
115
  print("✅ Verified test_file1.txt exists and content is correct")
110
116
 
111
- assert connected_sandbox.files.exists("/tmp/test_file3.bin"), "test_file3.bin should exist"
112
- file3_content = connected_sandbox.files.read("/tmp/test_file3.bin", format="bytes")
117
+ assert connected_sandbox.files.exists(
118
+ "/tmp/test_file3.bin"
119
+ ), "test_file3.bin should exist"
120
+ file3_content = connected_sandbox.files.read(
121
+ "/tmp/test_file3.bin", format="bytes"
122
+ )
113
123
  assert bytes(file3_content) == b"Binary content for test file 3"
114
124
  print("✅ Verified test_file3.bin exists and content is correct")
115
125
 
116
126
  # 校验应该不存在的文件(被删除的)
117
- assert not connected_sandbox.files.exists("/tmp/test_file2.txt"), "test_file2.txt should not exist"
127
+ assert not connected_sandbox.files.exists(
128
+ "/tmp/test_file2.txt"
129
+ ), "test_file2.txt should not exist"
118
130
  print("✅ Verified test_file2.txt was deleted correctly")
119
131
 
120
132
  # 校验目录和嵌套文件
121
- assert connected_sandbox.files.exists("/tmp/test_dir"), "test_dir should exist"
122
- assert connected_sandbox.files.exists("/tmp/test_dir/nested_file.txt"), "nested_file.txt should exist"
123
- nested_content = connected_sandbox.files.read("/tmp/test_dir/nested_file.txt", format="text")
133
+ assert connected_sandbox.files.exists(
134
+ "/tmp/test_dir"
135
+ ), "test_dir should exist"
136
+ assert connected_sandbox.files.exists(
137
+ "/tmp/test_dir/nested_file.txt"
138
+ ), "nested_file.txt should exist"
139
+ nested_content = connected_sandbox.files.read(
140
+ "/tmp/test_dir/nested_file.txt", format="text"
141
+ )
124
142
  assert "Nested file content" in nested_content
125
143
  print("✅ Verified directory and nested file exist and content is correct")
126
144
 
@@ -134,19 +152,24 @@ class ConnectPauseSyncTest:
134
152
  # 9. 创建新文件验证写入功能正常
135
153
  print("Step 9: Testing file write after connect...")
136
154
  new_file_path = "/tmp/new_file_after_connect.txt"
137
- connected_sandbox.files.write(new_file_path, "New file created after connect")
155
+ connected_sandbox.files.write(
156
+ new_file_path, "New file created after connect"
157
+ )
138
158
  assert connected_sandbox.files.exists(new_file_path)
139
159
  new_content = connected_sandbox.files.read(new_file_path, format="text")
140
160
  assert "New file created after connect" in new_content
141
161
  print("✅ Verified file write works after connect")
142
162
 
143
- self.log_test_result("Connect and Pause with Files", True, "All verifications passed")
163
+ self.log_test_result(
164
+ "Connect and Pause with Files", True, "All verifications passed"
165
+ )
144
166
  return True
145
167
 
146
168
  except Exception as e:
147
169
  self.log_test_result("Connect and Pause with Files", False, str(e))
148
170
  print(f"Test failed with error: {e}")
149
171
  import traceback
172
+
150
173
  traceback.print_exc()
151
174
  return False
152
175
 
@@ -198,22 +221,33 @@ class ConnectPauseSyncTest:
198
221
  time.sleep(2)
199
222
 
200
223
  # 9. 验证第二次操作的结果
201
- assert not sandbox.files.exists("/tmp/multi_test1.txt"), "multi_test1.txt should be deleted"
202
- assert sandbox.files.exists("/tmp/multi_test2.txt"), "multi_test2.txt should exist"
203
- assert sandbox.files.exists("/tmp/multi_test3.txt"), "multi_test3.txt should exist"
224
+ assert not sandbox.files.exists(
225
+ "/tmp/multi_test1.txt"
226
+ ), "multi_test1.txt should be deleted"
227
+ assert sandbox.files.exists(
228
+ "/tmp/multi_test2.txt"
229
+ ), "multi_test2.txt should exist"
230
+ assert sandbox.files.exists(
231
+ "/tmp/multi_test3.txt"
232
+ ), "multi_test3.txt should exist"
204
233
  content = sandbox.files.read("/tmp/multi_test3.txt", format="text")
205
234
  assert "Second batch" in content
206
235
 
207
236
  # 清理
208
237
  sandbox.kill()
209
238
 
210
- self.log_test_result("Multiple Connect and Pause Operations", True, "All verifications passed")
239
+ self.log_test_result(
240
+ "Multiple Connect and Pause Operations",
241
+ True,
242
+ "All verifications passed",
243
+ )
211
244
  return True
212
245
 
213
246
  except Exception as e:
214
247
  self.log_test_result("Multiple Connect and Pause Operations", False, str(e))
215
248
  print(f"Test failed with error: {e}")
216
249
  import traceback
250
+
217
251
  traceback.print_exc()
218
252
  return False
219
253
 
@@ -264,4 +298,3 @@ def main():
264
298
 
265
299
  if __name__ == "__main__":
266
300
  main()
267
-
@@ -18,7 +18,9 @@ class CsxDesktopValidator:
18
18
  self.success_count = 0
19
19
  self.fail_count = 0
20
20
 
21
- def log_test_result(self, name: str, success: bool, error: Optional[Exception] = None) -> None:
21
+ def log_test_result(
22
+ self, name: str, success: bool, error: Optional[Exception] = None
23
+ ) -> None:
22
24
  if success:
23
25
  self.success_count += 1
24
26
  print(f"✅ {name}")
@@ -126,5 +128,3 @@ if __name__ == "__main__":
126
128
  finally:
127
129
  validator.cleanup()
128
130
  validator.print_summary()
129
-
130
-
@@ -17,7 +17,7 @@ def main():
17
17
  print("=" * 60)
18
18
  print("开始测试:基于desktop创建sandbox并执行test_sf.py")
19
19
  print("=" * 60)
20
-
20
+
21
21
  # 1. 基于desktop创建sandbox
22
22
  print("\n[步骤 1] 正在创建desktop sandbox...")
23
23
  sandbox = Sandbox.create(
@@ -25,24 +25,24 @@ def main():
25
25
  timeout=3600, # 1小时超时
26
26
  )
27
27
  print(f"✓ Sandbox创建成功,ID: {sandbox.sandbox_id}")
28
-
28
+
29
29
  # 2. 获取network_proxy
30
30
  print("\n[步骤 2] 获取network_proxy...")
31
31
  network_proxy = sandbox.network_proxy()
32
32
  print(f"✓ Network Proxy: {network_proxy}")
33
-
33
+
34
34
  # 3. 获取VNC URL(不启动,直接获取)
35
35
  print("\n[步骤 3] 获取VNC URL...")
36
36
  vnc_url = sandbox.stream.get_url(auto_connect=True)
37
37
  print(f"✓ VNC URL: {vnc_url}")
38
-
38
+
39
39
  # 4. 读取test_sf.py并修改username和password
40
40
  print("\n[步骤 4] 读取并修改test_sf.py...")
41
41
  test_sf_path = os.path.join(os.path.dirname(__file__), "test_sf.py")
42
-
43
- with open(test_sf_path, 'r', encoding='utf-8') as f:
42
+
43
+ with open(test_sf_path, "r", encoding="utf-8") as f:
44
44
  test_sf_content = f.read()
45
-
45
+
46
46
  # 从network_proxy中提取username和password
47
47
  if network_proxy and isinstance(network_proxy, dict):
48
48
  # network_proxy结构: {'proxy_configs': {'username': '...', 'password': '...', ...}, ...}
@@ -54,7 +54,7 @@ def main():
54
54
  # 兼容旧格式:直接在network_proxy中
55
55
  proxy_username = network_proxy.get("username", "")
56
56
  proxy_password = network_proxy.get("password", "")
57
-
57
+
58
58
  if not proxy_username or not proxy_password:
59
59
  print("⚠ 警告: network_proxy中缺少username或password字段")
60
60
  print(f" network_proxy内容: {network_proxy}")
@@ -63,36 +63,32 @@ def main():
63
63
  # 匹配proxy字典中的username和password(处理可能的引号差异)
64
64
  pattern_username = r'"username"\s*:\s*"[^"]*"'
65
65
  pattern_password = r'"password"\s*:\s*"[^"]*"'
66
-
66
+
67
67
  test_sf_content = re.sub(
68
- pattern_username,
69
- f'"username": "{proxy_username}"',
70
- test_sf_content
68
+ pattern_username, f'"username": "{proxy_username}"', test_sf_content
71
69
  )
72
70
  test_sf_content = re.sub(
73
- pattern_password,
74
- f'"password": "{proxy_password}"',
75
- test_sf_content
71
+ pattern_password, f'"password": "{proxy_password}"', test_sf_content
76
72
  )
77
-
73
+
78
74
  print(f"✓ 已更新username: {proxy_username}")
79
75
  print(f"✓ 已更新password: {proxy_password[:20]}...")
80
76
  else:
81
77
  print("⚠ 警告: network_proxy为空或格式不正确,跳过修改")
82
78
  print(f" network_proxy类型: {type(network_proxy)}, 值: {network_proxy}")
83
-
79
+
84
80
  # 5. 上传test_sf.py到sandbox的/目录
85
81
  print("\n[步骤 5] 上传test_sf.py到sandbox的/目录...")
86
- result = sandbox.files.write("/test_sf.py", test_sf_content.encode('utf-8'))
82
+ result = sandbox.files.write("/test_sf.py", test_sf_content.encode("utf-8"))
87
83
  print(f"✓ 文件上传成功: {result.path}")
88
-
84
+
89
85
  # 6. 在sandbox中执行命令
90
86
  print("\n[步骤 6] 在sandbox中执行: source /venv/bin/activate && python /test_sf.py")
91
87
  try:
92
88
  # 使用bash -c确保source命令和环境变量正确加载
93
89
  result = sandbox.commands.run(
94
90
  'bash -c "source /venv/bin/activate && python /test_sf.py"',
95
- timeout=600 # 10分钟超时
91
+ timeout=600, # 10分钟超时
96
92
  )
97
93
  print(f"✓ 命令执行完成")
98
94
  print(f"退出码: {result.exit_code}")
@@ -102,11 +98,11 @@ def main():
102
98
  except Exception as e:
103
99
  print(f"✗ 命令执行失败: {e}")
104
100
  raise
105
-
101
+
106
102
  print("\n" + "=" * 60)
107
103
  print("测试完成!")
108
104
  print("=" * 60)
109
-
105
+
110
106
  # 清理(可选,注释掉以保留sandbox)
111
107
  # sandbox.kill()
112
108
  # print("Sandbox已清理")
@@ -114,4 +110,3 @@ def main():
114
110
 
115
111
  if __name__ == "__main__":
116
112
  main()
117
-
@@ -6,17 +6,13 @@ print("正在准备文件内容...")
6
6
  results_data = {
7
7
  "experiment_id": "exp_001",
8
8
  "status": "completed",
9
- "metrics": {
10
- "accuracy": 0.952,
11
- "precision": 0.94,
12
- "recall": 0.96
13
- },
9
+ "metrics": {"accuracy": 0.952, "precision": 0.94, "recall": 0.96},
14
10
  "timestamp": "2024-01-01T12:00:00Z",
15
11
  "details": [
16
12
  {"epoch": 1, "loss": 0.45},
17
13
  {"epoch": 2, "loss": 0.32},
18
- {"epoch": 3, "loss": 0.18}
19
- ]
14
+ {"epoch": 3, "loss": 0.18},
15
+ ],
20
16
  }
21
17
 
22
18
  # 转换为 JSON 字符串
@@ -34,16 +30,12 @@ print(f"✅ 文件已写入沙箱: {remote_path}")
34
30
  # 3. 获取预签名下载 URL
35
31
  print("\n正在生成下载链接...")
36
32
  download_url = sandbox.download_url(
37
- path=remote_path,
38
- use_signature_expiration=180 # 180秒有效期
33
+ path=remote_path, use_signature_expiration=180 # 180秒有效期
39
34
  )
40
35
 
41
36
  print(f"\n📥 下载 URL: {download_url}")
42
37
  print(f"⏰ 链接将在 3 分钟后过期")
43
38
 
44
- upload_url = sandbox.upload_url(
45
- path="/home/user",
46
- use_signature_expiration=360
47
- )
39
+ upload_url = sandbox.upload_url(path="/home/user", use_signature_expiration=360)
48
40
  print(f"\n📥 上传 URL: {upload_url}")
49
- print(f"⏰ 链接将在 6 分钟后过期")
41
+ print(f"⏰ 链接将在 6 分钟后过期")