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.
- render/__init__.py +98 -0
- render/client/__init__.py +119 -0
- render/client/client.py +110 -0
- render/client/errors.py +39 -0
- render/client/sse.py +90 -0
- render/client/sse_sync.py +20 -0
- render/client/tests/__init__.py +0 -0
- render/client/tests/test_client.py +379 -0
- render/client/tests/test_method_parity.py +118 -0
- render/client/tests/test_render.py +52 -0
- render/client/tests/test_sse.py +67 -0
- render/client/tests/test_util.py +303 -0
- render/client/tests/test_util_sync.py +73 -0
- render/client/tests/test_workflows_sync.py +313 -0
- render/client/types.py +52 -0
- render/client/util.py +285 -0
- render/client/util_sync.py +83 -0
- render/client/workflows.py +363 -0
- render/client/workflows_sync.py +298 -0
- render/experimental/__init__.py +37 -0
- render/experimental/experimental.py +93 -0
- render/experimental/experimental_sync.py +78 -0
- render/experimental/key_value/__init__.py +33 -0
- render/experimental/key_value/api.py +243 -0
- render/experimental/key_value/compare.py +83 -0
- render/experimental/key_value/provider.py +285 -0
- render/experimental/key_value/tests/__init__.py +0 -0
- render/experimental/key_value/tests/test_api.py +371 -0
- render/experimental/key_value/tests/test_compare.py +136 -0
- render/experimental/key_value/tests/test_provider.py +1016 -0
- render/experimental/key_value/types.py +130 -0
- render/experimental/key_value/utils.py +11 -0
- render/experimental/object/__init__.py +38 -0
- render/experimental/object/api.py +250 -0
- render/experimental/object/api_sync.py +250 -0
- render/experimental/object/client.py +545 -0
- render/experimental/object/client_sync.py +547 -0
- render/experimental/object/e2e_helpers.py +78 -0
- render/experimental/object/tests/__init__.py +0 -0
- render/experimental/object/tests/test_client.py +228 -0
- render/experimental/object/tests/test_e2e.py +125 -0
- render/experimental/object/types.py +87 -0
- render/experimental/sandbox/__init__.py +31 -0
- render/experimental/sandbox/_tar.py +278 -0
- render/experimental/sandbox/api.py +518 -0
- render/experimental/sandbox/api_sync.py +514 -0
- render/experimental/sandbox/client.py +168 -0
- render/experimental/sandbox/client_sync.py +170 -0
- render/experimental/sandbox/errors.py +37 -0
- render/experimental/sandbox/files.py +378 -0
- render/experimental/sandbox/tests/__init__.py +0 -0
- render/experimental/sandbox/tests/test_client.py +802 -0
- render/experimental/sandbox/tests/test_download.py +728 -0
- render/experimental/sandbox/tests/test_e2e.py +252 -0
- render/experimental/sandbox/tests/test_tar.py +153 -0
- render/experimental/sandbox/tests/test_types.py +57 -0
- render/experimental/sandbox/types.py +46 -0
- render/public_api/__init__.py +8 -0
- render/public_api/api/__init__.py +1 -0
- render/public_api/api/artifact_sources/__init__.py +1 -0
- render/public_api/api/artifact_sources/add_or_update_artifact_source_secret_file.py +252 -0
- render/public_api/api/artifact_sources/create_artifact_source.py +243 -0
- render/public_api/api/artifact_sources/delete_artifact_source.py +188 -0
- render/public_api/api/artifact_sources/delete_artifact_source_env_var.py +223 -0
- render/public_api/api/artifact_sources/delete_artifact_source_secret_file.py +223 -0
- render/public_api/api/artifact_sources/get_artifact_source.py +185 -0
- render/public_api/api/artifact_sources/get_env_vars_for_artifact_source.py +241 -0
- render/public_api/api/artifact_sources/link_artifact_source_to_env_group.py +215 -0
- render/public_api/api/artifact_sources/list_artifact_sources.py +338 -0
- render/public_api/api/artifact_sources/list_artifacts_in_artifact_source.py +241 -0
- render/public_api/api/artifact_sources/list_secret_files_for_artifact_source.py +241 -0
- render/public_api/api/artifact_sources/retrieve_artifact_source_env_var.py +225 -0
- render/public_api/api/artifact_sources/retrieve_artifact_source_secret_file.py +225 -0
- render/public_api/api/artifact_sources/unlink_artifact_source_from_env_group.py +209 -0
- render/public_api/api/artifact_sources/update_artifact_source.py +244 -0
- render/public_api/api/artifact_sources/update_artifact_source_env_var.py +257 -0
- render/public_api/api/artifact_sources/update_env_vars_for_artifact_source.py +245 -0
- render/public_api/api/artifact_sources/update_secret_files_for_artifact_source.py +255 -0
- render/public_api/api/audit_logs/__init__.py +1 -0
- render/public_api/api/audit_logs/list_organization_audit_logs.py +303 -0
- render/public_api/api/audit_logs/list_owner_audit_logs.py +303 -0
- render/public_api/api/blueprints/__init__.py +1 -0
- render/public_api/api/blueprints/disconnect_blueprint.py +210 -0
- render/public_api/api/blueprints/list_blueprint_syncs.py +241 -0
- render/public_api/api/blueprints/list_blueprints.py +251 -0
- render/public_api/api/blueprints/retrieve_blueprint.py +200 -0
- render/public_api/api/blueprints/update_blueprint.py +222 -0
- render/public_api/api/blueprints/validate_blueprint.py +217 -0
- render/public_api/api/custom_domains/__init__.py +1 -0
- render/public_api/api/custom_domains/create_custom_domain.py +242 -0
- render/public_api/api/custom_domains/delete_custom_domain.py +216 -0
- render/public_api/api/custom_domains/list_custom_domains.py +346 -0
- render/public_api/api/custom_domains/refresh_custom_domain.py +216 -0
- render/public_api/api/custom_domains/retrieve_custom_domain.py +218 -0
- render/public_api/api/dedicated_i_ps/__init__.py +1 -0
- render/public_api/api/dedicated_i_ps/create_dedicated_ip.py +234 -0
- render/public_api/api/dedicated_i_ps/delete_dedicated_ip.py +198 -0
- render/public_api/api/dedicated_i_ps/list_dedicated_ips.py +223 -0
- render/public_api/api/dedicated_i_ps/retrieve_dedicated_ip.py +200 -0
- render/public_api/api/dedicated_i_ps/update_dedicated_ip.py +244 -0
- render/public_api/api/deploys/__init__.py +1 -0
- render/public_api/api/deploys/cancel_deploy.py +216 -0
- render/public_api/api/deploys/create_deploy.py +231 -0
- render/public_api/api/deploys/list_deploys.py +377 -0
- render/public_api/api/deploys/retrieve_deploy.py +213 -0
- render/public_api/api/deploys/rollback_deploy.py +241 -0
- render/public_api/api/disks/__init__.py +1 -0
- render/public_api/api/disks/add_disk.py +222 -0
- render/public_api/api/disks/delete_disk.py +210 -0
- render/public_api/api/disks/list_disks.py +381 -0
- render/public_api/api/disks/list_snapshots.py +214 -0
- render/public_api/api/disks/restore_snapshot.py +255 -0
- render/public_api/api/disks/retrieve_disk.py +200 -0
- render/public_api/api/disks/update_disk.py +243 -0
- render/public_api/api/environment_groups/__init__.py +1 -0
- render/public_api/api/environment_groups/create_env_group.py +199 -0
- render/public_api/api/environment_groups/delete_env_group.py +192 -0
- render/public_api/api/environment_groups/delete_env_group_env_var.py +201 -0
- render/public_api/api/environment_groups/delete_env_group_secret_file.py +201 -0
- render/public_api/api/environment_groups/link_service_to_env_group.py +211 -0
- render/public_api/api/environment_groups/list_env_groups.py +352 -0
- render/public_api/api/environment_groups/retrieve_env_group.py +190 -0
- render/public_api/api/environment_groups/retrieve_env_group_env_var.py +203 -0
- render/public_api/api/environment_groups/retrieve_env_group_secret_file.py +203 -0
- render/public_api/api/environment_groups/unlink_service_from_env_group.py +209 -0
- render/public_api/api/environment_groups/update_env_group.py +212 -0
- render/public_api/api/environment_groups/update_env_group_env_var.py +230 -0
- render/public_api/api/environment_groups/update_env_group_secret_file.py +225 -0
- render/public_api/api/events/__init__.py +1 -0
- render/public_api/api/events/retrieve_event.py +205 -0
- render/public_api/api/key_value/__init__.py +1 -0
- render/public_api/api/key_value/create_key_value.py +199 -0
- render/public_api/api/key_value/delete_key_value.py +188 -0
- render/public_api/api/key_value/list_key_value.py +380 -0
- render/public_api/api/key_value/resume_key_value.py +203 -0
- render/public_api/api/key_value/retrieve_key_value.py +190 -0
- render/public_api/api/key_value/retrieve_key_value_connection_info.py +194 -0
- render/public_api/api/key_value/suspend_key_value.py +203 -0
- render/public_api/api/key_value/update_key_value.py +221 -0
- render/public_api/api/logs/__init__.py +1 -0
- render/public_api/api/logs/delete_owner_log_stream.py +188 -0
- render/public_api/api/logs/delete_resource_log_stream.py +192 -0
- render/public_api/api/logs/get_owner_log_stream.py +205 -0
- render/public_api/api/logs/get_resource_log_stream.py +209 -0
- render/public_api/api/logs/list_logs.py +535 -0
- render/public_api/api/logs/list_logs_values.py +527 -0
- render/public_api/api/logs/list_resource_log_streams.py +317 -0
- render/public_api/api/logs/subscribe_logs.py +527 -0
- render/public_api/api/logs/update_owner_log_stream.py +231 -0
- render/public_api/api/logs/update_resource_log_stream.py +231 -0
- render/public_api/api/maintenance/__init__.py +1 -0
- render/public_api/api/maintenance/list_maintenance.py +249 -0
- render/public_api/api/maintenance/retrieve_maintenance.py +190 -0
- render/public_api/api/maintenance/trigger_maintenance.py +212 -0
- render/public_api/api/maintenance/update_maintenance.py +222 -0
- render/public_api/api/metrics/__init__.py +1 -0
- render/public_api/api/metrics/delete_owner_metrics_stream.py +172 -0
- render/public_api/api/metrics/get_active_connections.py +237 -0
- render/public_api/api/metrics/get_bandwidth.py +237 -0
- render/public_api/api/metrics/get_bandwidth_sources.py +250 -0
- render/public_api/api/metrics/get_cpu.py +287 -0
- render/public_api/api/metrics/get_cpu_limit.py +267 -0
- render/public_api/api/metrics/get_cpu_target.py +267 -0
- render/public_api/api/metrics/get_disk_capacity.py +252 -0
- render/public_api/api/metrics/get_disk_usage.py +252 -0
- render/public_api/api/metrics/get_http_latency.py +297 -0
- render/public_api/api/metrics/get_http_requests.py +302 -0
- render/public_api/api/metrics/get_instance_count.py +252 -0
- render/public_api/api/metrics/get_memory.py +267 -0
- render/public_api/api/metrics/get_memory_limit.py +267 -0
- render/public_api/api/metrics/get_memory_target.py +267 -0
- render/public_api/api/metrics/get_owner_metrics_stream.py +174 -0
- render/public_api/api/metrics/get_replication_lag.py +237 -0
- render/public_api/api/metrics/get_task_runs_completed.py +281 -0
- render/public_api/api/metrics/get_task_runs_queued.py +237 -0
- render/public_api/api/metrics/list_application_filter_values.py +254 -0
- render/public_api/api/metrics/list_http_filter_values.py +282 -0
- render/public_api/api/metrics/list_path_filter_values.py +289 -0
- render/public_api/api/metrics/upsert_owner_metrics_stream.py +192 -0
- render/public_api/api/notification_settings/__init__.py +1 -0
- render/public_api/api/notification_settings/list_notification_overrides.py +255 -0
- render/public_api/api/notification_settings/patch_owner_notification_settings.py +207 -0
- render/public_api/api/notification_settings/patch_service_notification_overrides.py +207 -0
- render/public_api/api/notification_settings/retrieve_owner_notification_settings.py +193 -0
- render/public_api/api/notification_settings/retrieve_service_notification_overrides.py +193 -0
- render/public_api/api/object_storage/__init__.py +1 -0
- render/public_api/api/object_storage/delete_object.py +215 -0
- render/public_api/api/object_storage/get_object.py +221 -0
- render/public_api/api/object_storage/list_objects.py +240 -0
- render/public_api/api/object_storage/put_object.py +248 -0
- render/public_api/api/one_off_jobs/__init__.py +1 -0
- render/public_api/api/one_off_jobs/cancel_job.py +203 -0
- render/public_api/api/one_off_jobs/list_job.py +367 -0
- render/public_api/api/one_off_jobs/post_job.py +216 -0
- render/public_api/api/one_off_jobs/retrieve_job.py +203 -0
- render/public_api/api/postgres/__init__.py +1 -0
- render/public_api/api/postgres/create_postgres.py +199 -0
- render/public_api/api/postgres/create_postgres_export.py +207 -0
- render/public_api/api/postgres/create_postgres_user.py +229 -0
- render/public_api/api/postgres/delete_postgres.py +192 -0
- render/public_api/api/postgres/delete_postgres_user.py +201 -0
- render/public_api/api/postgres/failover_postgres.py +207 -0
- render/public_api/api/postgres/list_available_postgres_parameter_overrides.py +190 -0
- render/public_api/api/postgres/list_postgres.py +418 -0
- render/public_api/api/postgres/list_postgres_export.py +199 -0
- render/public_api/api/postgres/list_postgres_parameter_overrides.py +190 -0
- render/public_api/api/postgres/list_postgres_processes.py +190 -0
- render/public_api/api/postgres/list_postgres_sizes.py +190 -0
- render/public_api/api/postgres/list_postgres_table_scans.py +190 -0
- render/public_api/api/postgres/list_postgres_top_queries.py +194 -0
- render/public_api/api/postgres/list_postgres_users.py +195 -0
- render/public_api/api/postgres/promote_postgres.py +203 -0
- render/public_api/api/postgres/recover_postgres.py +231 -0
- render/public_api/api/postgres/restart_postgres.py +203 -0
- render/public_api/api/postgres/resume_postgres.py +203 -0
- render/public_api/api/postgres/retrieve_postgres.py +190 -0
- render/public_api/api/postgres/retrieve_postgres_connection_info.py +194 -0
- render/public_api/api/postgres/retrieve_postgres_recovery_info.py +194 -0
- render/public_api/api/postgres/setup_postgres_replication.py +231 -0
- render/public_api/api/postgres/suspend_postgres.py +203 -0
- render/public_api/api/postgres/update_postgres.py +217 -0
- render/public_api/api/postgres/update_postgres_parameter_overrides.py +217 -0
- render/public_api/api/projects_environments/__init__.py +1 -0
- render/public_api/api/projects_environments/add_resources_to_environment.py +212 -0
- render/public_api/api/projects_environments/create_environment.py +199 -0
- render/public_api/api/projects_environments/create_project.py +199 -0
- render/public_api/api/projects_environments/delete_environment.py +216 -0
- render/public_api/api/projects_environments/delete_project.py +216 -0
- render/public_api/api/projects_environments/list_environments.py +369 -0
- render/public_api/api/projects_environments/list_projects.py +329 -0
- render/public_api/api/projects_environments/remove_resources_from_environment.py +211 -0
- render/public_api/api/projects_environments/retrieve_environment.py +190 -0
- render/public_api/api/projects_environments/retrieve_project.py +190 -0
- render/public_api/api/projects_environments/update_environment.py +212 -0
- render/public_api/api/projects_environments/update_project.py +224 -0
- render/public_api/api/redis_deprecated/__init__.py +1 -0
- render/public_api/api/redis_deprecated/create_redis.py +199 -0
- render/public_api/api/redis_deprecated/delete_redis.py +188 -0
- render/public_api/api/redis_deprecated/list_redis.py +384 -0
- render/public_api/api/redis_deprecated/resume_redis.py +203 -0
- render/public_api/api/redis_deprecated/retrieve_redis.py +190 -0
- render/public_api/api/redis_deprecated/retrieve_redis_connection_info.py +194 -0
- render/public_api/api/redis_deprecated/suspend_redis.py +203 -0
- render/public_api/api/redis_deprecated/update_redis.py +217 -0
- render/public_api/api/registry_credentials/__init__.py +1 -0
- render/public_api/api/registry_credentials/create_registry_credential.py +209 -0
- render/public_api/api/registry_credentials/delete_registry_credential.py +198 -0
- render/public_api/api/registry_credentials/list_registry_credentials.py +370 -0
- render/public_api/api/registry_credentials/retrieve_registry_credential.py +200 -0
- render/public_api/api/registry_credentials/update_registry_credential.py +241 -0
- render/public_api/api/sandboxes/__init__.py +1 -0
- render/public_api/api/sandboxes/connect_sandbox_files.py +281 -0
- render/public_api/api/sandboxes/connect_sandbox_run.py +271 -0
- render/public_api/api/sandboxes/create_sandbox.py +199 -0
- render/public_api/api/sandboxes/list_sandbox_files.py +244 -0
- render/public_api/api/sandboxes/list_sandbox_groups.py +216 -0
- render/public_api/api/sandboxes/list_sandboxes.py +269 -0
- render/public_api/api/sandboxes/retrieve_sandbox.py +211 -0
- render/public_api/api/sandboxes/retrieve_sandbox_execution.py +224 -0
- render/public_api/api/sandboxes/stream_sandbox_logs.py +274 -0
- render/public_api/api/sandboxes/terminate_sandbox.py +217 -0
- render/public_api/api/sandboxes/update_sandbox_exec.py +258 -0
- render/public_api/api/services/__init__.py +1 -0
- render/public_api/api/services/add_or_update_secret_file.py +252 -0
- render/public_api/api/services/autoscale_service.py +230 -0
- render/public_api/api/services/create_ephemeral_shell.py +217 -0
- render/public_api/api/services/create_service.py +204 -0
- render/public_api/api/services/delete_autoscaling_config.py +198 -0
- render/public_api/api/services/delete_env_var.py +223 -0
- render/public_api/api/services/delete_secret_file.py +223 -0
- render/public_api/api/services/delete_service.py +198 -0
- render/public_api/api/services/get_env_vars_for_service.py +241 -0
- render/public_api/api/services/list_events.py +288 -0
- render/public_api/api/services/list_instances.py +190 -0
- render/public_api/api/services/list_secret_files_for_service.py +241 -0
- render/public_api/api/services/list_services.py +439 -0
- render/public_api/api/services/preview_service.py +227 -0
- render/public_api/api/services/purge_cache.py +203 -0
- render/public_api/api/services/restart_service.py +211 -0
- render/public_api/api/services/resume_service.py +203 -0
- render/public_api/api/services/retrieve_env_var.py +225 -0
- render/public_api/api/services/retrieve_secret_file.py +225 -0
- render/public_api/api/services/retrieve_service.py +190 -0
- render/public_api/api/services/retrieve_service_outbound_ips.py +207 -0
- render/public_api/api/services/scale_service.py +237 -0
- render/public_api/api/services/suspend_service.py +203 -0
- render/public_api/api/services/update_env_var.py +257 -0
- render/public_api/api/services/update_env_vars_for_service.py +241 -0
- render/public_api/api/services/update_secret_files_for_service.py +255 -0
- render/public_api/api/services/update_service.py +227 -0
- render/public_api/api/services_cron_jobs/__init__.py +1 -0
- render/public_api/api/services_cron_jobs/cancel_cron_job_run.py +183 -0
- render/public_api/api/services_cron_jobs/run_cron_job.py +185 -0
- render/public_api/api/services_headers/__init__.py +1 -0
- render/public_api/api/services_headers/add_headers.py +222 -0
- render/public_api/api/services_headers/delete_header.py +211 -0
- render/public_api/api/services_headers/list_headers.py +302 -0
- render/public_api/api/services_headers/update_headers.py +243 -0
- render/public_api/api/services_routes/__init__.py +1 -0
- render/public_api/api/services_routes/add_route.py +227 -0
- render/public_api/api/services_routes/delete_route.py +211 -0
- render/public_api/api/services_routes/list_routes.py +306 -0
- render/public_api/api/services_routes/patch_route.py +259 -0
- render/public_api/api/services_routes/put_routes.py +259 -0
- render/public_api/api/users/__init__.py +1 -0
- render/public_api/api/users/get_user.py +161 -0
- render/public_api/api/webhooks/__init__.py +1 -0
- render/public_api/api/webhooks/create_webhook.py +199 -0
- render/public_api/api/webhooks/delete_webhook.py +183 -0
- render/public_api/api/webhooks/list_webhook_events.py +268 -0
- render/public_api/api/webhooks/list_webhooks.py +237 -0
- render/public_api/api/webhooks/retrieve_webhook.py +185 -0
- render/public_api/api/webhooks/update_webhook.py +212 -0
- render/public_api/api/workflow_tasks_beta/__init__.py +1 -0
- render/public_api/api/workflow_tasks_beta/cancel_task_run.py +188 -0
- render/public_api/api/workflow_tasks_beta/create_task.py +204 -0
- render/public_api/api/workflow_tasks_beta/get_task.py +190 -0
- render/public_api/api/workflow_tasks_beta/get_task_run.py +190 -0
- render/public_api/api/workflow_tasks_beta/list_task_runs.py +317 -0
- render/public_api/api/workflow_tasks_beta/list_tasks.py +298 -0
- render/public_api/api/workflow_tasks_beta/stream_task_runs_events.py +230 -0
- render/public_api/api/workflows_beta/__init__.py +1 -0
- render/public_api/api/workflows_beta/create_workflow.py +199 -0
- render/public_api/api/workflows_beta/create_workflow_version.py +197 -0
- render/public_api/api/workflows_beta/delete_workflow.py +188 -0
- render/public_api/api/workflows_beta/get_workflow.py +190 -0
- render/public_api/api/workflows_beta/get_workflow_version.py +190 -0
- render/public_api/api/workflows_beta/list_workflow_versions.py +275 -0
- render/public_api/api/workflows_beta/list_workflows.py +298 -0
- render/public_api/api/workflows_beta/update_workflow.py +212 -0
- render/public_api/api/workspaces/__init__.py +1 -0
- render/public_api/api/workspaces/list_owners.py +255 -0
- render/public_api/api/workspaces/remove_workspace_member.py +206 -0
- render/public_api/api/workspaces/retrieve_owner.py +207 -0
- render/public_api/api/workspaces/retrieve_owner_members.py +200 -0
- render/public_api/api/workspaces/update_workspace_member.py +235 -0
- render/public_api/client.py +268 -0
- render/public_api/errors.py +16 -0
- render/public_api/models/__init__.py +861 -0
- render/public_api/models/add_headers_response_201.py +72 -0
- render/public_api/models/add_or_update_artifact_source_secret_file_body.py +59 -0
- render/public_api/models/add_or_update_secret_file_body.py +59 -0
- render/public_api/models/artifact.py +145 -0
- render/public_api/models/artifact_fetch_failed.py +67 -0
- render/public_api/models/artifact_source.py +162 -0
- render/public_api/models/artifact_source_changed.py +70 -0
- render/public_api/models/artifact_source_git.py +167 -0
- render/public_api/models/artifact_source_git_region.py +12 -0
- render/public_api/models/artifact_source_git_runtime.py +14 -0
- render/public_api/models/artifact_source_image.py +78 -0
- render/public_api/models/artifact_source_patch_git.py +175 -0
- render/public_api/models/artifact_source_patch_git_region.py +12 -0
- render/public_api/models/artifact_source_patch_git_runtime.py +14 -0
- render/public_api/models/artifact_source_patch_image.py +71 -0
- render/public_api/models/artifact_source_patch_input.py +101 -0
- render/public_api/models/artifact_source_post_input.py +213 -0
- render/public_api/models/artifact_source_service_link.py +67 -0
- render/public_api/models/artifact_source_with_cursor.py +73 -0
- render/public_api/models/audit_log.py +113 -0
- render/public_api/models/audit_log_actor.py +80 -0
- render/public_api/models/audit_log_actor_type.py +10 -0
- render/public_api/models/audit_log_event.py +87 -0
- render/public_api/models/audit_log_metadata.py +49 -0
- render/public_api/models/audit_log_status.py +9 -0
- render/public_api/models/audit_log_with_cursor.py +73 -0
- render/public_api/models/auto_deploy.py +9 -0
- render/public_api/models/auto_deploy_disabled.py +79 -0
- render/public_api/models/auto_deploy_enabled.py +68 -0
- render/public_api/models/auto_deploy_trigger.py +10 -0
- render/public_api/models/autoscaling_config.py +89 -0
- render/public_api/models/autoscaling_config_changed.py +83 -0
- render/public_api/models/autoscaling_criteria.py +73 -0
- render/public_api/models/autoscaling_criteria_percentage.py +68 -0
- render/public_api/models/autoscaling_ended.py +67 -0
- render/public_api/models/autoscaling_started.py +105 -0
- render/public_api/models/background_worker_details.py +256 -0
- render/public_api/models/background_worker_details_patch.py +184 -0
- render/public_api/models/background_worker_details_post.py +266 -0
- render/public_api/models/blueprint.py +128 -0
- render/public_api/models/blueprint_detail.py +150 -0
- render/public_api/models/blueprint_patch.py +77 -0
- render/public_api/models/blueprint_with_cursor.py +74 -0
- render/public_api/models/branch_deleted.py +67 -0
- render/public_api/models/build.py +148 -0
- render/public_api/models/build_config.py +96 -0
- render/public_api/models/build_deploy_end_reason.py +122 -0
- render/public_api/models/build_deploy_end_reason_id.py +59 -0
- render/public_api/models/build_deploy_trigger.py +150 -0
- render/public_api/models/build_ended.py +91 -0
- render/public_api/models/build_filter.py +67 -0
- render/public_api/models/build_plan.py +9 -0
- render/public_api/models/build_runtime.py +14 -0
- render/public_api/models/build_started.py +73 -0
- render/public_api/models/build_status.py +13 -0
- render/public_api/models/cache.py +61 -0
- render/public_api/models/cache_profile.py +10 -0
- render/public_api/models/cidr_block_and_description.py +67 -0
- render/public_api/models/commit_ignored.py +67 -0
- render/public_api/models/commit_ref.py +59 -0
- render/public_api/models/connect_sandbox_files_operation.py +9 -0
- render/public_api/models/connect_sandbox_run_operation.py +9 -0
- render/public_api/models/create_custom_domain_body.py +59 -0
- render/public_api/models/create_deploy_body.py +130 -0
- render/public_api/models/create_deploy_body_clear_cache.py +9 -0
- render/public_api/models/create_ephemeral_shell_body.py +69 -0
- render/public_api/models/create_ephemeral_shell_response_201.py +59 -0
- render/public_api/models/create_registry_credential_body.py +93 -0
- render/public_api/models/create_version.py +70 -0
- render/public_api/models/credential_create_input.py +59 -0
- render/public_api/models/cron_job_details.py +163 -0
- render/public_api/models/cron_job_details_patch.py +138 -0
- render/public_api/models/cron_job_details_post.py +172 -0
- render/public_api/models/cron_job_run.py +123 -0
- render/public_api/models/cron_job_run_ended.py +110 -0
- render/public_api/models/cron_job_run_started.py +59 -0
- render/public_api/models/cron_job_run_status.py +11 -0
- render/public_api/models/custom_domain.py +135 -0
- render/public_api/models/custom_domain_domain_type.py +9 -0
- render/public_api/models/custom_domain_server.py +68 -0
- render/public_api/models/custom_domain_verification_status.py +9 -0
- render/public_api/models/custom_domain_with_cursor.py +73 -0
- render/public_api/models/database_role.py +9 -0
- render/public_api/models/database_status.py +18 -0
- render/public_api/models/dedicated_ip.py +146 -0
- render/public_api/models/dedicated_ip_status.py +14 -0
- render/public_api/models/dedicated_ippatch.py +81 -0
- render/public_api/models/dedicated_ippost.py +100 -0
- render/public_api/models/deploy.py +211 -0
- render/public_api/models/deploy_commit.py +86 -0
- render/public_api/models/deploy_ended.py +102 -0
- render/public_api/models/deploy_image.py +78 -0
- render/public_api/models/deploy_mode.py +9 -0
- render/public_api/models/deploy_started.py +85 -0
- render/public_api/models/deploy_status.py +18 -0
- render/public_api/models/deploy_trigger.py +17 -0
- render/public_api/models/deploy_with_cursor.py +81 -0
- render/public_api/models/disk.py +83 -0
- render/public_api/models/disk_created.py +67 -0
- render/public_api/models/disk_deleted.py +59 -0
- render/public_api/models/disk_details.py +112 -0
- render/public_api/models/disk_patch.py +77 -0
- render/public_api/models/disk_post.py +83 -0
- render/public_api/models/disk_snapshot.py +88 -0
- render/public_api/models/disk_updated.py +75 -0
- render/public_api/models/disk_with_cursor.py +73 -0
- render/public_api/models/docker_details.py +108 -0
- render/public_api/models/docker_details_patch.py +86 -0
- render/public_api/models/docker_details_post.py +86 -0
- render/public_api/models/edge_cache_disabled.py +65 -0
- render/public_api/models/edge_cache_enabled.py +65 -0
- render/public_api/models/edge_cache_purged.py +65 -0
- render/public_api/models/edge_cache_trigger.py +91 -0
- render/public_api/models/env_group.py +162 -0
- render/public_api/models/env_group_link.py +77 -0
- render/public_api/models/env_group_meta.py +126 -0
- render/public_api/models/env_group_patch_input.py +59 -0
- render/public_api/models/env_group_post_input.py +161 -0
- render/public_api/models/env_var.py +67 -0
- render/public_api/models/env_var_generate_value.py +59 -0
- render/public_api/models/env_var_key_generate_value.py +68 -0
- render/public_api/models/env_var_key_value.py +67 -0
- render/public_api/models/env_var_value.py +59 -0
- render/public_api/models/env_var_with_cursor.py +73 -0
- render/public_api/models/environment.py +152 -0
- render/public_api/models/environment_patch_input.py +112 -0
- render/public_api/models/environment_post_input.py +122 -0
- render/public_api/models/environment_resources_post_input.py +59 -0
- render/public_api/models/environment_with_cursor.py +74 -0
- render/public_api/models/error.py +79 -0
- render/public_api/models/error_code.py +10 -0
- render/public_api/models/event.py +1122 -0
- render/public_api/models/event_status.py +10 -0
- render/public_api/models/event_type.py +74 -0
- render/public_api/models/execution.py +144 -0
- render/public_api/models/execution_operation.py +11 -0
- render/public_api/models/execution_type.py +9 -0
- render/public_api/models/failure_reason.py +138 -0
- render/public_api/models/filter_application_values_collection_item.py +78 -0
- render/public_api/models/filter_application_values_collection_item_filter.py +8 -0
- render/public_api/models/filter_http_values_collection_item.py +78 -0
- render/public_api/models/filter_http_values_collection_item_filter.py +9 -0
- render/public_api/models/get_bandwidth_sources_response_200.py +75 -0
- render/public_api/models/get_bandwidth_sources_response_200_data_item.py +101 -0
- render/public_api/models/get_bandwidth_sources_response_200_data_item_labels.py +78 -0
- render/public_api/models/get_bandwidth_sources_response_200_data_item_labels_traffic_source.py +12 -0
- render/public_api/models/get_bandwidth_sources_response_200_data_item_values_item.py +68 -0
- render/public_api/models/get_cpu_aggregation_method.py +10 -0
- render/public_api/models/get_http_requests_aggregate_by.py +9 -0
- render/public_api/models/get_object_output.py +71 -0
- render/public_api/models/get_task_runs_completed_aggregate_by.py +8 -0
- render/public_api/models/get_task_runs_completed_state.py +9 -0
- render/public_api/models/header.py +83 -0
- render/public_api/models/header_input.py +76 -0
- render/public_api/models/header_with_cursor.py +73 -0
- render/public_api/models/image.py +80 -0
- render/public_api/models/image_pull_failed.py +67 -0
- render/public_api/models/initial_deploy_hook_ended.py +59 -0
- render/public_api/models/initial_deploy_hook_started.py +59 -0
- render/public_api/models/instance_count_changed.py +67 -0
- render/public_api/models/instance_type_changed.py +67 -0
- render/public_api/models/internal_routing.py +8 -0
- render/public_api/models/job.py +144 -0
- render/public_api/models/job_run_ended.py +92 -0
- render/public_api/models/job_status.py +12 -0
- render/public_api/models/job_with_cursor.py +73 -0
- render/public_api/models/key_value.py +182 -0
- render/public_api/models/key_value_available.py +44 -0
- render/public_api/models/key_value_config_restart.py +67 -0
- render/public_api/models/key_value_connection_info.py +76 -0
- render/public_api/models/key_value_detail.py +192 -0
- render/public_api/models/key_value_options.py +79 -0
- render/public_api/models/key_value_patch_input.py +138 -0
- render/public_api/models/key_value_plan.py +13 -0
- render/public_api/models/key_value_post_input.py +166 -0
- render/public_api/models/key_value_unhealthy.py +44 -0
- render/public_api/models/key_value_with_cursor.py +73 -0
- render/public_api/models/label.py +68 -0
- render/public_api/models/list_custom_domains_domain_type.py +9 -0
- render/public_api/models/list_custom_domains_verification_status.py +9 -0
- render/public_api/models/list_logs_response_200.py +102 -0
- render/public_api/models/list_logs_values_label.py +13 -0
- render/public_api/models/list_objects_response.py +92 -0
- render/public_api/models/list_postgres_suspended_item.py +9 -0
- render/public_api/models/list_postgres_users_response_200_item.py +86 -0
- render/public_api/models/list_routes_type_item.py +9 -0
- render/public_api/models/list_services_suspended_item.py +9 -0
- render/public_api/models/log.py +100 -0
- render/public_api/models/log_direction.py +9 -0
- render/public_api/models/log_label.py +70 -0
- render/public_api/models/log_label_name.py +22 -0
- render/public_api/models/log_stream_owner_update.py +80 -0
- render/public_api/models/log_stream_preview_setting.py +9 -0
- render/public_api/models/log_stream_resource_update.py +80 -0
- render/public_api/models/log_stream_setting.py +9 -0
- render/public_api/models/maintenance_ended.py +44 -0
- render/public_api/models/maintenance_mode.py +68 -0
- render/public_api/models/maintenance_mode_enabled.py +59 -0
- render/public_api/models/maintenance_mode_uri_updated.py +67 -0
- render/public_api/models/maintenance_run.py +105 -0
- render/public_api/models/maintenance_run_patch.py +69 -0
- render/public_api/models/maintenance_run_with_resource.py +114 -0
- render/public_api/models/maintenance_started.py +65 -0
- render/public_api/models/maintenance_state.py +13 -0
- render/public_api/models/maintenance_trigger.py +91 -0
- render/public_api/models/maxmemory_policy.py +15 -0
- render/public_api/models/metrics_stream.py +77 -0
- render/public_api/models/metrics_stream_input.py +86 -0
- render/public_api/models/native_environment_details.py +78 -0
- render/public_api/models/native_environment_details_patch.py +68 -0
- render/public_api/models/native_environment_details_post.py +68 -0
- render/public_api/models/notification_override.py +78 -0
- render/public_api/models/notification_override_with_cursor.py +73 -0
- render/public_api/models/notification_service_override.py +78 -0
- render/public_api/models/notification_service_override_patch.py +84 -0
- render/public_api/models/notification_setting.py +93 -0
- render/public_api/models/notification_setting_patch.py +85 -0
- render/public_api/models/notify_override.py +11 -0
- render/public_api/models/notify_preview_override.py +10 -0
- render/public_api/models/notify_setting.py +10 -0
- render/public_api/models/notify_setting_v2.py +10 -0
- render/public_api/models/object_metadata.py +77 -0
- render/public_api/models/object_with_cursor.py +73 -0
- render/public_api/models/oom_killed.py +59 -0
- render/public_api/models/otel_provider_type.py +16 -0
- render/public_api/models/outbound_ips.py +81 -0
- render/public_api/models/outbound_ips_type.py +9 -0
- render/public_api/models/owner.py +121 -0
- render/public_api/models/owner_log_stream_setting.py +86 -0
- render/public_api/models/owner_type.py +9 -0
- render/public_api/models/owner_with_cursor.py +81 -0
- render/public_api/models/paid_plan.py +13 -0
- render/public_api/models/patch_route_response_200.py +72 -0
- render/public_api/models/persistence_mode.py +10 -0
- render/public_api/models/pipeline_minutes_exhausted.py +73 -0
- render/public_api/models/plan.py +22 -0
- render/public_api/models/post_job_body.py +70 -0
- render/public_api/models/postgres.py +300 -0
- render/public_api/models/postgres_available.py +44 -0
- render/public_api/models/postgres_available_parameter_override.py +106 -0
- render/public_api/models/postgres_available_parameter_overrides_result.py +75 -0
- render/public_api/models/postgres_backup_completed.py +44 -0
- render/public_api/models/postgres_backup_failed.py +44 -0
- render/public_api/models/postgres_backup_started.py +44 -0
- render/public_api/models/postgres_cluster_leader_changed.py +59 -0
- render/public_api/models/postgres_connection_info.py +103 -0
- render/public_api/models/postgres_connection_pool_changed.py +91 -0
- render/public_api/models/postgres_connection_pool_enabled_changed.py +83 -0
- render/public_api/models/postgres_created.py +72 -0
- render/public_api/models/postgres_detail.py +336 -0
- render/public_api/models/postgres_detail_suspended.py +9 -0
- render/public_api/models/postgres_disk_size_changed.py +91 -0
- render/public_api/models/postgres_export.py +80 -0
- render/public_api/models/postgres_ha_status_changed.py +67 -0
- render/public_api/models/postgres_parameter_overrides.py +44 -0
- render/public_api/models/postgres_parameter_overrides_wrapper.py +65 -0
- render/public_api/models/postgres_patch_input.py +199 -0
- render/public_api/models/postgres_pitr_checkpoint_completed.py +44 -0
- render/public_api/models/postgres_pitr_checkpoint_failed.py +44 -0
- render/public_api/models/postgres_pitr_checkpoint_started.py +44 -0
- render/public_api/models/postgres_plans.py +35 -0
- render/public_api/models/postgres_post_input.py +254 -0
- render/public_api/models/postgres_process.py +185 -0
- render/public_api/models/postgres_processes_result.py +73 -0
- render/public_api/models/postgres_put_parameter_overrides_result.py +82 -0
- render/public_api/models/postgres_query_statistic.py +222 -0
- render/public_api/models/postgres_read_replica_stale.py +44 -0
- render/public_api/models/postgres_read_replicas_changed.py +67 -0
- render/public_api/models/postgres_replication_setup_input.py +96 -0
- render/public_api/models/postgres_restarted.py +72 -0
- render/public_api/models/postgres_size.py +96 -0
- render/public_api/models/postgres_sizes_result.py +73 -0
- render/public_api/models/postgres_suspended.py +9 -0
- render/public_api/models/postgres_table_scan.py +87 -0
- render/public_api/models/postgres_table_scans_result.py +73 -0
- render/public_api/models/postgres_top_queries_result.py +73 -0
- render/public_api/models/postgres_unavailable.py +44 -0
- render/public_api/models/postgres_upgrade_failed.py +67 -0
- render/public_api/models/postgres_upgrade_started.py +91 -0
- render/public_api/models/postgres_upgrade_succeeded.py +67 -0
- render/public_api/models/postgres_version.py +15 -0
- render/public_api/models/postgres_with_cursor.py +73 -0
- render/public_api/models/pre_deploy_ended.py +99 -0
- render/public_api/models/pre_deploy_started.py +67 -0
- render/public_api/models/preview_input.py +94 -0
- render/public_api/models/previews.py +67 -0
- render/public_api/models/previews_generation.py +10 -0
- render/public_api/models/private_service_details.py +282 -0
- render/public_api/models/private_service_details_patch.py +184 -0
- render/public_api/models/private_service_details_post.py +266 -0
- render/public_api/models/project.py +108 -0
- render/public_api/models/project_patch_input.py +60 -0
- render/public_api/models/project_post_environment_input.py +114 -0
- render/public_api/models/project_post_input.py +89 -0
- render/public_api/models/project_with_cursor.py +73 -0
- render/public_api/models/protected_status.py +9 -0
- render/public_api/models/pull_request_previews_enabled.py +9 -0
- render/public_api/models/put_object_input.py +59 -0
- render/public_api/models/put_object_output.py +79 -0
- render/public_api/models/read_replica.py +91 -0
- render/public_api/models/read_replica_input.py +83 -0
- render/public_api/models/recovery_info.py +80 -0
- render/public_api/models/recovery_info_recovery_status.py +10 -0
- render/public_api/models/recovery_input.py +114 -0
- render/public_api/models/redis.py +182 -0
- render/public_api/models/redis_connection_info.py +76 -0
- render/public_api/models/redis_detail.py +192 -0
- render/public_api/models/redis_options.py +79 -0
- render/public_api/models/redis_patch_input.py +138 -0
- render/public_api/models/redis_plan.py +13 -0
- render/public_api/models/redis_post_input.py +166 -0
- render/public_api/models/redis_with_cursor.py +73 -0
- render/public_api/models/region.py +12 -0
- render/public_api/models/registry_credential.py +95 -0
- render/public_api/models/registry_credential_registry.py +12 -0
- render/public_api/models/registry_credential_summary.py +67 -0
- render/public_api/models/render_subdomain_policy.py +9 -0
- render/public_api/models/resource.py +67 -0
- render/public_api/models/resource_log_stream_setting.py +87 -0
- render/public_api/models/resource_ref.py +77 -0
- render/public_api/models/resource_ref_type.py +17 -0
- render/public_api/models/rollback_deploy_body.py +59 -0
- render/public_api/models/route.py +93 -0
- render/public_api/models/route_patch.py +60 -0
- render/public_api/models/route_post.py +88 -0
- render/public_api/models/route_put.py +77 -0
- render/public_api/models/route_type.py +9 -0
- render/public_api/models/route_with_cursor.py +73 -0
- render/public_api/models/run_task.py +96 -0
- render/public_api/models/runtime.py +12 -0
- render/public_api/models/sandbox.py +149 -0
- render/public_api/models/sandbox_connect_request.py +62 -0
- render/public_api/models/sandbox_connect_response.py +98 -0
- render/public_api/models/sandbox_directory_listing.py +82 -0
- render/public_api/models/sandbox_exec_update_request.py +60 -0
- render/public_api/models/sandbox_exec_update_response.py +130 -0
- render/public_api/models/sandbox_file_entry.py +98 -0
- render/public_api/models/sandbox_file_entry_type.py +10 -0
- render/public_api/models/sandbox_group.py +141 -0
- render/public_api/models/sandbox_group_with_cursor.py +74 -0
- render/public_api/models/sandbox_network_policy.py +61 -0
- render/public_api/models/sandbox_network_policy_default.py +9 -0
- render/public_api/models/sandbox_plan.py +10 -0
- render/public_api/models/sandbox_post.py +138 -0
- render/public_api/models/sandbox_post_env.py +44 -0
- render/public_api/models/sandbox_status.py +13 -0
- render/public_api/models/sandbox_with_cursor.py +74 -0
- render/public_api/models/scale_service_body.py +59 -0
- render/public_api/models/schemas_build_filter.py +70 -0
- render/public_api/models/schemas_image.py +96 -0
- render/public_api/models/schemas_user.py +68 -0
- render/public_api/models/secret_file.py +67 -0
- render/public_api/models/secret_file_input.py +67 -0
- render/public_api/models/secret_file_with_cursor.py +73 -0
- render/public_api/models/server_available.py +44 -0
- render/public_api/models/server_failed.py +81 -0
- render/public_api/models/server_hardware_failure.py +44 -0
- render/public_api/models/server_port.py +69 -0
- render/public_api/models/server_port_protocol.py +9 -0
- render/public_api/models/server_restarted.py +66 -0
- render/public_api/models/service_disk.py +78 -0
- render/public_api/models/service_env.py +15 -0
- render/public_api/models/service_event.py +770 -0
- render/public_api/models/service_event_type.py +48 -0
- render/public_api/models/service_event_with_cursor.py +66 -0
- render/public_api/models/service_instance.py +69 -0
- render/public_api/models/service_patch.py +273 -0
- render/public_api/models/service_post.py +357 -0
- render/public_api/models/service_resumed.py +44 -0
- render/public_api/models/service_runtime.py +15 -0
- render/public_api/models/service_suspended.py +44 -0
- render/public_api/models/service_type.py +12 -0
- render/public_api/models/service_type_short.py +12 -0
- render/public_api/models/setup_postgres_replication_response_201.py +44 -0
- render/public_api/models/snapshot_restore_post.py +72 -0
- render/public_api/models/static_site_details.py +183 -0
- render/public_api/models/static_site_details_patch.py +147 -0
- render/public_api/models/static_site_details_post.py +189 -0
- render/public_api/models/status.py +12 -0
- render/public_api/models/stream_sandbox_logs_accept.py +8 -0
- render/public_api/models/stream_task_runs_events_accept.py +8 -0
- render/public_api/models/suspender_added.py +83 -0
- render/public_api/models/suspender_removed.py +83 -0
- render/public_api/models/suspender_type.py +14 -0
- render/public_api/models/sync.py +118 -0
- render/public_api/models/sync_state.py +12 -0
- render/public_api/models/sync_with_cursor.py +74 -0
- render/public_api/models/task.py +97 -0
- render/public_api/models/task_attempt.py +121 -0
- render/public_api/models/task_attempt_details.py +141 -0
- render/public_api/models/task_data_type_1.py +44 -0
- render/public_api/models/task_run.py +168 -0
- render/public_api/models/task_run_details.py +216 -0
- render/public_api/models/task_run_status.py +14 -0
- render/public_api/models/task_run_with_cursor.py +73 -0
- render/public_api/models/task_with_cursor.py +73 -0
- render/public_api/models/team_member.py +102 -0
- render/public_api/models/team_member_role.py +12 -0
- render/public_api/models/team_member_status.py +9 -0
- render/public_api/models/time_series.py +100 -0
- render/public_api/models/time_series_value.py +70 -0
- render/public_api/models/update_env_group_secret_file_body.py +59 -0
- render/public_api/models/update_registry_credential_body.py +85 -0
- render/public_api/models/update_workspace_member_body.py +61 -0
- render/public_api/models/user.py +67 -0
- render/public_api/models/validate_blueprint_request.py +84 -0
- render/public_api/models/validate_blueprint_response.py +105 -0
- render/public_api/models/validation_error.py +88 -0
- render/public_api/models/validation_plan_summary.py +107 -0
- render/public_api/models/web_service_details.py +385 -0
- render/public_api/models/web_service_details_patch.py +270 -0
- render/public_api/models/web_service_details_post.py +354 -0
- render/public_api/models/webhook.py +110 -0
- render/public_api/models/webhook_event.py +115 -0
- render/public_api/models/webhook_event_with_cursor.py +73 -0
- render/public_api/models/webhook_patch_input.py +98 -0
- render/public_api/models/webhook_post_input.py +102 -0
- render/public_api/models/webhook_with_cursor.py +73 -0
- render/public_api/models/workflow.py +163 -0
- render/public_api/models/workflow_create.py +169 -0
- render/public_api/models/workflow_update.py +109 -0
- render/public_api/models/workflow_version.py +95 -0
- render/public_api/models/workflow_version_status.py +13 -0
- render/public_api/models/workflow_version_with_cursor.py +73 -0
- render/public_api/models/workflow_with_cursor.py +73 -0
- render/public_api/models/zero_downtime_redeploy_ended.py +44 -0
- render/public_api/models/zero_downtime_redeploy_started.py +59 -0
- render/public_api/py.typed +1 -0
- render/public_api/types.py +54 -0
- render/py.typed +0 -0
- render/render.py +81 -0
- render/render_async.py +80 -0
- render/version.py +27 -0
- render/workflows/__init__.py +25 -0
- render/workflows/_callback_models.py +194 -0
- render/workflows/_uds_http.py +128 -0
- render/workflows/app.py +263 -0
- render/workflows/cli.py +62 -0
- render/workflows/client.py +354 -0
- render/workflows/context.py +75 -0
- render/workflows/executor.py +86 -0
- render/workflows/runner.py +174 -0
- render/workflows/task.py +348 -0
- render/workflows/tests/__init__.py +0 -0
- render/workflows/tests/test_app.py +343 -0
- render/workflows/tests/test_cli.py +134 -0
- render/workflows/tests/test_client.py +59 -0
- render/workflows/tests/test_context.py +118 -0
- render/workflows/tests/test_end_to_end.py +307 -0
- render/workflows/tests/test_executor.py +221 -0
- render/workflows/tests/test_lazy_imports.py +100 -0
- render/workflows/tests/test_registration.py +293 -0
- render/workflows/tests/test_translate_errors.py +126 -0
- render/workflows/tests/test_uds_http.py +199 -0
- render/workflows/tests/test_version.py +15 -0
- render-1.0.1.dist-info/METADATA +382 -0
- render-1.0.1.dist-info/RECORD +799 -0
- render-1.0.1.dist-info/WHEEL +4 -0
- render-1.0.1.dist-info/entry_points.txt +2 -0
- render-1.0.1.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Unit tests for task registration functionality."""
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from render.workflows.task import (
|
|
7
|
+
Options,
|
|
8
|
+
Retry,
|
|
9
|
+
TaskRegistry,
|
|
10
|
+
create_task_decorator,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Fixtures
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def task_registry():
|
|
17
|
+
"""Create a fresh task registry for each test."""
|
|
18
|
+
return TaskRegistry()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.fixture
|
|
22
|
+
def task_decorator(task_registry):
|
|
23
|
+
"""Create a task decorator bound to the test registry."""
|
|
24
|
+
return create_task_decorator(task_registry)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Task Registration Tests
|
|
28
|
+
def test_basic_task_registration(task_registry, task_decorator):
|
|
29
|
+
"""Test that basic tasks are registered correctly."""
|
|
30
|
+
|
|
31
|
+
@task_decorator
|
|
32
|
+
def simple_task(ctx, x: int) -> int:
|
|
33
|
+
return x * 2
|
|
34
|
+
|
|
35
|
+
# Verify task is registered
|
|
36
|
+
task_names = task_registry.get_task_names()
|
|
37
|
+
assert "simple_task" in task_names
|
|
38
|
+
assert len(task_names) == 1
|
|
39
|
+
|
|
40
|
+
# Verify task info
|
|
41
|
+
task_info = task_registry.get_task("simple_task")
|
|
42
|
+
assert task_info is not None
|
|
43
|
+
assert task_info.func.__name__ == "simple_task"
|
|
44
|
+
# Tasks always get an Options object, but with retry=None when no options provided
|
|
45
|
+
if task_info.options:
|
|
46
|
+
assert task_info.options.retry is None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_context_parameter_is_not_a_declared_input(task_registry, task_decorator):
|
|
50
|
+
"""The leading context is supplied by the runtime, not by the caller."""
|
|
51
|
+
|
|
52
|
+
@task_decorator
|
|
53
|
+
def simple_task(ctx, x: int, flag: bool = False) -> int:
|
|
54
|
+
return x * 2
|
|
55
|
+
|
|
56
|
+
task_info = task_registry.get_task("simple_task")
|
|
57
|
+
assert [p.name for p in task_info.parameters] == ["x", "flag"]
|
|
58
|
+
assert [p.type_hint for p in task_info.parameters] == ["int", "bool"]
|
|
59
|
+
assert [p.has_default for p in task_info.parameters] == [False, True]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_task_with_only_a_context_has_no_declared_inputs(task_registry, task_decorator):
|
|
63
|
+
"""A task that takes nothing but the context registers zero parameters."""
|
|
64
|
+
|
|
65
|
+
@task_decorator
|
|
66
|
+
def ping(ctx) -> str:
|
|
67
|
+
return "pong"
|
|
68
|
+
|
|
69
|
+
assert task_registry.get_task("ping").parameters == []
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_task_without_a_context_parameter_is_rejected(task_decorator):
|
|
73
|
+
"""A task must be able to receive a context as its first argument."""
|
|
74
|
+
|
|
75
|
+
with pytest.raises(ValueError, match="must accept a TaskContext"):
|
|
76
|
+
|
|
77
|
+
@task_decorator
|
|
78
|
+
def no_context() -> int:
|
|
79
|
+
return 1
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_task_with_keyword_only_first_parameter_is_rejected(task_decorator):
|
|
83
|
+
"""The context is passed positionally, so it cannot be keyword-only."""
|
|
84
|
+
|
|
85
|
+
with pytest.raises(ValueError, match="keyword-only"):
|
|
86
|
+
|
|
87
|
+
@task_decorator
|
|
88
|
+
def keyword_only(*, ctx) -> int:
|
|
89
|
+
return 1
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_definition_exposes_the_function_for_in_process_invocation(task_decorator):
|
|
93
|
+
"""A definition hands back the undecorated function for direct calls."""
|
|
94
|
+
|
|
95
|
+
@task_decorator
|
|
96
|
+
def square(ctx, a: int) -> int:
|
|
97
|
+
return a * a
|
|
98
|
+
|
|
99
|
+
assert square.func(object(), 5) == 25
|
|
100
|
+
assert square.name == "square"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_function_attributes_do_not_overwrite_definition_fields(task_decorator):
|
|
104
|
+
"""
|
|
105
|
+
A function carrying its own `name` attribute must not clobber the task name.
|
|
106
|
+
|
|
107
|
+
functools.update_wrapper copies the function's __dict__ over the definition,
|
|
108
|
+
so the definition's own fields have to be assigned after it runs. This test
|
|
109
|
+
pins that ordering.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def tagged(ctx, a: int) -> int:
|
|
113
|
+
return a
|
|
114
|
+
|
|
115
|
+
tagged.name = "attribute-from-the-function"
|
|
116
|
+
tagged.func = "also-not-ours"
|
|
117
|
+
|
|
118
|
+
definition = task_decorator(tagged)
|
|
119
|
+
|
|
120
|
+
assert definition.name == "tagged"
|
|
121
|
+
assert definition.func is tagged
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_definition_is_not_callable(task_decorator):
|
|
125
|
+
"""Running a task goes through a context, so a definition is inert."""
|
|
126
|
+
|
|
127
|
+
@task_decorator
|
|
128
|
+
def square(ctx, a: int) -> int:
|
|
129
|
+
return a * a
|
|
130
|
+
|
|
131
|
+
assert not callable(square)
|
|
132
|
+
with pytest.raises(TypeError):
|
|
133
|
+
square(object(), 5)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_custom_name_registration(task_registry, task_decorator):
|
|
137
|
+
"""Test task registration with custom name."""
|
|
138
|
+
|
|
139
|
+
@task_decorator(name="custom_name")
|
|
140
|
+
def original_function(ctx, data: str) -> str:
|
|
141
|
+
return data.upper()
|
|
142
|
+
|
|
143
|
+
# Verify custom name is used
|
|
144
|
+
task_names = task_registry.get_task_names()
|
|
145
|
+
assert "custom_name" in task_names
|
|
146
|
+
assert "original_function" not in task_names
|
|
147
|
+
|
|
148
|
+
task_info = task_registry.get_task("custom_name")
|
|
149
|
+
assert task_info.func.__name__ == "original_function"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_duplicate_task_registration(task_registry, task_decorator):
|
|
153
|
+
"""Test that duplicate task registration raises an error."""
|
|
154
|
+
|
|
155
|
+
@task_decorator
|
|
156
|
+
def duplicate_task(ctx, value: int) -> int:
|
|
157
|
+
return value + 1
|
|
158
|
+
|
|
159
|
+
with pytest.raises(ValueError, match="Task 'duplicate_task' already registered"):
|
|
160
|
+
|
|
161
|
+
@task_decorator
|
|
162
|
+
def duplicate_task(ctx, value: int) -> int: # noqa: F811
|
|
163
|
+
return value + 2
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_task_registration_with_options_object():
|
|
167
|
+
"""Test task registration with different Options configurations."""
|
|
168
|
+
registry = TaskRegistry()
|
|
169
|
+
task_decorator = create_task_decorator(registry)
|
|
170
|
+
|
|
171
|
+
# Task with None options
|
|
172
|
+
@task_decorator(options=None)
|
|
173
|
+
def task_with_none_options(ctx, x: int) -> int:
|
|
174
|
+
return x
|
|
175
|
+
|
|
176
|
+
# Task with empty options
|
|
177
|
+
@task_decorator(options=Options())
|
|
178
|
+
def task_with_empty_options(ctx, x: int) -> int:
|
|
179
|
+
return x
|
|
180
|
+
|
|
181
|
+
# Task with only retry options
|
|
182
|
+
@task_decorator(
|
|
183
|
+
options=Options(
|
|
184
|
+
retry=Retry(max_retries=1, wait_duration_ms=500, backoff_scaling=1.0)
|
|
185
|
+
),
|
|
186
|
+
)
|
|
187
|
+
def task_with_retry_only(ctx, x: int) -> int:
|
|
188
|
+
return x
|
|
189
|
+
|
|
190
|
+
# Verify all tasks registered correctly
|
|
191
|
+
task_names = registry.get_task_names()
|
|
192
|
+
assert len(task_names) == 3
|
|
193
|
+
|
|
194
|
+
# Verify options are handled correctly
|
|
195
|
+
none_task = registry.get_task("task_with_none_options")
|
|
196
|
+
assert none_task.options is not None # Always gets an Options object
|
|
197
|
+
assert none_task.options.retry is None
|
|
198
|
+
|
|
199
|
+
empty_task = registry.get_task("task_with_empty_options")
|
|
200
|
+
assert empty_task.options is not None
|
|
201
|
+
assert empty_task.options.retry is None
|
|
202
|
+
|
|
203
|
+
retry_task = registry.get_task("task_with_retry_only")
|
|
204
|
+
assert retry_task.options is not None
|
|
205
|
+
assert retry_task.options.retry is not None
|
|
206
|
+
assert retry_task.options.retry.max_retries == 1
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def test_options_coerces_dict_retry_to_retry():
|
|
210
|
+
"""
|
|
211
|
+
Test that Options.__post_init__ coerces a dict retry config to a Retry instance.
|
|
212
|
+
"""
|
|
213
|
+
options = Options(
|
|
214
|
+
retry={"max_retries": 5, "wait_duration_ms": 2000, "backoff_scaling": 2.0}
|
|
215
|
+
)
|
|
216
|
+
assert isinstance(options.retry, Retry)
|
|
217
|
+
assert options.retry.max_retries == 5
|
|
218
|
+
assert options.retry.wait_duration_ms == 2000
|
|
219
|
+
assert options.retry.backoff_scaling == 2.0
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def test_options_rejects_incomplete_dict_retry():
|
|
223
|
+
"""Test that dict-to-Retry coercion raises KeyError for missing required keys."""
|
|
224
|
+
with pytest.raises(KeyError):
|
|
225
|
+
Options(retry={})
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def test_task_registration_preserves_function_attributes(task_registry, task_decorator):
|
|
229
|
+
"""Test that task registration preserves original function attributes."""
|
|
230
|
+
|
|
231
|
+
@task_decorator
|
|
232
|
+
def documented_task(ctx, x: int) -> int:
|
|
233
|
+
"""This is a documented function."""
|
|
234
|
+
return x * 3
|
|
235
|
+
|
|
236
|
+
# Verify the original function attributes are preserved
|
|
237
|
+
assert documented_task.__name__ == "documented_task"
|
|
238
|
+
assert documented_task.__doc__ == "This is a documented function."
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def test_task_registration_with_timeout_seconds():
|
|
242
|
+
"""Test task registration with timeout_seconds option."""
|
|
243
|
+
registry = TaskRegistry()
|
|
244
|
+
task_decorator = create_task_decorator(registry)
|
|
245
|
+
|
|
246
|
+
# Task with timeout_seconds
|
|
247
|
+
@task_decorator(options=Options(timeout_seconds=120))
|
|
248
|
+
def task_with_timeout(ctx, x: int) -> int:
|
|
249
|
+
return x
|
|
250
|
+
|
|
251
|
+
# Verify task registered correctly
|
|
252
|
+
task_names = registry.get_task_names()
|
|
253
|
+
assert "task_with_timeout" in task_names
|
|
254
|
+
|
|
255
|
+
# Verify timeout_seconds is set
|
|
256
|
+
task_info = registry.get_task("task_with_timeout")
|
|
257
|
+
assert task_info.options is not None
|
|
258
|
+
assert task_info.options.timeout_seconds == 120
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def test_task_registration_without_timeout_seconds():
|
|
262
|
+
"""Test task registration without timeout_seconds defaults to None."""
|
|
263
|
+
registry = TaskRegistry()
|
|
264
|
+
task_decorator = create_task_decorator(registry)
|
|
265
|
+
|
|
266
|
+
@task_decorator
|
|
267
|
+
def task_without_timeout(ctx, x: int) -> int:
|
|
268
|
+
return x
|
|
269
|
+
|
|
270
|
+
task_info = registry.get_task("task_without_timeout")
|
|
271
|
+
assert task_info.options is not None
|
|
272
|
+
assert task_info.options.timeout_seconds is None
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def test_task_registration_with_timeout_and_retry():
|
|
276
|
+
"""Test task registration with both timeout_seconds and retry options."""
|
|
277
|
+
registry = TaskRegistry()
|
|
278
|
+
task_decorator = create_task_decorator(registry)
|
|
279
|
+
|
|
280
|
+
@task_decorator(
|
|
281
|
+
options=Options(
|
|
282
|
+
timeout_seconds=300,
|
|
283
|
+
retry=Retry(max_retries=3, wait_duration_ms=1000, backoff_scaling=2.0),
|
|
284
|
+
)
|
|
285
|
+
)
|
|
286
|
+
def task_with_both(ctx, x: int) -> int:
|
|
287
|
+
return x
|
|
288
|
+
|
|
289
|
+
task_info = registry.get_task("task_with_both")
|
|
290
|
+
assert task_info.options is not None
|
|
291
|
+
assert task_info.options.timeout_seconds == 300
|
|
292
|
+
assert task_info.options.retry is not None
|
|
293
|
+
assert task_info.options.retry.max_retries == 3
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Unit tests for the ``_translate_errors`` decorator in client.py."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import http.client
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from render.client.errors import (
|
|
11
|
+
ClientError,
|
|
12
|
+
RateLimitError,
|
|
13
|
+
RenderError,
|
|
14
|
+
ServerError,
|
|
15
|
+
)
|
|
16
|
+
from render.client.errors import TimeoutError as SdkTimeoutError
|
|
17
|
+
from render.workflows._uds_http import HttpStatusError
|
|
18
|
+
from render.workflows.client import _translate_errors
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _wrap_raises(operation: str, exc: BaseException):
|
|
22
|
+
"""Build a ``_translate_errors``-decorated coroutine that raises ``exc``."""
|
|
23
|
+
|
|
24
|
+
@_translate_errors(operation)
|
|
25
|
+
async def fn():
|
|
26
|
+
raise exc
|
|
27
|
+
|
|
28
|
+
return fn
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.asyncio
|
|
32
|
+
async def test_builtin_timeout_becomes_sdk_timeout():
|
|
33
|
+
fn = _wrap_raises("get input", TimeoutError("read timed out"))
|
|
34
|
+
with pytest.raises(SdkTimeoutError) as exc_info:
|
|
35
|
+
await fn()
|
|
36
|
+
assert "get input timed out" in str(exc_info.value)
|
|
37
|
+
assert "read timed out" in str(exc_info.value)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.asyncio
|
|
41
|
+
async def test_connection_refused_becomes_server_error():
|
|
42
|
+
fn = _wrap_raises("get input", ConnectionRefusedError("no such file"))
|
|
43
|
+
with pytest.raises(ServerError) as exc_info:
|
|
44
|
+
await fn()
|
|
45
|
+
assert "get input failed to connect" in str(exc_info.value)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@pytest.mark.asyncio
|
|
49
|
+
async def test_file_not_found_becomes_server_error():
|
|
50
|
+
fn = _wrap_raises("get input", FileNotFoundError("missing socket"))
|
|
51
|
+
with pytest.raises(ServerError):
|
|
52
|
+
await fn()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@pytest.mark.asyncio
|
|
56
|
+
async def test_generic_oserror_becomes_server_error():
|
|
57
|
+
fn = _wrap_raises("get input", OSError("network blip"))
|
|
58
|
+
with pytest.raises(ServerError) as exc_info:
|
|
59
|
+
await fn()
|
|
60
|
+
assert "get input network error" in str(exc_info.value)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@pytest.mark.asyncio
|
|
64
|
+
async def test_http_exception_becomes_server_error():
|
|
65
|
+
fn = _wrap_raises("get input", http.client.BadStatusLine("garbled\r\n"))
|
|
66
|
+
with pytest.raises(ServerError) as exc_info:
|
|
67
|
+
await fn()
|
|
68
|
+
assert "get input got invalid HTTP response" in str(exc_info.value)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.mark.asyncio
|
|
72
|
+
async def test_4xx_status_becomes_client_error():
|
|
73
|
+
fn = _wrap_raises("run subtask", HttpStatusError(400, b'{"message": "bad input"}'))
|
|
74
|
+
with pytest.raises(ClientError) as exc_info:
|
|
75
|
+
await fn()
|
|
76
|
+
msg = str(exc_info.value)
|
|
77
|
+
assert "run subtask failed with status 400" in msg
|
|
78
|
+
assert "bad input" in msg
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@pytest.mark.asyncio
|
|
82
|
+
async def test_429_status_becomes_rate_limit_error():
|
|
83
|
+
fn = _wrap_raises("get input", HttpStatusError(429, b""))
|
|
84
|
+
with pytest.raises(RateLimitError) as exc_info:
|
|
85
|
+
await fn()
|
|
86
|
+
assert "429" in str(exc_info.value)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@pytest.mark.asyncio
|
|
90
|
+
async def test_5xx_status_becomes_server_error():
|
|
91
|
+
fn = _wrap_raises("get input", HttpStatusError(503, b'{"error": "boom"}'))
|
|
92
|
+
with pytest.raises(ServerError) as exc_info:
|
|
93
|
+
await fn()
|
|
94
|
+
msg = str(exc_info.value)
|
|
95
|
+
assert "503" in msg
|
|
96
|
+
assert "boom" in msg
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@pytest.mark.asyncio
|
|
100
|
+
async def test_status_error_with_non_json_body_uses_raw_text():
|
|
101
|
+
fn = _wrap_raises("get input", HttpStatusError(503, b"raw error string"))
|
|
102
|
+
with pytest.raises(ServerError) as exc_info:
|
|
103
|
+
await fn()
|
|
104
|
+
assert "raw error string" in str(exc_info.value)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@pytest.mark.asyncio
|
|
108
|
+
async def test_json_decode_error_becomes_render_error():
|
|
109
|
+
fn = _wrap_raises("get input", json.JSONDecodeError("expecting value", "doc", 0))
|
|
110
|
+
with pytest.raises(RenderError) as exc_info:
|
|
111
|
+
await fn()
|
|
112
|
+
msg = str(exc_info.value)
|
|
113
|
+
assert "get input failed" in msg
|
|
114
|
+
assert "non-JSON response" in msg
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@pytest.mark.asyncio
|
|
118
|
+
async def test_render_error_propagates_unchanged():
|
|
119
|
+
"""RenderError subclasses raised inside the wrapped function (e.g.,
|
|
120
|
+
a method's own "unexpected response shape" guard) pass through with
|
|
121
|
+
their original identity — no re-wrapping."""
|
|
122
|
+
original = ClientError("already typed")
|
|
123
|
+
fn = _wrap_raises("op", original)
|
|
124
|
+
with pytest.raises(ClientError) as exc_info:
|
|
125
|
+
await fn()
|
|
126
|
+
assert exc_info.value is original
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""Integration tests for the hand-rolled UDS HTTP transport.
|
|
2
|
+
|
|
3
|
+
These tests bring up a real ``aiohttp`` server bound to a Unix Domain
|
|
4
|
+
Socket so they exercise the actual ``http.client``-based transport
|
|
5
|
+
end-to-end against a real socket.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import tempfile
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
16
|
+
from aiohttp import web
|
|
17
|
+
|
|
18
|
+
from render.workflows._uds_http import HttpStatusError, request_json
|
|
19
|
+
|
|
20
|
+
# Note: we deliberately do NOT import ``TimeoutError`` from
|
|
21
|
+
# render.client.errors here, so the built-in ``TimeoutError`` stays
|
|
22
|
+
# in scope for the timeout assertion below (socket.timeout aliases it).
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture
|
|
26
|
+
def socket_path(tmp_path):
|
|
27
|
+
"""Returns a path suitable for binding a UDS server to."""
|
|
28
|
+
# tmp_path can be longer than the OS-level UDS path limit (~104 chars on
|
|
29
|
+
# macOS), so fall back to a short path under /tmp when needed.
|
|
30
|
+
candidate = str(tmp_path / "render-sdk-test.sock")
|
|
31
|
+
if len(candidate) >= 100:
|
|
32
|
+
with tempfile.NamedTemporaryFile(
|
|
33
|
+
prefix="render-sdk-", suffix=".sock", delete=True
|
|
34
|
+
) as f:
|
|
35
|
+
candidate = f.name
|
|
36
|
+
if os.path.exists(candidate):
|
|
37
|
+
os.unlink(candidate)
|
|
38
|
+
return candidate
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def _start_server(handler, socket_path: str) -> web.AppRunner:
|
|
42
|
+
app = web.Application()
|
|
43
|
+
app.router.add_route("*", "/{tail:.*}", handler)
|
|
44
|
+
runner = web.AppRunner(app)
|
|
45
|
+
await runner.setup()
|
|
46
|
+
site = web.UnixSite(runner, socket_path)
|
|
47
|
+
await site.start()
|
|
48
|
+
return runner
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.mark.asyncio
|
|
52
|
+
async def test_request_json_get_returns_parsed_body(socket_path):
|
|
53
|
+
async def handler(request: web.Request) -> web.Response:
|
|
54
|
+
assert request.method == "GET"
|
|
55
|
+
assert request.path == "/input"
|
|
56
|
+
return web.json_response({"task_name": "t", "input": "blob"})
|
|
57
|
+
|
|
58
|
+
runner = await _start_server(handler, socket_path)
|
|
59
|
+
try:
|
|
60
|
+
result = await request_json(
|
|
61
|
+
socket_path,
|
|
62
|
+
"GET",
|
|
63
|
+
"/input",
|
|
64
|
+
body=None,
|
|
65
|
+
user_agent="test",
|
|
66
|
+
timeout=5.0,
|
|
67
|
+
)
|
|
68
|
+
assert result == {"task_name": "t", "input": "blob"}
|
|
69
|
+
finally:
|
|
70
|
+
await runner.cleanup()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@pytest.mark.asyncio
|
|
74
|
+
async def test_request_json_post_sends_json_body(socket_path):
|
|
75
|
+
received: dict = {}
|
|
76
|
+
|
|
77
|
+
async def handler(request: web.Request) -> web.Response:
|
|
78
|
+
received["method"] = request.method
|
|
79
|
+
received["path"] = request.path
|
|
80
|
+
received["content_type"] = request.headers.get("Content-Type")
|
|
81
|
+
received["body"] = await request.json()
|
|
82
|
+
return web.json_response({"task_run_id": "tr-1"})
|
|
83
|
+
|
|
84
|
+
runner = await _start_server(handler, socket_path)
|
|
85
|
+
try:
|
|
86
|
+
result = await request_json(
|
|
87
|
+
socket_path,
|
|
88
|
+
"POST",
|
|
89
|
+
"/run-subtask",
|
|
90
|
+
body={"task_name": "x", "input": "y"},
|
|
91
|
+
user_agent="test",
|
|
92
|
+
timeout=5.0,
|
|
93
|
+
)
|
|
94
|
+
assert result == {"task_run_id": "tr-1"}
|
|
95
|
+
assert received["method"] == "POST"
|
|
96
|
+
assert received["path"] == "/run-subtask"
|
|
97
|
+
assert received["content_type"] == "application/json"
|
|
98
|
+
assert received["body"] == {"task_name": "x", "input": "y"}
|
|
99
|
+
finally:
|
|
100
|
+
await runner.cleanup()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@pytest.mark.asyncio
|
|
104
|
+
async def test_request_json_empty_response_returns_none(socket_path):
|
|
105
|
+
async def handler(request: web.Request) -> web.Response:
|
|
106
|
+
return web.Response(status=200, body=b"")
|
|
107
|
+
|
|
108
|
+
runner = await _start_server(handler, socket_path)
|
|
109
|
+
try:
|
|
110
|
+
result = await request_json(
|
|
111
|
+
socket_path,
|
|
112
|
+
"POST",
|
|
113
|
+
"/callback",
|
|
114
|
+
body={"complete": {"output": "ok"}},
|
|
115
|
+
user_agent="test",
|
|
116
|
+
timeout=5.0,
|
|
117
|
+
)
|
|
118
|
+
assert result is None
|
|
119
|
+
finally:
|
|
120
|
+
await runner.cleanup()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@pytest.mark.asyncio
|
|
124
|
+
async def test_request_json_error_status_raises_http_status_error(socket_path):
|
|
125
|
+
async def handler(request: web.Request) -> web.Response:
|
|
126
|
+
return web.json_response({"message": "bad input"}, status=400)
|
|
127
|
+
|
|
128
|
+
runner = await _start_server(handler, socket_path)
|
|
129
|
+
try:
|
|
130
|
+
with pytest.raises(HttpStatusError) as exc_info:
|
|
131
|
+
await request_json(
|
|
132
|
+
socket_path,
|
|
133
|
+
"POST",
|
|
134
|
+
"/run-subtask",
|
|
135
|
+
body={},
|
|
136
|
+
user_agent="test",
|
|
137
|
+
timeout=5.0,
|
|
138
|
+
)
|
|
139
|
+
assert exc_info.value.status == 400
|
|
140
|
+
assert b"bad input" in exc_info.value.body
|
|
141
|
+
finally:
|
|
142
|
+
await runner.cleanup()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@pytest.mark.asyncio
|
|
146
|
+
async def test_request_json_connection_refused_raises_oserror():
|
|
147
|
+
# Path that doesn't exist -> connection refused / no such file. The
|
|
148
|
+
# transport propagates the OSError unchanged; translation is the
|
|
149
|
+
# caller's responsibility.
|
|
150
|
+
with pytest.raises((ConnectionError, FileNotFoundError)):
|
|
151
|
+
await request_json(
|
|
152
|
+
"/tmp/does-not-exist-render-sdk.sock", # noqa: S108
|
|
153
|
+
"GET",
|
|
154
|
+
"/input",
|
|
155
|
+
body=None,
|
|
156
|
+
user_agent="test",
|
|
157
|
+
timeout=5.0,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@pytest.mark.asyncio
|
|
162
|
+
async def test_request_json_non_json_body_raises_json_decode_error(socket_path):
|
|
163
|
+
async def handler(request: web.Request) -> web.Response:
|
|
164
|
+
return web.Response(status=200, body=b"not json", content_type="text/plain")
|
|
165
|
+
|
|
166
|
+
runner = await _start_server(handler, socket_path)
|
|
167
|
+
try:
|
|
168
|
+
with pytest.raises(json.JSONDecodeError):
|
|
169
|
+
await request_json(
|
|
170
|
+
socket_path,
|
|
171
|
+
"GET",
|
|
172
|
+
"/input",
|
|
173
|
+
body=None,
|
|
174
|
+
user_agent="test",
|
|
175
|
+
timeout=5.0,
|
|
176
|
+
)
|
|
177
|
+
finally:
|
|
178
|
+
await runner.cleanup()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@pytest.mark.asyncio
|
|
182
|
+
async def test_request_json_timeout_raises_timeout_error(socket_path):
|
|
183
|
+
async def handler(request: web.Request) -> web.Response:
|
|
184
|
+
await asyncio.sleep(2.0)
|
|
185
|
+
return web.json_response({})
|
|
186
|
+
|
|
187
|
+
runner = await _start_server(handler, socket_path)
|
|
188
|
+
try:
|
|
189
|
+
with pytest.raises(TimeoutError):
|
|
190
|
+
await request_json(
|
|
191
|
+
socket_path,
|
|
192
|
+
"GET",
|
|
193
|
+
"/input",
|
|
194
|
+
body=None,
|
|
195
|
+
user_agent="test",
|
|
196
|
+
timeout=0.2,
|
|
197
|
+
)
|
|
198
|
+
finally:
|
|
199
|
+
await runner.cleanup()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Guard against version drift between render.__version__ and pyproject.toml.
|
|
2
|
+
|
|
3
|
+
The two values are maintained separately and once diverged for months
|
|
4
|
+
(__version__ reported 0.8.0 while the distribution was published as 1.0.0).
|
|
5
|
+
importlib.metadata reads the installed dist-info, which comes from
|
|
6
|
+
pyproject.toml, so this test fails whenever one is bumped without the other.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import importlib.metadata
|
|
10
|
+
|
|
11
|
+
import render
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_version_matches_distribution_metadata() -> None:
|
|
15
|
+
assert render.__version__ == importlib.metadata.version("render")
|