render 1.0.1__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 (799) hide show
  1. render/__init__.py +98 -0
  2. render/client/__init__.py +119 -0
  3. render/client/client.py +110 -0
  4. render/client/errors.py +39 -0
  5. render/client/sse.py +90 -0
  6. render/client/sse_sync.py +20 -0
  7. render/client/tests/__init__.py +0 -0
  8. render/client/tests/test_client.py +379 -0
  9. render/client/tests/test_method_parity.py +118 -0
  10. render/client/tests/test_render.py +52 -0
  11. render/client/tests/test_sse.py +67 -0
  12. render/client/tests/test_util.py +303 -0
  13. render/client/tests/test_util_sync.py +73 -0
  14. render/client/tests/test_workflows_sync.py +313 -0
  15. render/client/types.py +52 -0
  16. render/client/util.py +285 -0
  17. render/client/util_sync.py +83 -0
  18. render/client/workflows.py +363 -0
  19. render/client/workflows_sync.py +298 -0
  20. render/experimental/__init__.py +37 -0
  21. render/experimental/experimental.py +93 -0
  22. render/experimental/experimental_sync.py +78 -0
  23. render/experimental/key_value/__init__.py +33 -0
  24. render/experimental/key_value/api.py +243 -0
  25. render/experimental/key_value/compare.py +83 -0
  26. render/experimental/key_value/provider.py +285 -0
  27. render/experimental/key_value/tests/__init__.py +0 -0
  28. render/experimental/key_value/tests/test_api.py +371 -0
  29. render/experimental/key_value/tests/test_compare.py +136 -0
  30. render/experimental/key_value/tests/test_provider.py +1016 -0
  31. render/experimental/key_value/types.py +130 -0
  32. render/experimental/key_value/utils.py +11 -0
  33. render/experimental/object/__init__.py +38 -0
  34. render/experimental/object/api.py +250 -0
  35. render/experimental/object/api_sync.py +250 -0
  36. render/experimental/object/client.py +545 -0
  37. render/experimental/object/client_sync.py +547 -0
  38. render/experimental/object/e2e_helpers.py +78 -0
  39. render/experimental/object/tests/__init__.py +0 -0
  40. render/experimental/object/tests/test_client.py +228 -0
  41. render/experimental/object/tests/test_e2e.py +125 -0
  42. render/experimental/object/types.py +87 -0
  43. render/experimental/sandbox/__init__.py +31 -0
  44. render/experimental/sandbox/_tar.py +278 -0
  45. render/experimental/sandbox/api.py +518 -0
  46. render/experimental/sandbox/api_sync.py +514 -0
  47. render/experimental/sandbox/client.py +168 -0
  48. render/experimental/sandbox/client_sync.py +170 -0
  49. render/experimental/sandbox/errors.py +37 -0
  50. render/experimental/sandbox/files.py +378 -0
  51. render/experimental/sandbox/tests/__init__.py +0 -0
  52. render/experimental/sandbox/tests/test_client.py +802 -0
  53. render/experimental/sandbox/tests/test_download.py +728 -0
  54. render/experimental/sandbox/tests/test_e2e.py +252 -0
  55. render/experimental/sandbox/tests/test_tar.py +153 -0
  56. render/experimental/sandbox/tests/test_types.py +57 -0
  57. render/experimental/sandbox/types.py +46 -0
  58. render/public_api/__init__.py +8 -0
  59. render/public_api/api/__init__.py +1 -0
  60. render/public_api/api/artifact_sources/__init__.py +1 -0
  61. render/public_api/api/artifact_sources/add_or_update_artifact_source_secret_file.py +252 -0
  62. render/public_api/api/artifact_sources/create_artifact_source.py +243 -0
  63. render/public_api/api/artifact_sources/delete_artifact_source.py +188 -0
  64. render/public_api/api/artifact_sources/delete_artifact_source_env_var.py +223 -0
  65. render/public_api/api/artifact_sources/delete_artifact_source_secret_file.py +223 -0
  66. render/public_api/api/artifact_sources/get_artifact_source.py +185 -0
  67. render/public_api/api/artifact_sources/get_env_vars_for_artifact_source.py +241 -0
  68. render/public_api/api/artifact_sources/link_artifact_source_to_env_group.py +215 -0
  69. render/public_api/api/artifact_sources/list_artifact_sources.py +338 -0
  70. render/public_api/api/artifact_sources/list_artifacts_in_artifact_source.py +241 -0
  71. render/public_api/api/artifact_sources/list_secret_files_for_artifact_source.py +241 -0
  72. render/public_api/api/artifact_sources/retrieve_artifact_source_env_var.py +225 -0
  73. render/public_api/api/artifact_sources/retrieve_artifact_source_secret_file.py +225 -0
  74. render/public_api/api/artifact_sources/unlink_artifact_source_from_env_group.py +209 -0
  75. render/public_api/api/artifact_sources/update_artifact_source.py +244 -0
  76. render/public_api/api/artifact_sources/update_artifact_source_env_var.py +257 -0
  77. render/public_api/api/artifact_sources/update_env_vars_for_artifact_source.py +245 -0
  78. render/public_api/api/artifact_sources/update_secret_files_for_artifact_source.py +255 -0
  79. render/public_api/api/audit_logs/__init__.py +1 -0
  80. render/public_api/api/audit_logs/list_organization_audit_logs.py +303 -0
  81. render/public_api/api/audit_logs/list_owner_audit_logs.py +303 -0
  82. render/public_api/api/blueprints/__init__.py +1 -0
  83. render/public_api/api/blueprints/disconnect_blueprint.py +210 -0
  84. render/public_api/api/blueprints/list_blueprint_syncs.py +241 -0
  85. render/public_api/api/blueprints/list_blueprints.py +251 -0
  86. render/public_api/api/blueprints/retrieve_blueprint.py +200 -0
  87. render/public_api/api/blueprints/update_blueprint.py +222 -0
  88. render/public_api/api/blueprints/validate_blueprint.py +217 -0
  89. render/public_api/api/custom_domains/__init__.py +1 -0
  90. render/public_api/api/custom_domains/create_custom_domain.py +242 -0
  91. render/public_api/api/custom_domains/delete_custom_domain.py +216 -0
  92. render/public_api/api/custom_domains/list_custom_domains.py +346 -0
  93. render/public_api/api/custom_domains/refresh_custom_domain.py +216 -0
  94. render/public_api/api/custom_domains/retrieve_custom_domain.py +218 -0
  95. render/public_api/api/dedicated_i_ps/__init__.py +1 -0
  96. render/public_api/api/dedicated_i_ps/create_dedicated_ip.py +234 -0
  97. render/public_api/api/dedicated_i_ps/delete_dedicated_ip.py +198 -0
  98. render/public_api/api/dedicated_i_ps/list_dedicated_ips.py +223 -0
  99. render/public_api/api/dedicated_i_ps/retrieve_dedicated_ip.py +200 -0
  100. render/public_api/api/dedicated_i_ps/update_dedicated_ip.py +244 -0
  101. render/public_api/api/deploys/__init__.py +1 -0
  102. render/public_api/api/deploys/cancel_deploy.py +216 -0
  103. render/public_api/api/deploys/create_deploy.py +231 -0
  104. render/public_api/api/deploys/list_deploys.py +377 -0
  105. render/public_api/api/deploys/retrieve_deploy.py +213 -0
  106. render/public_api/api/deploys/rollback_deploy.py +241 -0
  107. render/public_api/api/disks/__init__.py +1 -0
  108. render/public_api/api/disks/add_disk.py +222 -0
  109. render/public_api/api/disks/delete_disk.py +210 -0
  110. render/public_api/api/disks/list_disks.py +381 -0
  111. render/public_api/api/disks/list_snapshots.py +214 -0
  112. render/public_api/api/disks/restore_snapshot.py +255 -0
  113. render/public_api/api/disks/retrieve_disk.py +200 -0
  114. render/public_api/api/disks/update_disk.py +243 -0
  115. render/public_api/api/environment_groups/__init__.py +1 -0
  116. render/public_api/api/environment_groups/create_env_group.py +199 -0
  117. render/public_api/api/environment_groups/delete_env_group.py +192 -0
  118. render/public_api/api/environment_groups/delete_env_group_env_var.py +201 -0
  119. render/public_api/api/environment_groups/delete_env_group_secret_file.py +201 -0
  120. render/public_api/api/environment_groups/link_service_to_env_group.py +211 -0
  121. render/public_api/api/environment_groups/list_env_groups.py +352 -0
  122. render/public_api/api/environment_groups/retrieve_env_group.py +190 -0
  123. render/public_api/api/environment_groups/retrieve_env_group_env_var.py +203 -0
  124. render/public_api/api/environment_groups/retrieve_env_group_secret_file.py +203 -0
  125. render/public_api/api/environment_groups/unlink_service_from_env_group.py +209 -0
  126. render/public_api/api/environment_groups/update_env_group.py +212 -0
  127. render/public_api/api/environment_groups/update_env_group_env_var.py +230 -0
  128. render/public_api/api/environment_groups/update_env_group_secret_file.py +225 -0
  129. render/public_api/api/events/__init__.py +1 -0
  130. render/public_api/api/events/retrieve_event.py +205 -0
  131. render/public_api/api/key_value/__init__.py +1 -0
  132. render/public_api/api/key_value/create_key_value.py +199 -0
  133. render/public_api/api/key_value/delete_key_value.py +188 -0
  134. render/public_api/api/key_value/list_key_value.py +380 -0
  135. render/public_api/api/key_value/resume_key_value.py +203 -0
  136. render/public_api/api/key_value/retrieve_key_value.py +190 -0
  137. render/public_api/api/key_value/retrieve_key_value_connection_info.py +194 -0
  138. render/public_api/api/key_value/suspend_key_value.py +203 -0
  139. render/public_api/api/key_value/update_key_value.py +221 -0
  140. render/public_api/api/logs/__init__.py +1 -0
  141. render/public_api/api/logs/delete_owner_log_stream.py +188 -0
  142. render/public_api/api/logs/delete_resource_log_stream.py +192 -0
  143. render/public_api/api/logs/get_owner_log_stream.py +205 -0
  144. render/public_api/api/logs/get_resource_log_stream.py +209 -0
  145. render/public_api/api/logs/list_logs.py +535 -0
  146. render/public_api/api/logs/list_logs_values.py +527 -0
  147. render/public_api/api/logs/list_resource_log_streams.py +317 -0
  148. render/public_api/api/logs/subscribe_logs.py +527 -0
  149. render/public_api/api/logs/update_owner_log_stream.py +231 -0
  150. render/public_api/api/logs/update_resource_log_stream.py +231 -0
  151. render/public_api/api/maintenance/__init__.py +1 -0
  152. render/public_api/api/maintenance/list_maintenance.py +249 -0
  153. render/public_api/api/maintenance/retrieve_maintenance.py +190 -0
  154. render/public_api/api/maintenance/trigger_maintenance.py +212 -0
  155. render/public_api/api/maintenance/update_maintenance.py +222 -0
  156. render/public_api/api/metrics/__init__.py +1 -0
  157. render/public_api/api/metrics/delete_owner_metrics_stream.py +172 -0
  158. render/public_api/api/metrics/get_active_connections.py +237 -0
  159. render/public_api/api/metrics/get_bandwidth.py +237 -0
  160. render/public_api/api/metrics/get_bandwidth_sources.py +250 -0
  161. render/public_api/api/metrics/get_cpu.py +287 -0
  162. render/public_api/api/metrics/get_cpu_limit.py +267 -0
  163. render/public_api/api/metrics/get_cpu_target.py +267 -0
  164. render/public_api/api/metrics/get_disk_capacity.py +252 -0
  165. render/public_api/api/metrics/get_disk_usage.py +252 -0
  166. render/public_api/api/metrics/get_http_latency.py +297 -0
  167. render/public_api/api/metrics/get_http_requests.py +302 -0
  168. render/public_api/api/metrics/get_instance_count.py +252 -0
  169. render/public_api/api/metrics/get_memory.py +267 -0
  170. render/public_api/api/metrics/get_memory_limit.py +267 -0
  171. render/public_api/api/metrics/get_memory_target.py +267 -0
  172. render/public_api/api/metrics/get_owner_metrics_stream.py +174 -0
  173. render/public_api/api/metrics/get_replication_lag.py +237 -0
  174. render/public_api/api/metrics/get_task_runs_completed.py +281 -0
  175. render/public_api/api/metrics/get_task_runs_queued.py +237 -0
  176. render/public_api/api/metrics/list_application_filter_values.py +254 -0
  177. render/public_api/api/metrics/list_http_filter_values.py +282 -0
  178. render/public_api/api/metrics/list_path_filter_values.py +289 -0
  179. render/public_api/api/metrics/upsert_owner_metrics_stream.py +192 -0
  180. render/public_api/api/notification_settings/__init__.py +1 -0
  181. render/public_api/api/notification_settings/list_notification_overrides.py +255 -0
  182. render/public_api/api/notification_settings/patch_owner_notification_settings.py +207 -0
  183. render/public_api/api/notification_settings/patch_service_notification_overrides.py +207 -0
  184. render/public_api/api/notification_settings/retrieve_owner_notification_settings.py +193 -0
  185. render/public_api/api/notification_settings/retrieve_service_notification_overrides.py +193 -0
  186. render/public_api/api/object_storage/__init__.py +1 -0
  187. render/public_api/api/object_storage/delete_object.py +215 -0
  188. render/public_api/api/object_storage/get_object.py +221 -0
  189. render/public_api/api/object_storage/list_objects.py +240 -0
  190. render/public_api/api/object_storage/put_object.py +248 -0
  191. render/public_api/api/one_off_jobs/__init__.py +1 -0
  192. render/public_api/api/one_off_jobs/cancel_job.py +203 -0
  193. render/public_api/api/one_off_jobs/list_job.py +367 -0
  194. render/public_api/api/one_off_jobs/post_job.py +216 -0
  195. render/public_api/api/one_off_jobs/retrieve_job.py +203 -0
  196. render/public_api/api/postgres/__init__.py +1 -0
  197. render/public_api/api/postgres/create_postgres.py +199 -0
  198. render/public_api/api/postgres/create_postgres_export.py +207 -0
  199. render/public_api/api/postgres/create_postgres_user.py +229 -0
  200. render/public_api/api/postgres/delete_postgres.py +192 -0
  201. render/public_api/api/postgres/delete_postgres_user.py +201 -0
  202. render/public_api/api/postgres/failover_postgres.py +207 -0
  203. render/public_api/api/postgres/list_available_postgres_parameter_overrides.py +190 -0
  204. render/public_api/api/postgres/list_postgres.py +418 -0
  205. render/public_api/api/postgres/list_postgres_export.py +199 -0
  206. render/public_api/api/postgres/list_postgres_parameter_overrides.py +190 -0
  207. render/public_api/api/postgres/list_postgres_processes.py +190 -0
  208. render/public_api/api/postgres/list_postgres_sizes.py +190 -0
  209. render/public_api/api/postgres/list_postgres_table_scans.py +190 -0
  210. render/public_api/api/postgres/list_postgres_top_queries.py +194 -0
  211. render/public_api/api/postgres/list_postgres_users.py +195 -0
  212. render/public_api/api/postgres/promote_postgres.py +203 -0
  213. render/public_api/api/postgres/recover_postgres.py +231 -0
  214. render/public_api/api/postgres/restart_postgres.py +203 -0
  215. render/public_api/api/postgres/resume_postgres.py +203 -0
  216. render/public_api/api/postgres/retrieve_postgres.py +190 -0
  217. render/public_api/api/postgres/retrieve_postgres_connection_info.py +194 -0
  218. render/public_api/api/postgres/retrieve_postgres_recovery_info.py +194 -0
  219. render/public_api/api/postgres/setup_postgres_replication.py +231 -0
  220. render/public_api/api/postgres/suspend_postgres.py +203 -0
  221. render/public_api/api/postgres/update_postgres.py +217 -0
  222. render/public_api/api/postgres/update_postgres_parameter_overrides.py +217 -0
  223. render/public_api/api/projects_environments/__init__.py +1 -0
  224. render/public_api/api/projects_environments/add_resources_to_environment.py +212 -0
  225. render/public_api/api/projects_environments/create_environment.py +199 -0
  226. render/public_api/api/projects_environments/create_project.py +199 -0
  227. render/public_api/api/projects_environments/delete_environment.py +216 -0
  228. render/public_api/api/projects_environments/delete_project.py +216 -0
  229. render/public_api/api/projects_environments/list_environments.py +369 -0
  230. render/public_api/api/projects_environments/list_projects.py +329 -0
  231. render/public_api/api/projects_environments/remove_resources_from_environment.py +211 -0
  232. render/public_api/api/projects_environments/retrieve_environment.py +190 -0
  233. render/public_api/api/projects_environments/retrieve_project.py +190 -0
  234. render/public_api/api/projects_environments/update_environment.py +212 -0
  235. render/public_api/api/projects_environments/update_project.py +224 -0
  236. render/public_api/api/redis_deprecated/__init__.py +1 -0
  237. render/public_api/api/redis_deprecated/create_redis.py +199 -0
  238. render/public_api/api/redis_deprecated/delete_redis.py +188 -0
  239. render/public_api/api/redis_deprecated/list_redis.py +384 -0
  240. render/public_api/api/redis_deprecated/resume_redis.py +203 -0
  241. render/public_api/api/redis_deprecated/retrieve_redis.py +190 -0
  242. render/public_api/api/redis_deprecated/retrieve_redis_connection_info.py +194 -0
  243. render/public_api/api/redis_deprecated/suspend_redis.py +203 -0
  244. render/public_api/api/redis_deprecated/update_redis.py +217 -0
  245. render/public_api/api/registry_credentials/__init__.py +1 -0
  246. render/public_api/api/registry_credentials/create_registry_credential.py +209 -0
  247. render/public_api/api/registry_credentials/delete_registry_credential.py +198 -0
  248. render/public_api/api/registry_credentials/list_registry_credentials.py +370 -0
  249. render/public_api/api/registry_credentials/retrieve_registry_credential.py +200 -0
  250. render/public_api/api/registry_credentials/update_registry_credential.py +241 -0
  251. render/public_api/api/sandboxes/__init__.py +1 -0
  252. render/public_api/api/sandboxes/connect_sandbox_files.py +281 -0
  253. render/public_api/api/sandboxes/connect_sandbox_run.py +271 -0
  254. render/public_api/api/sandboxes/create_sandbox.py +199 -0
  255. render/public_api/api/sandboxes/list_sandbox_files.py +244 -0
  256. render/public_api/api/sandboxes/list_sandbox_groups.py +216 -0
  257. render/public_api/api/sandboxes/list_sandboxes.py +269 -0
  258. render/public_api/api/sandboxes/retrieve_sandbox.py +211 -0
  259. render/public_api/api/sandboxes/retrieve_sandbox_execution.py +224 -0
  260. render/public_api/api/sandboxes/stream_sandbox_logs.py +274 -0
  261. render/public_api/api/sandboxes/terminate_sandbox.py +217 -0
  262. render/public_api/api/sandboxes/update_sandbox_exec.py +258 -0
  263. render/public_api/api/services/__init__.py +1 -0
  264. render/public_api/api/services/add_or_update_secret_file.py +252 -0
  265. render/public_api/api/services/autoscale_service.py +230 -0
  266. render/public_api/api/services/create_ephemeral_shell.py +217 -0
  267. render/public_api/api/services/create_service.py +204 -0
  268. render/public_api/api/services/delete_autoscaling_config.py +198 -0
  269. render/public_api/api/services/delete_env_var.py +223 -0
  270. render/public_api/api/services/delete_secret_file.py +223 -0
  271. render/public_api/api/services/delete_service.py +198 -0
  272. render/public_api/api/services/get_env_vars_for_service.py +241 -0
  273. render/public_api/api/services/list_events.py +288 -0
  274. render/public_api/api/services/list_instances.py +190 -0
  275. render/public_api/api/services/list_secret_files_for_service.py +241 -0
  276. render/public_api/api/services/list_services.py +439 -0
  277. render/public_api/api/services/preview_service.py +227 -0
  278. render/public_api/api/services/purge_cache.py +203 -0
  279. render/public_api/api/services/restart_service.py +211 -0
  280. render/public_api/api/services/resume_service.py +203 -0
  281. render/public_api/api/services/retrieve_env_var.py +225 -0
  282. render/public_api/api/services/retrieve_secret_file.py +225 -0
  283. render/public_api/api/services/retrieve_service.py +190 -0
  284. render/public_api/api/services/retrieve_service_outbound_ips.py +207 -0
  285. render/public_api/api/services/scale_service.py +237 -0
  286. render/public_api/api/services/suspend_service.py +203 -0
  287. render/public_api/api/services/update_env_var.py +257 -0
  288. render/public_api/api/services/update_env_vars_for_service.py +241 -0
  289. render/public_api/api/services/update_secret_files_for_service.py +255 -0
  290. render/public_api/api/services/update_service.py +227 -0
  291. render/public_api/api/services_cron_jobs/__init__.py +1 -0
  292. render/public_api/api/services_cron_jobs/cancel_cron_job_run.py +183 -0
  293. render/public_api/api/services_cron_jobs/run_cron_job.py +185 -0
  294. render/public_api/api/services_headers/__init__.py +1 -0
  295. render/public_api/api/services_headers/add_headers.py +222 -0
  296. render/public_api/api/services_headers/delete_header.py +211 -0
  297. render/public_api/api/services_headers/list_headers.py +302 -0
  298. render/public_api/api/services_headers/update_headers.py +243 -0
  299. render/public_api/api/services_routes/__init__.py +1 -0
  300. render/public_api/api/services_routes/add_route.py +227 -0
  301. render/public_api/api/services_routes/delete_route.py +211 -0
  302. render/public_api/api/services_routes/list_routes.py +306 -0
  303. render/public_api/api/services_routes/patch_route.py +259 -0
  304. render/public_api/api/services_routes/put_routes.py +259 -0
  305. render/public_api/api/users/__init__.py +1 -0
  306. render/public_api/api/users/get_user.py +161 -0
  307. render/public_api/api/webhooks/__init__.py +1 -0
  308. render/public_api/api/webhooks/create_webhook.py +199 -0
  309. render/public_api/api/webhooks/delete_webhook.py +183 -0
  310. render/public_api/api/webhooks/list_webhook_events.py +268 -0
  311. render/public_api/api/webhooks/list_webhooks.py +237 -0
  312. render/public_api/api/webhooks/retrieve_webhook.py +185 -0
  313. render/public_api/api/webhooks/update_webhook.py +212 -0
  314. render/public_api/api/workflow_tasks_beta/__init__.py +1 -0
  315. render/public_api/api/workflow_tasks_beta/cancel_task_run.py +188 -0
  316. render/public_api/api/workflow_tasks_beta/create_task.py +204 -0
  317. render/public_api/api/workflow_tasks_beta/get_task.py +190 -0
  318. render/public_api/api/workflow_tasks_beta/get_task_run.py +190 -0
  319. render/public_api/api/workflow_tasks_beta/list_task_runs.py +317 -0
  320. render/public_api/api/workflow_tasks_beta/list_tasks.py +298 -0
  321. render/public_api/api/workflow_tasks_beta/stream_task_runs_events.py +230 -0
  322. render/public_api/api/workflows_beta/__init__.py +1 -0
  323. render/public_api/api/workflows_beta/create_workflow.py +199 -0
  324. render/public_api/api/workflows_beta/create_workflow_version.py +197 -0
  325. render/public_api/api/workflows_beta/delete_workflow.py +188 -0
  326. render/public_api/api/workflows_beta/get_workflow.py +190 -0
  327. render/public_api/api/workflows_beta/get_workflow_version.py +190 -0
  328. render/public_api/api/workflows_beta/list_workflow_versions.py +275 -0
  329. render/public_api/api/workflows_beta/list_workflows.py +298 -0
  330. render/public_api/api/workflows_beta/update_workflow.py +212 -0
  331. render/public_api/api/workspaces/__init__.py +1 -0
  332. render/public_api/api/workspaces/list_owners.py +255 -0
  333. render/public_api/api/workspaces/remove_workspace_member.py +206 -0
  334. render/public_api/api/workspaces/retrieve_owner.py +207 -0
  335. render/public_api/api/workspaces/retrieve_owner_members.py +200 -0
  336. render/public_api/api/workspaces/update_workspace_member.py +235 -0
  337. render/public_api/client.py +268 -0
  338. render/public_api/errors.py +16 -0
  339. render/public_api/models/__init__.py +861 -0
  340. render/public_api/models/add_headers_response_201.py +72 -0
  341. render/public_api/models/add_or_update_artifact_source_secret_file_body.py +59 -0
  342. render/public_api/models/add_or_update_secret_file_body.py +59 -0
  343. render/public_api/models/artifact.py +145 -0
  344. render/public_api/models/artifact_fetch_failed.py +67 -0
  345. render/public_api/models/artifact_source.py +162 -0
  346. render/public_api/models/artifact_source_changed.py +70 -0
  347. render/public_api/models/artifact_source_git.py +167 -0
  348. render/public_api/models/artifact_source_git_region.py +12 -0
  349. render/public_api/models/artifact_source_git_runtime.py +14 -0
  350. render/public_api/models/artifact_source_image.py +78 -0
  351. render/public_api/models/artifact_source_patch_git.py +175 -0
  352. render/public_api/models/artifact_source_patch_git_region.py +12 -0
  353. render/public_api/models/artifact_source_patch_git_runtime.py +14 -0
  354. render/public_api/models/artifact_source_patch_image.py +71 -0
  355. render/public_api/models/artifact_source_patch_input.py +101 -0
  356. render/public_api/models/artifact_source_post_input.py +213 -0
  357. render/public_api/models/artifact_source_service_link.py +67 -0
  358. render/public_api/models/artifact_source_with_cursor.py +73 -0
  359. render/public_api/models/audit_log.py +113 -0
  360. render/public_api/models/audit_log_actor.py +80 -0
  361. render/public_api/models/audit_log_actor_type.py +10 -0
  362. render/public_api/models/audit_log_event.py +87 -0
  363. render/public_api/models/audit_log_metadata.py +49 -0
  364. render/public_api/models/audit_log_status.py +9 -0
  365. render/public_api/models/audit_log_with_cursor.py +73 -0
  366. render/public_api/models/auto_deploy.py +9 -0
  367. render/public_api/models/auto_deploy_disabled.py +79 -0
  368. render/public_api/models/auto_deploy_enabled.py +68 -0
  369. render/public_api/models/auto_deploy_trigger.py +10 -0
  370. render/public_api/models/autoscaling_config.py +89 -0
  371. render/public_api/models/autoscaling_config_changed.py +83 -0
  372. render/public_api/models/autoscaling_criteria.py +73 -0
  373. render/public_api/models/autoscaling_criteria_percentage.py +68 -0
  374. render/public_api/models/autoscaling_ended.py +67 -0
  375. render/public_api/models/autoscaling_started.py +105 -0
  376. render/public_api/models/background_worker_details.py +256 -0
  377. render/public_api/models/background_worker_details_patch.py +184 -0
  378. render/public_api/models/background_worker_details_post.py +266 -0
  379. render/public_api/models/blueprint.py +128 -0
  380. render/public_api/models/blueprint_detail.py +150 -0
  381. render/public_api/models/blueprint_patch.py +77 -0
  382. render/public_api/models/blueprint_with_cursor.py +74 -0
  383. render/public_api/models/branch_deleted.py +67 -0
  384. render/public_api/models/build.py +148 -0
  385. render/public_api/models/build_config.py +96 -0
  386. render/public_api/models/build_deploy_end_reason.py +122 -0
  387. render/public_api/models/build_deploy_end_reason_id.py +59 -0
  388. render/public_api/models/build_deploy_trigger.py +150 -0
  389. render/public_api/models/build_ended.py +91 -0
  390. render/public_api/models/build_filter.py +67 -0
  391. render/public_api/models/build_plan.py +9 -0
  392. render/public_api/models/build_runtime.py +14 -0
  393. render/public_api/models/build_started.py +73 -0
  394. render/public_api/models/build_status.py +13 -0
  395. render/public_api/models/cache.py +61 -0
  396. render/public_api/models/cache_profile.py +10 -0
  397. render/public_api/models/cidr_block_and_description.py +67 -0
  398. render/public_api/models/commit_ignored.py +67 -0
  399. render/public_api/models/commit_ref.py +59 -0
  400. render/public_api/models/connect_sandbox_files_operation.py +9 -0
  401. render/public_api/models/connect_sandbox_run_operation.py +9 -0
  402. render/public_api/models/create_custom_domain_body.py +59 -0
  403. render/public_api/models/create_deploy_body.py +130 -0
  404. render/public_api/models/create_deploy_body_clear_cache.py +9 -0
  405. render/public_api/models/create_ephemeral_shell_body.py +69 -0
  406. render/public_api/models/create_ephemeral_shell_response_201.py +59 -0
  407. render/public_api/models/create_registry_credential_body.py +93 -0
  408. render/public_api/models/create_version.py +70 -0
  409. render/public_api/models/credential_create_input.py +59 -0
  410. render/public_api/models/cron_job_details.py +163 -0
  411. render/public_api/models/cron_job_details_patch.py +138 -0
  412. render/public_api/models/cron_job_details_post.py +172 -0
  413. render/public_api/models/cron_job_run.py +123 -0
  414. render/public_api/models/cron_job_run_ended.py +110 -0
  415. render/public_api/models/cron_job_run_started.py +59 -0
  416. render/public_api/models/cron_job_run_status.py +11 -0
  417. render/public_api/models/custom_domain.py +135 -0
  418. render/public_api/models/custom_domain_domain_type.py +9 -0
  419. render/public_api/models/custom_domain_server.py +68 -0
  420. render/public_api/models/custom_domain_verification_status.py +9 -0
  421. render/public_api/models/custom_domain_with_cursor.py +73 -0
  422. render/public_api/models/database_role.py +9 -0
  423. render/public_api/models/database_status.py +18 -0
  424. render/public_api/models/dedicated_ip.py +146 -0
  425. render/public_api/models/dedicated_ip_status.py +14 -0
  426. render/public_api/models/dedicated_ippatch.py +81 -0
  427. render/public_api/models/dedicated_ippost.py +100 -0
  428. render/public_api/models/deploy.py +211 -0
  429. render/public_api/models/deploy_commit.py +86 -0
  430. render/public_api/models/deploy_ended.py +102 -0
  431. render/public_api/models/deploy_image.py +78 -0
  432. render/public_api/models/deploy_mode.py +9 -0
  433. render/public_api/models/deploy_started.py +85 -0
  434. render/public_api/models/deploy_status.py +18 -0
  435. render/public_api/models/deploy_trigger.py +17 -0
  436. render/public_api/models/deploy_with_cursor.py +81 -0
  437. render/public_api/models/disk.py +83 -0
  438. render/public_api/models/disk_created.py +67 -0
  439. render/public_api/models/disk_deleted.py +59 -0
  440. render/public_api/models/disk_details.py +112 -0
  441. render/public_api/models/disk_patch.py +77 -0
  442. render/public_api/models/disk_post.py +83 -0
  443. render/public_api/models/disk_snapshot.py +88 -0
  444. render/public_api/models/disk_updated.py +75 -0
  445. render/public_api/models/disk_with_cursor.py +73 -0
  446. render/public_api/models/docker_details.py +108 -0
  447. render/public_api/models/docker_details_patch.py +86 -0
  448. render/public_api/models/docker_details_post.py +86 -0
  449. render/public_api/models/edge_cache_disabled.py +65 -0
  450. render/public_api/models/edge_cache_enabled.py +65 -0
  451. render/public_api/models/edge_cache_purged.py +65 -0
  452. render/public_api/models/edge_cache_trigger.py +91 -0
  453. render/public_api/models/env_group.py +162 -0
  454. render/public_api/models/env_group_link.py +77 -0
  455. render/public_api/models/env_group_meta.py +126 -0
  456. render/public_api/models/env_group_patch_input.py +59 -0
  457. render/public_api/models/env_group_post_input.py +161 -0
  458. render/public_api/models/env_var.py +67 -0
  459. render/public_api/models/env_var_generate_value.py +59 -0
  460. render/public_api/models/env_var_key_generate_value.py +68 -0
  461. render/public_api/models/env_var_key_value.py +67 -0
  462. render/public_api/models/env_var_value.py +59 -0
  463. render/public_api/models/env_var_with_cursor.py +73 -0
  464. render/public_api/models/environment.py +152 -0
  465. render/public_api/models/environment_patch_input.py +112 -0
  466. render/public_api/models/environment_post_input.py +122 -0
  467. render/public_api/models/environment_resources_post_input.py +59 -0
  468. render/public_api/models/environment_with_cursor.py +74 -0
  469. render/public_api/models/error.py +79 -0
  470. render/public_api/models/error_code.py +10 -0
  471. render/public_api/models/event.py +1122 -0
  472. render/public_api/models/event_status.py +10 -0
  473. render/public_api/models/event_type.py +74 -0
  474. render/public_api/models/execution.py +144 -0
  475. render/public_api/models/execution_operation.py +11 -0
  476. render/public_api/models/execution_type.py +9 -0
  477. render/public_api/models/failure_reason.py +138 -0
  478. render/public_api/models/filter_application_values_collection_item.py +78 -0
  479. render/public_api/models/filter_application_values_collection_item_filter.py +8 -0
  480. render/public_api/models/filter_http_values_collection_item.py +78 -0
  481. render/public_api/models/filter_http_values_collection_item_filter.py +9 -0
  482. render/public_api/models/get_bandwidth_sources_response_200.py +75 -0
  483. render/public_api/models/get_bandwidth_sources_response_200_data_item.py +101 -0
  484. render/public_api/models/get_bandwidth_sources_response_200_data_item_labels.py +78 -0
  485. render/public_api/models/get_bandwidth_sources_response_200_data_item_labels_traffic_source.py +12 -0
  486. render/public_api/models/get_bandwidth_sources_response_200_data_item_values_item.py +68 -0
  487. render/public_api/models/get_cpu_aggregation_method.py +10 -0
  488. render/public_api/models/get_http_requests_aggregate_by.py +9 -0
  489. render/public_api/models/get_object_output.py +71 -0
  490. render/public_api/models/get_task_runs_completed_aggregate_by.py +8 -0
  491. render/public_api/models/get_task_runs_completed_state.py +9 -0
  492. render/public_api/models/header.py +83 -0
  493. render/public_api/models/header_input.py +76 -0
  494. render/public_api/models/header_with_cursor.py +73 -0
  495. render/public_api/models/image.py +80 -0
  496. render/public_api/models/image_pull_failed.py +67 -0
  497. render/public_api/models/initial_deploy_hook_ended.py +59 -0
  498. render/public_api/models/initial_deploy_hook_started.py +59 -0
  499. render/public_api/models/instance_count_changed.py +67 -0
  500. render/public_api/models/instance_type_changed.py +67 -0
  501. render/public_api/models/internal_routing.py +8 -0
  502. render/public_api/models/job.py +144 -0
  503. render/public_api/models/job_run_ended.py +92 -0
  504. render/public_api/models/job_status.py +12 -0
  505. render/public_api/models/job_with_cursor.py +73 -0
  506. render/public_api/models/key_value.py +182 -0
  507. render/public_api/models/key_value_available.py +44 -0
  508. render/public_api/models/key_value_config_restart.py +67 -0
  509. render/public_api/models/key_value_connection_info.py +76 -0
  510. render/public_api/models/key_value_detail.py +192 -0
  511. render/public_api/models/key_value_options.py +79 -0
  512. render/public_api/models/key_value_patch_input.py +138 -0
  513. render/public_api/models/key_value_plan.py +13 -0
  514. render/public_api/models/key_value_post_input.py +166 -0
  515. render/public_api/models/key_value_unhealthy.py +44 -0
  516. render/public_api/models/key_value_with_cursor.py +73 -0
  517. render/public_api/models/label.py +68 -0
  518. render/public_api/models/list_custom_domains_domain_type.py +9 -0
  519. render/public_api/models/list_custom_domains_verification_status.py +9 -0
  520. render/public_api/models/list_logs_response_200.py +102 -0
  521. render/public_api/models/list_logs_values_label.py +13 -0
  522. render/public_api/models/list_objects_response.py +92 -0
  523. render/public_api/models/list_postgres_suspended_item.py +9 -0
  524. render/public_api/models/list_postgres_users_response_200_item.py +86 -0
  525. render/public_api/models/list_routes_type_item.py +9 -0
  526. render/public_api/models/list_services_suspended_item.py +9 -0
  527. render/public_api/models/log.py +100 -0
  528. render/public_api/models/log_direction.py +9 -0
  529. render/public_api/models/log_label.py +70 -0
  530. render/public_api/models/log_label_name.py +22 -0
  531. render/public_api/models/log_stream_owner_update.py +80 -0
  532. render/public_api/models/log_stream_preview_setting.py +9 -0
  533. render/public_api/models/log_stream_resource_update.py +80 -0
  534. render/public_api/models/log_stream_setting.py +9 -0
  535. render/public_api/models/maintenance_ended.py +44 -0
  536. render/public_api/models/maintenance_mode.py +68 -0
  537. render/public_api/models/maintenance_mode_enabled.py +59 -0
  538. render/public_api/models/maintenance_mode_uri_updated.py +67 -0
  539. render/public_api/models/maintenance_run.py +105 -0
  540. render/public_api/models/maintenance_run_patch.py +69 -0
  541. render/public_api/models/maintenance_run_with_resource.py +114 -0
  542. render/public_api/models/maintenance_started.py +65 -0
  543. render/public_api/models/maintenance_state.py +13 -0
  544. render/public_api/models/maintenance_trigger.py +91 -0
  545. render/public_api/models/maxmemory_policy.py +15 -0
  546. render/public_api/models/metrics_stream.py +77 -0
  547. render/public_api/models/metrics_stream_input.py +86 -0
  548. render/public_api/models/native_environment_details.py +78 -0
  549. render/public_api/models/native_environment_details_patch.py +68 -0
  550. render/public_api/models/native_environment_details_post.py +68 -0
  551. render/public_api/models/notification_override.py +78 -0
  552. render/public_api/models/notification_override_with_cursor.py +73 -0
  553. render/public_api/models/notification_service_override.py +78 -0
  554. render/public_api/models/notification_service_override_patch.py +84 -0
  555. render/public_api/models/notification_setting.py +93 -0
  556. render/public_api/models/notification_setting_patch.py +85 -0
  557. render/public_api/models/notify_override.py +11 -0
  558. render/public_api/models/notify_preview_override.py +10 -0
  559. render/public_api/models/notify_setting.py +10 -0
  560. render/public_api/models/notify_setting_v2.py +10 -0
  561. render/public_api/models/object_metadata.py +77 -0
  562. render/public_api/models/object_with_cursor.py +73 -0
  563. render/public_api/models/oom_killed.py +59 -0
  564. render/public_api/models/otel_provider_type.py +16 -0
  565. render/public_api/models/outbound_ips.py +81 -0
  566. render/public_api/models/outbound_ips_type.py +9 -0
  567. render/public_api/models/owner.py +121 -0
  568. render/public_api/models/owner_log_stream_setting.py +86 -0
  569. render/public_api/models/owner_type.py +9 -0
  570. render/public_api/models/owner_with_cursor.py +81 -0
  571. render/public_api/models/paid_plan.py +13 -0
  572. render/public_api/models/patch_route_response_200.py +72 -0
  573. render/public_api/models/persistence_mode.py +10 -0
  574. render/public_api/models/pipeline_minutes_exhausted.py +73 -0
  575. render/public_api/models/plan.py +22 -0
  576. render/public_api/models/post_job_body.py +70 -0
  577. render/public_api/models/postgres.py +300 -0
  578. render/public_api/models/postgres_available.py +44 -0
  579. render/public_api/models/postgres_available_parameter_override.py +106 -0
  580. render/public_api/models/postgres_available_parameter_overrides_result.py +75 -0
  581. render/public_api/models/postgres_backup_completed.py +44 -0
  582. render/public_api/models/postgres_backup_failed.py +44 -0
  583. render/public_api/models/postgres_backup_started.py +44 -0
  584. render/public_api/models/postgres_cluster_leader_changed.py +59 -0
  585. render/public_api/models/postgres_connection_info.py +103 -0
  586. render/public_api/models/postgres_connection_pool_changed.py +91 -0
  587. render/public_api/models/postgres_connection_pool_enabled_changed.py +83 -0
  588. render/public_api/models/postgres_created.py +72 -0
  589. render/public_api/models/postgres_detail.py +336 -0
  590. render/public_api/models/postgres_detail_suspended.py +9 -0
  591. render/public_api/models/postgres_disk_size_changed.py +91 -0
  592. render/public_api/models/postgres_export.py +80 -0
  593. render/public_api/models/postgres_ha_status_changed.py +67 -0
  594. render/public_api/models/postgres_parameter_overrides.py +44 -0
  595. render/public_api/models/postgres_parameter_overrides_wrapper.py +65 -0
  596. render/public_api/models/postgres_patch_input.py +199 -0
  597. render/public_api/models/postgres_pitr_checkpoint_completed.py +44 -0
  598. render/public_api/models/postgres_pitr_checkpoint_failed.py +44 -0
  599. render/public_api/models/postgres_pitr_checkpoint_started.py +44 -0
  600. render/public_api/models/postgres_plans.py +35 -0
  601. render/public_api/models/postgres_post_input.py +254 -0
  602. render/public_api/models/postgres_process.py +185 -0
  603. render/public_api/models/postgres_processes_result.py +73 -0
  604. render/public_api/models/postgres_put_parameter_overrides_result.py +82 -0
  605. render/public_api/models/postgres_query_statistic.py +222 -0
  606. render/public_api/models/postgres_read_replica_stale.py +44 -0
  607. render/public_api/models/postgres_read_replicas_changed.py +67 -0
  608. render/public_api/models/postgres_replication_setup_input.py +96 -0
  609. render/public_api/models/postgres_restarted.py +72 -0
  610. render/public_api/models/postgres_size.py +96 -0
  611. render/public_api/models/postgres_sizes_result.py +73 -0
  612. render/public_api/models/postgres_suspended.py +9 -0
  613. render/public_api/models/postgres_table_scan.py +87 -0
  614. render/public_api/models/postgres_table_scans_result.py +73 -0
  615. render/public_api/models/postgres_top_queries_result.py +73 -0
  616. render/public_api/models/postgres_unavailable.py +44 -0
  617. render/public_api/models/postgres_upgrade_failed.py +67 -0
  618. render/public_api/models/postgres_upgrade_started.py +91 -0
  619. render/public_api/models/postgres_upgrade_succeeded.py +67 -0
  620. render/public_api/models/postgres_version.py +15 -0
  621. render/public_api/models/postgres_with_cursor.py +73 -0
  622. render/public_api/models/pre_deploy_ended.py +99 -0
  623. render/public_api/models/pre_deploy_started.py +67 -0
  624. render/public_api/models/preview_input.py +94 -0
  625. render/public_api/models/previews.py +67 -0
  626. render/public_api/models/previews_generation.py +10 -0
  627. render/public_api/models/private_service_details.py +282 -0
  628. render/public_api/models/private_service_details_patch.py +184 -0
  629. render/public_api/models/private_service_details_post.py +266 -0
  630. render/public_api/models/project.py +108 -0
  631. render/public_api/models/project_patch_input.py +60 -0
  632. render/public_api/models/project_post_environment_input.py +114 -0
  633. render/public_api/models/project_post_input.py +89 -0
  634. render/public_api/models/project_with_cursor.py +73 -0
  635. render/public_api/models/protected_status.py +9 -0
  636. render/public_api/models/pull_request_previews_enabled.py +9 -0
  637. render/public_api/models/put_object_input.py +59 -0
  638. render/public_api/models/put_object_output.py +79 -0
  639. render/public_api/models/read_replica.py +91 -0
  640. render/public_api/models/read_replica_input.py +83 -0
  641. render/public_api/models/recovery_info.py +80 -0
  642. render/public_api/models/recovery_info_recovery_status.py +10 -0
  643. render/public_api/models/recovery_input.py +114 -0
  644. render/public_api/models/redis.py +182 -0
  645. render/public_api/models/redis_connection_info.py +76 -0
  646. render/public_api/models/redis_detail.py +192 -0
  647. render/public_api/models/redis_options.py +79 -0
  648. render/public_api/models/redis_patch_input.py +138 -0
  649. render/public_api/models/redis_plan.py +13 -0
  650. render/public_api/models/redis_post_input.py +166 -0
  651. render/public_api/models/redis_with_cursor.py +73 -0
  652. render/public_api/models/region.py +12 -0
  653. render/public_api/models/registry_credential.py +95 -0
  654. render/public_api/models/registry_credential_registry.py +12 -0
  655. render/public_api/models/registry_credential_summary.py +67 -0
  656. render/public_api/models/render_subdomain_policy.py +9 -0
  657. render/public_api/models/resource.py +67 -0
  658. render/public_api/models/resource_log_stream_setting.py +87 -0
  659. render/public_api/models/resource_ref.py +77 -0
  660. render/public_api/models/resource_ref_type.py +17 -0
  661. render/public_api/models/rollback_deploy_body.py +59 -0
  662. render/public_api/models/route.py +93 -0
  663. render/public_api/models/route_patch.py +60 -0
  664. render/public_api/models/route_post.py +88 -0
  665. render/public_api/models/route_put.py +77 -0
  666. render/public_api/models/route_type.py +9 -0
  667. render/public_api/models/route_with_cursor.py +73 -0
  668. render/public_api/models/run_task.py +96 -0
  669. render/public_api/models/runtime.py +12 -0
  670. render/public_api/models/sandbox.py +149 -0
  671. render/public_api/models/sandbox_connect_request.py +62 -0
  672. render/public_api/models/sandbox_connect_response.py +98 -0
  673. render/public_api/models/sandbox_directory_listing.py +82 -0
  674. render/public_api/models/sandbox_exec_update_request.py +60 -0
  675. render/public_api/models/sandbox_exec_update_response.py +130 -0
  676. render/public_api/models/sandbox_file_entry.py +98 -0
  677. render/public_api/models/sandbox_file_entry_type.py +10 -0
  678. render/public_api/models/sandbox_group.py +141 -0
  679. render/public_api/models/sandbox_group_with_cursor.py +74 -0
  680. render/public_api/models/sandbox_network_policy.py +61 -0
  681. render/public_api/models/sandbox_network_policy_default.py +9 -0
  682. render/public_api/models/sandbox_plan.py +10 -0
  683. render/public_api/models/sandbox_post.py +138 -0
  684. render/public_api/models/sandbox_post_env.py +44 -0
  685. render/public_api/models/sandbox_status.py +13 -0
  686. render/public_api/models/sandbox_with_cursor.py +74 -0
  687. render/public_api/models/scale_service_body.py +59 -0
  688. render/public_api/models/schemas_build_filter.py +70 -0
  689. render/public_api/models/schemas_image.py +96 -0
  690. render/public_api/models/schemas_user.py +68 -0
  691. render/public_api/models/secret_file.py +67 -0
  692. render/public_api/models/secret_file_input.py +67 -0
  693. render/public_api/models/secret_file_with_cursor.py +73 -0
  694. render/public_api/models/server_available.py +44 -0
  695. render/public_api/models/server_failed.py +81 -0
  696. render/public_api/models/server_hardware_failure.py +44 -0
  697. render/public_api/models/server_port.py +69 -0
  698. render/public_api/models/server_port_protocol.py +9 -0
  699. render/public_api/models/server_restarted.py +66 -0
  700. render/public_api/models/service_disk.py +78 -0
  701. render/public_api/models/service_env.py +15 -0
  702. render/public_api/models/service_event.py +770 -0
  703. render/public_api/models/service_event_type.py +48 -0
  704. render/public_api/models/service_event_with_cursor.py +66 -0
  705. render/public_api/models/service_instance.py +69 -0
  706. render/public_api/models/service_patch.py +273 -0
  707. render/public_api/models/service_post.py +357 -0
  708. render/public_api/models/service_resumed.py +44 -0
  709. render/public_api/models/service_runtime.py +15 -0
  710. render/public_api/models/service_suspended.py +44 -0
  711. render/public_api/models/service_type.py +12 -0
  712. render/public_api/models/service_type_short.py +12 -0
  713. render/public_api/models/setup_postgres_replication_response_201.py +44 -0
  714. render/public_api/models/snapshot_restore_post.py +72 -0
  715. render/public_api/models/static_site_details.py +183 -0
  716. render/public_api/models/static_site_details_patch.py +147 -0
  717. render/public_api/models/static_site_details_post.py +189 -0
  718. render/public_api/models/status.py +12 -0
  719. render/public_api/models/stream_sandbox_logs_accept.py +8 -0
  720. render/public_api/models/stream_task_runs_events_accept.py +8 -0
  721. render/public_api/models/suspender_added.py +83 -0
  722. render/public_api/models/suspender_removed.py +83 -0
  723. render/public_api/models/suspender_type.py +14 -0
  724. render/public_api/models/sync.py +118 -0
  725. render/public_api/models/sync_state.py +12 -0
  726. render/public_api/models/sync_with_cursor.py +74 -0
  727. render/public_api/models/task.py +97 -0
  728. render/public_api/models/task_attempt.py +121 -0
  729. render/public_api/models/task_attempt_details.py +141 -0
  730. render/public_api/models/task_data_type_1.py +44 -0
  731. render/public_api/models/task_run.py +168 -0
  732. render/public_api/models/task_run_details.py +216 -0
  733. render/public_api/models/task_run_status.py +14 -0
  734. render/public_api/models/task_run_with_cursor.py +73 -0
  735. render/public_api/models/task_with_cursor.py +73 -0
  736. render/public_api/models/team_member.py +102 -0
  737. render/public_api/models/team_member_role.py +12 -0
  738. render/public_api/models/team_member_status.py +9 -0
  739. render/public_api/models/time_series.py +100 -0
  740. render/public_api/models/time_series_value.py +70 -0
  741. render/public_api/models/update_env_group_secret_file_body.py +59 -0
  742. render/public_api/models/update_registry_credential_body.py +85 -0
  743. render/public_api/models/update_workspace_member_body.py +61 -0
  744. render/public_api/models/user.py +67 -0
  745. render/public_api/models/validate_blueprint_request.py +84 -0
  746. render/public_api/models/validate_blueprint_response.py +105 -0
  747. render/public_api/models/validation_error.py +88 -0
  748. render/public_api/models/validation_plan_summary.py +107 -0
  749. render/public_api/models/web_service_details.py +385 -0
  750. render/public_api/models/web_service_details_patch.py +270 -0
  751. render/public_api/models/web_service_details_post.py +354 -0
  752. render/public_api/models/webhook.py +110 -0
  753. render/public_api/models/webhook_event.py +115 -0
  754. render/public_api/models/webhook_event_with_cursor.py +73 -0
  755. render/public_api/models/webhook_patch_input.py +98 -0
  756. render/public_api/models/webhook_post_input.py +102 -0
  757. render/public_api/models/webhook_with_cursor.py +73 -0
  758. render/public_api/models/workflow.py +163 -0
  759. render/public_api/models/workflow_create.py +169 -0
  760. render/public_api/models/workflow_update.py +109 -0
  761. render/public_api/models/workflow_version.py +95 -0
  762. render/public_api/models/workflow_version_status.py +13 -0
  763. render/public_api/models/workflow_version_with_cursor.py +73 -0
  764. render/public_api/models/workflow_with_cursor.py +73 -0
  765. render/public_api/models/zero_downtime_redeploy_ended.py +44 -0
  766. render/public_api/models/zero_downtime_redeploy_started.py +59 -0
  767. render/public_api/py.typed +1 -0
  768. render/public_api/types.py +54 -0
  769. render/py.typed +0 -0
  770. render/render.py +81 -0
  771. render/render_async.py +80 -0
  772. render/version.py +27 -0
  773. render/workflows/__init__.py +25 -0
  774. render/workflows/_callback_models.py +194 -0
  775. render/workflows/_uds_http.py +128 -0
  776. render/workflows/app.py +263 -0
  777. render/workflows/cli.py +62 -0
  778. render/workflows/client.py +354 -0
  779. render/workflows/context.py +75 -0
  780. render/workflows/executor.py +86 -0
  781. render/workflows/runner.py +174 -0
  782. render/workflows/task.py +348 -0
  783. render/workflows/tests/__init__.py +0 -0
  784. render/workflows/tests/test_app.py +343 -0
  785. render/workflows/tests/test_cli.py +134 -0
  786. render/workflows/tests/test_client.py +59 -0
  787. render/workflows/tests/test_context.py +118 -0
  788. render/workflows/tests/test_end_to_end.py +307 -0
  789. render/workflows/tests/test_executor.py +221 -0
  790. render/workflows/tests/test_lazy_imports.py +100 -0
  791. render/workflows/tests/test_registration.py +293 -0
  792. render/workflows/tests/test_translate_errors.py +126 -0
  793. render/workflows/tests/test_uds_http.py +199 -0
  794. render/workflows/tests/test_version.py +15 -0
  795. render-1.0.1.dist-info/METADATA +382 -0
  796. render-1.0.1.dist-info/RECORD +799 -0
  797. render-1.0.1.dist-info/WHEEL +4 -0
  798. render-1.0.1.dist-info/entry_points.txt +2 -0
  799. render-1.0.1.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,514 @@
1
+ # Auto-generated sync version. Do not edit — run scripts/unasync.py instead.
2
+
3
+ """Typed wrapper over the generated public_api sandbox endpoints."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import os
9
+ import posixpath
10
+ import stat
11
+ from collections.abc import Iterator, Sequence
12
+ from datetime import datetime
13
+ from pathlib import Path
14
+ from typing import TYPE_CHECKING, Any, NoReturn
15
+
16
+ import httpx
17
+
18
+ from render.client.errors import (
19
+ ClientError,
20
+ RateLimitError,
21
+ RenderError,
22
+ ServerError,
23
+ )
24
+ from render.client.util_sync import (
25
+ handle_api_error,
26
+ handle_http_errors,
27
+ handle_httpx_exception,
28
+ )
29
+ from render.experimental.sandbox._tar import (
30
+ close_content,
31
+ iter_file,
32
+ iter_tar_gzip,
33
+ stat_path,
34
+ )
35
+ from render.experimental.sandbox.errors import (
36
+ SandboxDownloadError,
37
+ SandboxExecError,
38
+ SandboxExecStreamError,
39
+ SandboxFileNotFoundError,
40
+ SandboxNotFoundError,
41
+ )
42
+ from render.experimental.sandbox.files import (
43
+ PartialDownload,
44
+ check_content_encoding,
45
+ disposition_filename,
46
+ media_type,
47
+ parent_dir,
48
+ prepare_extract_dir,
49
+ resolve_file_dest,
50
+ run_blocking,
51
+ )
52
+ from render.experimental.sandbox.types import (
53
+ Sandbox,
54
+ SandboxExecEvent,
55
+ SandboxExecExit,
56
+ SandboxExecOutput,
57
+ SandboxList,
58
+ )
59
+ from render.public_api.api.sandboxes import (
60
+ create_sandbox,
61
+ list_sandboxes,
62
+ retrieve_sandbox,
63
+ terminate_sandbox,
64
+ )
65
+ from render.public_api.models.error import Error
66
+ from render.public_api.models.sandbox import Sandbox as GeneratedSandbox
67
+ from render.public_api.models.sandbox_network_policy import SandboxNetworkPolicy
68
+ from render.public_api.models.sandbox_network_policy_default import (
69
+ SandboxNetworkPolicyDefault,
70
+ )
71
+ from render.public_api.models.sandbox_plan import SandboxPlan
72
+ from render.public_api.models.sandbox_post import SandboxPOST
73
+ from render.public_api.models.sandbox_post_env import SandboxPOSTEnv
74
+ from render.public_api.models.sandbox_status import SandboxStatus
75
+ from render.public_api.models.sandbox_with_cursor import SandboxWithCursor
76
+ from render.public_api.types import UNSET, Response
77
+
78
+ if TYPE_CHECKING:
79
+ from render.public_api.client import AuthenticatedClient, Client
80
+
81
+
82
+ # The code the sandbox agent sends in a 404 body when the remote path is missing.
83
+ _FILE_NOT_FOUND_CODE = "file_not_found"
84
+
85
+ # Aliased at module scope so the annotations on _list_api_call resolve the
86
+ # builtin list, not the SyncSandboxApi.list method that shadows it in the class body.
87
+ _SandboxWithCursorList = list[SandboxWithCursor]
88
+ _SandboxStatusList = list[SandboxStatus]
89
+
90
+ # File transfer content types. The content type states intent and nothing else:
91
+ # a single file travels as octet-stream and a directory as an x-tar archive the
92
+ # server extracts, with Content-Encoding carrying wire compression separately.
93
+ _CONTENT_TYPE_OCTET_STREAM = "application/octet-stream"
94
+ _CONTENT_TYPE_TAR = "application/x-tar"
95
+
96
+
97
+ def _to_sandbox(model: GeneratedSandbox) -> Sandbox:
98
+ terminated = model.terminated_at
99
+ return Sandbox(
100
+ id=model.id,
101
+ status=model.status.value,
102
+ plan=model.plan.value,
103
+ network_policy=model.network_policy.default.value,
104
+ region=model.region,
105
+ timeout_seconds=model.timeout_seconds,
106
+ created_at=model.created_at,
107
+ terminated_at=terminated if isinstance(terminated, datetime) else None,
108
+ )
109
+
110
+
111
+ def _normalize_statuses(status: str | Sequence[str] | None) -> list[SandboxStatus]:
112
+ if status is None:
113
+ return []
114
+ values = [status] if isinstance(status, str) else list(status)
115
+ return [SandboxStatus(value) for value in values]
116
+
117
+
118
+ class SyncSandboxApi:
119
+ """Typed wrapper over the generated sandbox endpoints."""
120
+
121
+ def __init__(self, client: AuthenticatedClient | Client):
122
+ self.client = client
123
+
124
+ def create(
125
+ self,
126
+ owner_id: str,
127
+ plan: str | None,
128
+ timeout_seconds: int | None,
129
+ network_policy: str | None,
130
+ region: str | None,
131
+ env: dict[str, str] | None,
132
+ ) -> Sandbox:
133
+ body = SandboxPOST(owner_id=owner_id)
134
+ if plan is not None:
135
+ body.plan = SandboxPlan(plan)
136
+ if timeout_seconds is not None:
137
+ body.timeout_seconds = timeout_seconds
138
+ if region is not None:
139
+ body.region = region
140
+ if network_policy is not None:
141
+ body.network_policy = SandboxNetworkPolicy(
142
+ default=SandboxNetworkPolicyDefault(network_policy)
143
+ )
144
+ if env is not None:
145
+ body.env = SandboxPOSTEnv.from_dict(env)
146
+
147
+ response = self._create_api_call(body)
148
+ if not isinstance(response.parsed, GeneratedSandbox):
149
+ raise RenderError("Failed to create sandbox: unexpected response type")
150
+ return _to_sandbox(response.parsed)
151
+
152
+ def get(self, sandbox_id: str, owner_id: str) -> Sandbox:
153
+ try:
154
+ response = retrieve_sandbox.sync_detailed(
155
+ sandbox_id, client=self.client, owner_id=owner_id
156
+ )
157
+ except httpx.RequestError as exc:
158
+ handle_httpx_exception(exc, "retrieve sandbox")
159
+ except json.JSONDecodeError as exc:
160
+ body = exc.doc.strip() if exc.doc else "empty response"
161
+ raise RenderError(
162
+ f"retrieve sandbox failed: server returned a non-JSON response: {body}"
163
+ ) from exc
164
+ if response.status_code == 404:
165
+ raise SandboxNotFoundError(f"sandbox {sandbox_id} not found")
166
+ handle_api_error(response, "retrieve sandbox")
167
+ if not isinstance(response.parsed, GeneratedSandbox):
168
+ raise RenderError("Failed to retrieve sandbox: unexpected response type")
169
+ return _to_sandbox(response.parsed)
170
+
171
+ def list(
172
+ self,
173
+ owner_id: str,
174
+ status: str | Sequence[str] | None,
175
+ cursor: str | None,
176
+ limit: int | None,
177
+ ) -> SandboxList:
178
+ statuses = _normalize_statuses(status)
179
+ response = self._list_api_call(owner_id, statuses, cursor, limit)
180
+ parsed = response.parsed
181
+ if not isinstance(parsed, list):
182
+ raise RenderError("Failed to list sandboxes: unexpected response type")
183
+ sandboxes = [_to_sandbox(item.sandbox) for item in parsed]
184
+ next_cursor = parsed[-1].cursor if parsed else None
185
+ return SandboxList(sandboxes=sandboxes, next_cursor=next_cursor)
186
+
187
+ @handle_http_errors("list sandboxes")
188
+ def _list_api_call(
189
+ self,
190
+ owner_id: str,
191
+ statuses: _SandboxStatusList,
192
+ cursor: str | None,
193
+ limit: int | None,
194
+ ) -> Response[Error | _SandboxWithCursorList]:
195
+ return list_sandboxes.sync_detailed(
196
+ client=self.client,
197
+ owner_id=[owner_id],
198
+ status=statuses or UNSET,
199
+ cursor=cursor if cursor is not None else UNSET,
200
+ limit=limit if limit is not None else UNSET,
201
+ )
202
+
203
+ def terminate(self, sandbox_id: str, owner_id: str) -> None:
204
+ try:
205
+ response = terminate_sandbox.sync_detailed(
206
+ sandbox_id, client=self.client, owner_id=owner_id
207
+ )
208
+ except httpx.RequestError as exc:
209
+ handle_httpx_exception(exc, "terminate sandbox")
210
+ except json.JSONDecodeError as exc:
211
+ body = exc.doc.strip() if exc.doc else "empty response"
212
+ raise RenderError(
213
+ f"terminate sandbox failed: server returned a non-JSON response: {body}"
214
+ ) from exc
215
+ if response.status_code == 404:
216
+ raise SandboxNotFoundError(f"sandbox {sandbox_id} not found")
217
+ handle_api_error(response, "terminate sandbox")
218
+
219
+ def _mint_run_token(
220
+ self, sandbox_id: str, owner_id: str, operation: str, command: str
221
+ ) -> dict[str, Any]:
222
+ # Command rides along so the API keeps a sanitized copy for the audit trail.
223
+ api_client = self.client.get_httpx_client()
224
+ try:
225
+ response = api_client.post(
226
+ f"/sandboxes/{sandbox_id}/runs/{operation}/token",
227
+ params={"ownerId": owner_id},
228
+ json={"command": command},
229
+ )
230
+ except httpx.RequestError as exc:
231
+ handle_httpx_exception(exc, "connect sandbox run")
232
+ if response.status_code >= 400:
233
+ _raise_sandbox_http_error(
234
+ sandbox_id, response.status_code, response.text, "exec"
235
+ )
236
+ return response.json()
237
+
238
+ def _mint_file_token(
239
+ self, sandbox_id: str, owner_id: str, operation: str, path: str
240
+ ) -> dict[str, Any]:
241
+ api_client = self.client.get_httpx_client()
242
+ try:
243
+ response = api_client.post(
244
+ f"/sandboxes/{sandbox_id}/files/{operation}/token",
245
+ params={"ownerId": owner_id, "path": path},
246
+ )
247
+ except httpx.RequestError as exc:
248
+ handle_httpx_exception(exc, "connect sandbox files")
249
+ if response.status_code >= 400:
250
+ _raise_sandbox_http_error(
251
+ sandbox_id, response.status_code, response.text, operation
252
+ )
253
+ return response.json()
254
+
255
+ def upload(
256
+ self,
257
+ sandbox_id: str,
258
+ local_path: str | os.PathLike[str],
259
+ remote_path: str,
260
+ owner_id: str,
261
+ ) -> None:
262
+ source = Path(local_path)
263
+ # The server rejects any path it would have to clean, so clean it here
264
+ # instead of turning a trailing slash into a 400. The CLI does the same
265
+ # before minting, which keeps the two clients in step. Guard the empty
266
+ # path first: normpath turns it into ".", which would quietly copy to
267
+ # the home directory instead of failing.
268
+ if not remote_path:
269
+ raise ValueError("remote_path is required")
270
+ remote_path = posixpath.normpath(remote_path)
271
+ # stat, not lstat: a symlinked directory uploads as the directory it
272
+ # points at. Statting before the mint also keeps a missing local path
273
+ # from spending a token.
274
+ info = stat_path(source)
275
+ if not (stat.S_ISDIR(info.st_mode) or stat.S_ISREG(info.st_mode)):
276
+ # Opening a fifo blocks until a writer appears, which may be never,
277
+ # and that open would block the event loop rather than time out.
278
+ # Refuse before the mint so a bad path does not spend a token.
279
+ raise ValueError(
280
+ f"{source} is not a file or directory; "
281
+ "sockets, fifos and devices cannot be copied to a sandbox"
282
+ )
283
+ connection = self._mint_file_token(sandbox_id, owner_id, "upload", remote_path)
284
+
285
+ headers = {"Authorization": f"Bearer {connection['token']}"}
286
+ content: Iterator[bytes]
287
+ if stat.S_ISDIR(info.st_mode):
288
+ headers["Content-Type"] = _CONTENT_TYPE_TAR
289
+ # The archive's length is not known until it has been produced, so
290
+ # the body goes out chunked. gzip is the wire encoding only: the
291
+ # server gunzips it and extracts the tar underneath.
292
+ headers["Content-Encoding"] = "gzip"
293
+ content = iter_tar_gzip(source)
294
+ else:
295
+ headers["Content-Type"] = _CONTENT_TYPE_OCTET_STREAM
296
+ # An explicit length keeps httpx from sending an iterator body
297
+ # chunked, and lets the sandbox size the write up front.
298
+ headers["Content-Length"] = str(info.st_size)
299
+ content = iter_file(source)
300
+
301
+ # Keep the connect timeout, but let a large upload take as long as it
302
+ # takes, as the object client does.
303
+ timeout = httpx.Timeout(5.0, read=None, write=None)
304
+ try:
305
+ with httpx.Client(timeout=timeout) as proxy_client:
306
+ response = proxy_client.request(
307
+ connection["method"],
308
+ connection["uri"],
309
+ headers=headers,
310
+ content=content,
311
+ )
312
+ except httpx.RequestError as exc:
313
+ handle_httpx_exception(exc, "upload to sandbox")
314
+ finally:
315
+ # httpx closes the body on today's failure paths, but that is its
316
+ # internals, not a contract. Closing here is what actually
317
+ # guarantees the archive producer stops when a request dies early.
318
+ close_content(content)
319
+ # Any 2xx, not just the 204 the sandbox sends today: the API deploys
320
+ # ahead of the SDK, so pinning the exact code would break on a benign
321
+ # change.
322
+ if not 200 <= response.status_code < 300:
323
+ _raise_sandbox_http_error(
324
+ sandbox_id, response.status_code, response.text, "upload"
325
+ )
326
+
327
+ def download_file(
328
+ self, sandbox_id: str, remote_path: str, local_path: str, owner_id: str
329
+ ) -> str:
330
+ """Copy remote_path out of the sandbox and return the local path written.
331
+
332
+ A directory arrives as an x-tar archive and is extracted under
333
+ local_path; anything else is written as a single file.
334
+ """
335
+ connection = self._mint_file_token(
336
+ sandbox_id, owner_id, "download", remote_path
337
+ )
338
+ headers = {
339
+ "Authorization": f"Bearer {connection['token']}",
340
+ # Ask only for the coding httpx undoes for us. Left to itself it
341
+ # also advertises deflate, and br/zstd when those are installed,
342
+ # any of which would arrive as a body we refuse to write.
343
+ "Accept-Encoding": "gzip",
344
+ }
345
+ # read bounds the wait for the next chunk, not the transfer, so a large
346
+ # download still has as long as it needs while a body that stops
347
+ # arriving fails instead of hanging. Same budget as exec_stream.
348
+ timeout = httpx.Timeout(5.0, read=45.0, write=None)
349
+ try:
350
+ with (
351
+ httpx.Client(timeout=timeout) as proxy_client,
352
+ proxy_client.stream(
353
+ connection["method"], connection["uri"], headers=headers
354
+ ) as response,
355
+ ):
356
+ if response.status_code >= 400:
357
+ body = (response.read()).decode("utf-8", errors="replace")
358
+ _raise_sandbox_http_error(
359
+ sandbox_id, response.status_code, body, "download"
360
+ )
361
+ check_content_encoding(response.headers.get("content-encoding", ""))
362
+
363
+ if media_type(response.headers.get("content-type", "")) == (
364
+ _CONTENT_TYPE_TAR
365
+ ):
366
+ # The archive is spooled next to the destination rather than
367
+ # extracted as it arrives: feeding tarfile from an async
368
+ # stream would take a thread to bridge, and the memory
369
+ # footprint is the same either way.
370
+ with PartialDownload(prepare_extract_dir(local_path)) as partial:
371
+ for chunk in response.iter_bytes():
372
+ partial.write(chunk)
373
+ run_blocking(partial.extract, local_path)
374
+ return local_path
375
+
376
+ dest = resolve_file_dest(
377
+ local_path,
378
+ disposition_filename(
379
+ response.headers.get("content-disposition", "")
380
+ ),
381
+ remote_path,
382
+ )
383
+ with PartialDownload(parent_dir(dest)) as partial:
384
+ for chunk in response.iter_bytes():
385
+ partial.write(chunk)
386
+ return run_blocking(partial.commit, dest)
387
+ except httpx.RequestError as exc:
388
+ handle_httpx_exception(exc, "download sandbox file")
389
+ except OSError as exc:
390
+ # Spooling, extracting and renaming all touch the local disk, and a
391
+ # bare OSError from any of them tells a caller nothing about which
392
+ # download failed.
393
+ raise SandboxDownloadError(
394
+ f"could not write the download to {local_path}: {exc}"
395
+ ) from exc
396
+
397
+ def exec_stream(
398
+ self, sandbox_id: str, command: str, owner_id: str, operation: str = "stream"
399
+ ) -> Iterator[SandboxExecEvent]:
400
+ connection = self._mint_run_token(sandbox_id, owner_id, operation, command)
401
+ token = connection["token"]
402
+ uri = connection["uri"]
403
+ method = connection["method"]
404
+ headers = {
405
+ "Authorization": f"Bearer {token}",
406
+ "Accept": "text/event-stream",
407
+ "Content-Type": "application/json",
408
+ }
409
+ # Read timeout at 3x the server's 15s SSE keep-alive interval, so a dead
410
+ # connection is detected without cutting off a live but idle stream.
411
+ timeout = httpx.Timeout(5.0, read=45.0, write=None)
412
+ try:
413
+ with (
414
+ httpx.Client(timeout=timeout) as proxy_client,
415
+ proxy_client.stream(
416
+ method, uri, headers=headers, json={"command": command}
417
+ ) as response,
418
+ ):
419
+ if response.status_code >= 400:
420
+ body = (response.read()).decode("utf-8", errors="replace")
421
+ _raise_sandbox_http_error(
422
+ sandbox_id, response.status_code, body, "exec"
423
+ )
424
+ for name, data in _iter_sse_events(response.iter_lines()):
425
+ if name == "output":
426
+ payload = _load_event(data)
427
+ yield SandboxExecOutput(
428
+ stream=payload["stream"], data=payload["data"]
429
+ )
430
+ elif name == "exit":
431
+ payload = _load_event(data)
432
+ yield SandboxExecExit(exit_code=payload["exit_code"])
433
+ return
434
+ elif name == "error":
435
+ payload = _load_event(data)
436
+ raise SandboxExecStreamError(
437
+ payload.get("status", 0), payload.get("message", "")
438
+ )
439
+ else:
440
+ raise SandboxExecError(f"unknown sandbox exec event {name!r}")
441
+ raise SandboxExecError(
442
+ "sandbox exec stream ended without an exit event"
443
+ )
444
+ except httpx.RequestError as exc:
445
+ handle_httpx_exception(exc, "exec sandbox")
446
+
447
+ @handle_http_errors("create sandbox")
448
+ def _create_api_call(self, body: SandboxPOST) -> Response[Error | GeneratedSandbox]:
449
+ return create_sandbox.sync_detailed(client=self.client, body=body)
450
+
451
+
452
+ def _load_event(data: str) -> dict[str, Any]:
453
+ try:
454
+ return json.loads(data)
455
+ except json.JSONDecodeError as exc:
456
+ raise SandboxExecError(
457
+ f"failed to parse sandbox exec event data: {data}"
458
+ ) from exc
459
+
460
+
461
+ def _file_error_code(body: str) -> str:
462
+ """The ``code`` of a sandbox agent error body, or "" if it has none."""
463
+ try:
464
+ payload = json.loads(body)
465
+ except ValueError:
466
+ return ""
467
+ code = payload.get("code") if isinstance(payload, dict) else None
468
+ return code if isinstance(code, str) else ""
469
+
470
+
471
+ def _raise_sandbox_http_error(
472
+ sandbox_id: str, status_code: int, body: str, action: str
473
+ ) -> NoReturn:
474
+ message = f"{action} failed with status {status_code}"
475
+ if body:
476
+ message = f"{message}: {body}"
477
+ if status_code == 404:
478
+ # The agent 404s a missing remote path with this code, and the sandbox
479
+ # is alive when it does. Any other 404 is the sandbox itself being gone,
480
+ # including the one the mint endpoint returns.
481
+ if _file_error_code(body) == _FILE_NOT_FOUND_CODE:
482
+ raise SandboxFileNotFoundError(message)
483
+ raise SandboxNotFoundError(f"sandbox {sandbox_id} not found")
484
+ if status_code == 429:
485
+ raise RateLimitError(message)
486
+ if 400 <= status_code < 500:
487
+ raise ClientError(message)
488
+ raise ServerError(message)
489
+
490
+
491
+ def _iter_sse_events(
492
+ lines: Iterator[str],
493
+ ) -> Iterator[tuple[str, str]]:
494
+ event_name = ""
495
+ data_parts: list[str] = []
496
+ for raw in lines:
497
+ line = raw.rstrip("\r")
498
+ if line == "":
499
+ if event_name or data_parts:
500
+ yield event_name, "\n".join(data_parts)
501
+ event_name = ""
502
+ data_parts = []
503
+ continue
504
+ if line.startswith(":"):
505
+ continue
506
+ if line.startswith("event:"):
507
+ event_name = line[len("event:") :].strip()
508
+ elif line.startswith("data:"):
509
+ chunk = line[len("data:") :]
510
+ if chunk.startswith(" "):
511
+ chunk = chunk[1:]
512
+ data_parts.append(chunk)
513
+ if event_name or data_parts:
514
+ yield event_name, "\n".join(data_parts)
@@ -0,0 +1,168 @@
1
+ """High-level client for creating and operating Render sandboxes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from collections.abc import AsyncIterator, Sequence
7
+ from typing import TYPE_CHECKING
8
+
9
+ from render.client.errors import RenderError
10
+ from render.experimental.sandbox.api import SandboxApi
11
+ from render.experimental.sandbox.files import normalize_remote_path
12
+ from render.experimental.sandbox.types import Sandbox, SandboxExecEvent, SandboxList
13
+
14
+ if TYPE_CHECKING:
15
+ from render.public_api.client import AuthenticatedClient, Client
16
+
17
+
18
+ class SandboxClient:
19
+ """High-level client for creating and operating Render sandboxes."""
20
+
21
+ def __init__(
22
+ self,
23
+ client: AuthenticatedClient | Client,
24
+ default_owner_id: str | None = None,
25
+ default_region: str | None = None,
26
+ ):
27
+ self.client = client
28
+ self.api = SandboxApi(client)
29
+ self._default_owner_id = default_owner_id
30
+ self._default_region = default_region
31
+
32
+ def _resolve_owner_id(self, owner_id: str | None) -> str:
33
+ resolved = owner_id or self._default_owner_id
34
+ if not resolved:
35
+ raise RenderError(
36
+ "owner_id is required. Provide it as a parameter or set the RENDER_WORKSPACE_ID environment variable."
37
+ )
38
+ return resolved
39
+
40
+ async def create(
41
+ self,
42
+ *,
43
+ owner_id: str | None = None,
44
+ plan: str | None = None,
45
+ timeout_seconds: int | None = None,
46
+ network_policy: str | None = None,
47
+ region: str | None = None,
48
+ env: dict[str, str] | None = None,
49
+ ) -> Sandbox:
50
+ """Create a sandbox and return its initial snapshot.
51
+
52
+ All parameters are optional. Unspecified fields fall back to the
53
+ workspace defaults enforced by the API (plan starter, 7200s timeout,
54
+ workspace default region and network policy).
55
+ """
56
+ resolved_owner_id = self._resolve_owner_id(owner_id)
57
+ resolved_region = region or self._default_region
58
+ return await self.api.create(
59
+ owner_id=resolved_owner_id,
60
+ plan=plan,
61
+ timeout_seconds=timeout_seconds,
62
+ network_policy=network_policy,
63
+ region=resolved_region,
64
+ env=env,
65
+ )
66
+
67
+ async def from_id(self, sandbox_id: str, *, owner_id: str | None = None) -> Sandbox:
68
+ """Reconnect to an existing sandbox by id.
69
+
70
+ Raises SandboxNotFoundError if the sandbox does not exist or has been
71
+ terminated.
72
+ """
73
+ resolved_owner_id = self._resolve_owner_id(owner_id)
74
+ return await self.api.get(sandbox_id, resolved_owner_id)
75
+
76
+ async def list(
77
+ self,
78
+ *,
79
+ owner_id: str | None = None,
80
+ status: str | Sequence[str] | None = None,
81
+ cursor: str | None = None,
82
+ limit: int | None = None,
83
+ ) -> SandboxList:
84
+ """List sandboxes for a workspace.
85
+
86
+ status filters by sandbox status, one or a sequence of them (each one
87
+ of creating, running, suspended, resuming, errored, terminated). limit
88
+ is capped at 100 by the API.
89
+ """
90
+ resolved_owner_id = self._resolve_owner_id(owner_id)
91
+ return await self.api.list(resolved_owner_id, status, cursor, limit)
92
+
93
+ async def terminate(self, sandbox_id: str, *, owner_id: str | None = None) -> None:
94
+ """Terminate a sandbox.
95
+
96
+ Idempotent for an already-terminated sandbox (the API returns 204).
97
+ Raises SandboxNotFoundError if the sandbox id was never valid.
98
+ """
99
+ resolved_owner_id = self._resolve_owner_id(owner_id)
100
+ await self.api.terminate(sandbox_id, resolved_owner_id)
101
+
102
+ async def copy_to(
103
+ self,
104
+ sandbox_id: str,
105
+ local_path: str | os.PathLike[str],
106
+ remote_path: str,
107
+ *,
108
+ owner_id: str | None = None,
109
+ ) -> None:
110
+ """Copy a local file or directory into the sandbox at remote_path.
111
+
112
+ A relative remote_path resolves under the sandbox's home directory and
113
+ an absolute one addresses the filesystem, as scp does. The path is
114
+ normalized before it is sent, so a trailing slash or a redundant
115
+ separator is accepted rather than rejected by the sandbox.
116
+
117
+ A file is uploaded as raw bytes. A directory is streamed as an archive
118
+ that the sandbox extracts at remote_path: names are relative to
119
+ local_path, symlinks are stored rather than followed, and sockets,
120
+ fifos and other special files are skipped. Passing one of those special
121
+ files as local_path raises ValueError.
122
+ """
123
+ resolved_owner_id = self._resolve_owner_id(owner_id)
124
+ await self.api.upload(sandbox_id, local_path, remote_path, resolved_owner_id)
125
+
126
+ def exec(
127
+ self,
128
+ sandbox_id: str,
129
+ command: str,
130
+ *,
131
+ owner_id: str | None = None,
132
+ ) -> AsyncIterator[SandboxExecEvent]:
133
+ """Run a command in a sandbox and stream its output.
134
+
135
+ command is passed to ``bash -c`` in the sandbox. Yields
136
+ SandboxExecOutput chunks as they arrive and a final SandboxExecExit.
137
+ A non-zero exit code is reported via SandboxExecExit, not an exception.
138
+ Raises SandboxExecStreamError if the sandbox reports a terminal error.
139
+ """
140
+ resolved_owner_id = self._resolve_owner_id(owner_id)
141
+ return self.api.exec_stream(sandbox_id, command, resolved_owner_id)
142
+
143
+ async def copy_from(
144
+ self,
145
+ sandbox_id: str,
146
+ remote_path: str,
147
+ local_path: str | os.PathLike[str],
148
+ *,
149
+ owner_id: str | None = None,
150
+ ) -> str:
151
+ """Copy a file or directory out of a sandbox, returning the path written.
152
+
153
+ A directory is extracted under local_path. A file is written to
154
+ local_path, or into it under the name the sandbox suggests when
155
+ local_path is an existing directory. remote_path is cleaned before it
156
+ is sent, since the API rejects a path carrying "." , ".." or redundant
157
+ separators. Raises SandboxFileNotFoundError if the sandbox has no such
158
+ path. Raises SandboxDownloadError if the response is unsafe or the download
159
+ cannot be written or extracted locally. Directory extraction is not atomic
160
+ and may leave partial contents after a failure.
161
+ """
162
+ resolved_owner_id = self._resolve_owner_id(owner_id)
163
+ return await self.api.download_file(
164
+ sandbox_id,
165
+ normalize_remote_path(remote_path),
166
+ os.fspath(local_path),
167
+ resolved_owner_id,
168
+ )