render_sdk 0.1.2__py3-none-any.whl → 0.2.0__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 (156) hide show
  1. render_sdk/__init__.py +41 -4
  2. render_sdk/client/__init__.py +25 -0
  3. render_sdk/client/client.py +5 -0
  4. render_sdk/client/sse.py +5 -1
  5. render_sdk/client/tests/test_client.py +6 -4
  6. render_sdk/client/tests/test_sse.py +1 -0
  7. render_sdk/client/types.py +2 -1
  8. render_sdk/client/workflows.py +13 -3
  9. render_sdk/experimental/__init__.py +31 -0
  10. render_sdk/experimental/experimental.py +71 -0
  11. render_sdk/experimental/object/__init__.py +30 -0
  12. render_sdk/experimental/object/api.py +260 -0
  13. render_sdk/experimental/object/client.py +475 -0
  14. render_sdk/experimental/object/types.py +87 -0
  15. render_sdk/public_api/api/audit_logs/list_organization_audit_logs.py +303 -0
  16. render_sdk/public_api/api/audit_logs/list_owner_audit_logs.py +303 -0
  17. render_sdk/public_api/api/blob_storage/delete_blob.py +215 -0
  18. render_sdk/public_api/api/blob_storage/get_blob.py +221 -0
  19. render_sdk/public_api/api/{workflows/list_workflow_versions.py → blob_storage/list_blobs.py} +52 -30
  20. render_sdk/public_api/api/blob_storage/put_blob.py +248 -0
  21. render_sdk/public_api/api/blueprints/validate_blueprint.py +212 -0
  22. render_sdk/public_api/api/key_value/resume_key_value.py +203 -0
  23. render_sdk/public_api/api/key_value/suspend_key_value.py +203 -0
  24. render_sdk/public_api/api/metrics/get_bandwidth_sources.py +251 -0
  25. render_sdk/public_api/api/postgres/create_postgres_user.py +229 -0
  26. render_sdk/public_api/api/postgres/delete_postgres_user.py +201 -0
  27. render_sdk/public_api/api/postgres/list_postgres_users.py +195 -0
  28. render_sdk/public_api/api/redis_deprecated/__init__.py +1 -0
  29. render_sdk/public_api/api/{redis → redis_deprecated}/create_redis.py +4 -4
  30. render_sdk/public_api/api/{redis → redis_deprecated}/delete_redis.py +4 -4
  31. render_sdk/public_api/api/{redis → redis_deprecated}/list_redis.py +4 -0
  32. render_sdk/public_api/api/{redis → redis_deprecated}/retrieve_redis.py +4 -4
  33. render_sdk/public_api/api/{redis → redis_deprecated}/retrieve_redis_connection_info.py +4 -0
  34. render_sdk/public_api/api/{redis → redis_deprecated}/update_redis.py +4 -4
  35. render_sdk/public_api/api/services/create_service.py +4 -4
  36. render_sdk/public_api/api/workflow_tasks_ea/__init__.py +1 -0
  37. render_sdk/public_api/api/{workflows → workflow_tasks_ea}/cancel_task_run.py +12 -4
  38. render_sdk/public_api/api/{workflows → workflow_tasks_ea}/create_task.py +12 -4
  39. render_sdk/public_api/api/{workflows → workflow_tasks_ea}/get_task.py +12 -4
  40. render_sdk/public_api/api/{workflows → workflow_tasks_ea}/get_task_run.py +12 -4
  41. render_sdk/public_api/api/{workflows → workflow_tasks_ea}/list_task_runs.py +12 -0
  42. render_sdk/public_api/api/{workflows → workflow_tasks_ea}/list_tasks.py +24 -12
  43. render_sdk/public_api/api/workflows_ea/__init__.py +1 -0
  44. render_sdk/public_api/api/workflows_ea/create_workflow.py +199 -0
  45. render_sdk/public_api/api/{workflows/deploy_workflow.py → workflows_ea/create_workflow_version.py} +31 -14
  46. render_sdk/public_api/api/{workflows → workflows_ea}/delete_workflow.py +12 -4
  47. render_sdk/public_api/api/{workflows → workflows_ea}/get_workflow.py +32 -14
  48. render_sdk/public_api/api/{workflows → workflows_ea}/get_workflow_version.py +12 -4
  49. render_sdk/public_api/api/workflows_ea/list_workflow_versions.py +275 -0
  50. render_sdk/public_api/api/{workflows → workflows_ea}/list_workflows.py +41 -14
  51. render_sdk/public_api/api/workflows_ea/update_workflow.py +212 -0
  52. render_sdk/public_api/api/workspaces/remove_workspace_member.py +206 -0
  53. render_sdk/public_api/api/workspaces/update_workspace_member.py +235 -0
  54. render_sdk/public_api/models/__init__.py +82 -4
  55. render_sdk/public_api/models/audit_log.py +113 -0
  56. render_sdk/public_api/models/audit_log_actor.py +80 -0
  57. render_sdk/public_api/models/audit_log_actor_type.py +10 -0
  58. render_sdk/public_api/models/audit_log_event.py +80 -0
  59. render_sdk/public_api/models/audit_log_metadata.py +49 -0
  60. render_sdk/public_api/models/audit_log_status.py +9 -0
  61. render_sdk/public_api/models/audit_log_with_cursor.py +73 -0
  62. render_sdk/public_api/models/background_worker_details.py +2 -2
  63. render_sdk/public_api/models/background_worker_details_patch.py +1 -1
  64. render_sdk/public_api/models/background_worker_details_post.py +1 -1
  65. render_sdk/public_api/models/blob_metadata.py +85 -0
  66. render_sdk/public_api/models/blob_with_cursor.py +73 -0
  67. render_sdk/public_api/models/cache.py +6 -4
  68. render_sdk/public_api/models/cache_profile.py +10 -0
  69. render_sdk/public_api/models/create_deploy_body.py +23 -0
  70. render_sdk/public_api/models/create_version.py +70 -0
  71. render_sdk/public_api/models/credential_create_input.py +59 -0
  72. render_sdk/public_api/models/cron_job_details.py +2 -2
  73. render_sdk/public_api/models/cron_job_details_patch.py +1 -1
  74. render_sdk/public_api/models/cron_job_details_post.py +1 -1
  75. render_sdk/public_api/models/deploy_mode.py +9 -0
  76. render_sdk/public_api/models/event.py +11 -27
  77. render_sdk/public_api/models/event_type.py +1 -1
  78. render_sdk/public_api/models/get_bandwidth_sources_response_200.py +75 -0
  79. render_sdk/public_api/models/get_bandwidth_sources_response_200_data_item.py +101 -0
  80. render_sdk/public_api/models/get_bandwidth_sources_response_200_data_item_labels.py +78 -0
  81. render_sdk/public_api/models/get_bandwidth_sources_response_200_data_item_labels_traffic_source.py +12 -0
  82. render_sdk/public_api/models/get_bandwidth_sources_response_200_data_item_values_item.py +68 -0
  83. render_sdk/public_api/models/{server_unhealthy.py → get_bandwidth_sources_response_400.py} +12 -12
  84. render_sdk/public_api/models/get_blob_output.py +71 -0
  85. render_sdk/public_api/models/list_postgres_users_response_200_item.py +86 -0
  86. render_sdk/public_api/models/otel_provider_type.py +2 -0
  87. render_sdk/public_api/models/postgres.py +8 -0
  88. render_sdk/public_api/models/postgres_detail.py +26 -0
  89. render_sdk/public_api/models/postgres_parameter_overrides.py +44 -0
  90. render_sdk/public_api/models/postgres_patch_input.py +27 -0
  91. render_sdk/public_api/models/postgres_post_input.py +27 -0
  92. render_sdk/public_api/models/postgres_version.py +1 -0
  93. render_sdk/public_api/models/preview_input.py +2 -2
  94. render_sdk/public_api/models/private_service_details.py +2 -2
  95. render_sdk/public_api/models/private_service_details_patch.py +1 -1
  96. render_sdk/public_api/models/private_service_details_post.py +1 -1
  97. render_sdk/public_api/models/project_post_environment_input.py +26 -1
  98. render_sdk/public_api/models/put_blob_input.py +59 -0
  99. render_sdk/public_api/models/put_blob_output.py +79 -0
  100. render_sdk/public_api/models/read_replica.py +25 -1
  101. render_sdk/public_api/models/read_replica_input.py +25 -1
  102. render_sdk/public_api/models/run_task.py +35 -7
  103. render_sdk/public_api/models/service_event.py +12 -27
  104. render_sdk/public_api/models/service_event_type.py +0 -1
  105. render_sdk/public_api/models/service_post.py +9 -6
  106. render_sdk/public_api/models/task_attempt.py +88 -0
  107. render_sdk/public_api/models/task_attempt_details.py +108 -0
  108. render_sdk/public_api/models/task_data_type_1.py +44 -0
  109. render_sdk/public_api/models/task_run.py +23 -1
  110. render_sdk/public_api/models/task_run_details.py +50 -5
  111. render_sdk/public_api/models/task_run_status.py +1 -0
  112. render_sdk/public_api/models/task_with_cursor.py +73 -0
  113. render_sdk/public_api/models/team_member.py +5 -4
  114. render_sdk/public_api/models/team_member_role.py +12 -0
  115. render_sdk/public_api/models/update_workspace_member_body.py +61 -0
  116. render_sdk/public_api/models/validate_blueprint_request.py +84 -0
  117. render_sdk/public_api/models/validate_blueprint_response.py +105 -0
  118. render_sdk/public_api/models/validation_error.py +88 -0
  119. render_sdk/public_api/models/validation_plan_summary.py +107 -0
  120. render_sdk/public_api/models/web_service_details.py +2 -2
  121. render_sdk/public_api/models/web_service_details_patch.py +6 -5
  122. render_sdk/public_api/models/web_service_details_post.py +6 -5
  123. render_sdk/public_api/models/workflow.py +144 -0
  124. render_sdk/public_api/models/workflow_create.py +99 -0
  125. render_sdk/public_api/models/workflow_update.py +90 -0
  126. render_sdk/public_api/models/workflow_version.py +10 -14
  127. render_sdk/public_api/models/workflow_version_status.py +13 -0
  128. render_sdk/public_api/models/workflow_version_with_cursor.py +73 -0
  129. render_sdk/public_api/models/workflow_with_cursor.py +73 -0
  130. render_sdk/render.py +65 -0
  131. render_sdk/version.py +27 -0
  132. render_sdk/workflows/__init__.py +5 -1
  133. render_sdk/workflows/app.py +262 -0
  134. render_sdk/workflows/callback_api/models/__init__.py +2 -0
  135. render_sdk/workflows/callback_api/models/task.py +21 -0
  136. render_sdk/workflows/callback_api/models/task_options.py +18 -0
  137. render_sdk/workflows/callback_api/models/task_parameter.py +88 -0
  138. render_sdk/workflows/callback_api/py.typed +1 -1
  139. render_sdk/workflows/cli.py +58 -0
  140. render_sdk/workflows/client.py +8 -9
  141. render_sdk/workflows/executor.py +19 -7
  142. render_sdk/workflows/runner.py +43 -10
  143. render_sdk/workflows/task.py +84 -5
  144. render_sdk/workflows/tests/test_app.py +412 -0
  145. render_sdk/workflows/tests/test_cli.py +134 -0
  146. render_sdk/workflows/tests/test_end_to_end.py +71 -1
  147. render_sdk/workflows/tests/test_registration.py +58 -1
  148. {render_sdk-0.1.2.dist-info → render_sdk-0.2.0.dist-info}/METADATA +4 -3
  149. {render_sdk-0.1.2.dist-info → render_sdk-0.2.0.dist-info}/RECORD +155 -83
  150. {render_sdk-0.1.2.dist-info → render_sdk-0.2.0.dist-info}/WHEEL +1 -1
  151. render_sdk-0.2.0.dist-info/entry_points.txt +3 -0
  152. render_sdk/public_api/models/image_version.py +0 -79
  153. /render_sdk/public_api/api/{redis → audit_logs}/__init__.py +0 -0
  154. /render_sdk/public_api/api/{workflows → blob_storage}/__init__.py +0 -0
  155. /render_sdk/public_api/api/{workflows → workflow_tasks_ea}/stream_task_runs_events.py +0 -0
  156. {render_sdk-0.1.2.dist-info → render_sdk-0.2.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,134 @@
1
+ """Tests for the CLI entrypoint module."""
2
+
3
+ import pytest
4
+
5
+ from render_sdk.workflows import cli
6
+
7
+
8
+ class TestCLIMain:
9
+ """Tests for the main() CLI entrypoint."""
10
+
11
+ def test_no_arguments_shows_usage_and_exits(self, mocker, capsys):
12
+ """Test that running with no arguments shows usage and exits with code 1."""
13
+ mocker.patch("sys.argv", ["render-workflows"])
14
+
15
+ with pytest.raises(SystemExit) as exc_info:
16
+ cli.main()
17
+
18
+ assert exc_info.value.code == 1
19
+ captured = capsys.readouterr()
20
+ assert "Usage: render-workflows <module:app>" in captured.err
21
+ assert "Example: render-workflows myapp:app" in captured.err
22
+
23
+ def test_invalid_format_no_colon_shows_error(self, mocker, capsys):
24
+ """Test that an argument without a colon shows an error."""
25
+ mocker.patch("sys.argv", ["render-workflows", "myapp"])
26
+
27
+ with pytest.raises(SystemExit) as exc_info:
28
+ cli.main()
29
+
30
+ assert exc_info.value.code == 1
31
+ captured = capsys.readouterr()
32
+ assert "Error: Invalid app path 'myapp'" in captured.err
33
+ assert "Expected format: <module>:<app_variable>" in captured.err
34
+
35
+ def test_module_not_found_shows_error(self, mocker, capsys):
36
+ """Test that a non-existent module shows an import error."""
37
+ mocker.patch("sys.argv", ["render-workflows", "nonexistent_module:app"])
38
+
39
+ with pytest.raises(SystemExit) as exc_info:
40
+ cli.main()
41
+
42
+ assert exc_info.value.code == 1
43
+ captured = capsys.readouterr()
44
+ assert "Error: Could not import module 'nonexistent_module'" in captured.err
45
+
46
+ def test_attribute_not_found_shows_error(self, mocker, capsys):
47
+ """Test that a missing attribute shows an error."""
48
+ mocker.patch("sys.argv", ["render-workflows", "os:nonexistent_attr"])
49
+
50
+ with pytest.raises(SystemExit) as exc_info:
51
+ cli.main()
52
+
53
+ assert exc_info.value.code == 1
54
+ captured = capsys.readouterr()
55
+ assert "Error: Module 'os' has no attribute 'nonexistent_attr'" in captured.err
56
+
57
+ def test_object_without_start_method_shows_error(self, mocker, capsys):
58
+ """Test that an object without a start() method shows an error."""
59
+ # os.path is a module, not a Workflows instance
60
+ mocker.patch("sys.argv", ["render-workflows", "os:path"])
61
+
62
+ with pytest.raises(SystemExit) as exc_info:
63
+ cli.main()
64
+
65
+ assert exc_info.value.code == 1
66
+ captured = capsys.readouterr()
67
+ assert "Error: 'path' does not have a start() method" in captured.err
68
+ assert "Expected a Workflows instance" in captured.err
69
+
70
+ def test_valid_app_calls_start(self, mocker):
71
+ """Test that a valid app path calls the app's start() method."""
72
+ # Create a mock app with a start method
73
+ mock_app = mocker.Mock()
74
+ mock_app.start = mocker.Mock()
75
+
76
+ # Create a mock module containing the app
77
+ mock_module = mocker.Mock()
78
+ mock_module.app = mock_app
79
+
80
+ # Patch sys.argv and importlib
81
+ mocker.patch("sys.argv", ["render-workflows", "mymodule:app"])
82
+ mocker.patch("importlib.import_module", return_value=mock_module)
83
+
84
+ # Should not raise
85
+ cli.main()
86
+
87
+ # Verify start() was called
88
+ mock_app.start.assert_called_once()
89
+
90
+ def test_nested_module_path(self, mocker):
91
+ """Test that nested module paths (e.g., 'myproject.tasks:app') work."""
92
+ mock_app = mocker.Mock()
93
+ mock_app.start = mocker.Mock()
94
+
95
+ mock_module = mocker.Mock()
96
+ mock_module.app = mock_app
97
+
98
+ mocker.patch("sys.argv", ["render-workflows", "myproject.tasks.workers:app"])
99
+ mock_import = mocker.patch("importlib.import_module", return_value=mock_module)
100
+
101
+ cli.main()
102
+
103
+ # Verify the full module path was used
104
+ mock_import.assert_called_once_with("myproject.tasks.workers")
105
+ mock_app.start.assert_called_once()
106
+
107
+ def test_colon_in_module_path_uses_last_colon(self, mocker, capsys):
108
+ """Test that multiple colons use rsplit to get the last segment."""
109
+ # This is an edge case: "weird:module:app" should split as
110
+ # module="weird:module", app="app"
111
+ mocker.patch("sys.argv", ["render-workflows", "weird:module:app"])
112
+
113
+ with pytest.raises(SystemExit) as exc_info:
114
+ cli.main()
115
+
116
+ # Should fail on import (module "weird:module" doesn't exist)
117
+ assert exc_info.value.code == 1
118
+ captured = capsys.readouterr()
119
+ assert "Could not import module 'weird:module'" in captured.err
120
+
121
+ def test_import_error_includes_original_message(self, mocker, capsys):
122
+ """Test that import errors include the original exception message."""
123
+ mocker.patch("sys.argv", ["render-workflows", "mymodule:app"])
124
+ mocker.patch(
125
+ "importlib.import_module",
126
+ side_effect=ImportError("No module named 'dependency'"),
127
+ )
128
+
129
+ with pytest.raises(SystemExit) as exc_info:
130
+ cli.main()
131
+
132
+ assert exc_info.value.code == 1
133
+ captured = capsys.readouterr()
134
+ assert "No module named 'dependency'" in captured.err
@@ -70,7 +70,9 @@ def test_task_registration_network_payload(task_registry, task_decorator, mocker
70
70
  return f"Hello {msg}"
71
71
 
72
72
  @task_decorator(
73
- options=Options(retry=Retry(max_retries=3, wait_duration_ms=1000, factor=1.5)),
73
+ options=Options(
74
+ retry=Retry(max_retries=3, wait_duration_ms=1000, backoff_scaling=1.5)
75
+ ),
74
76
  )
75
77
  def retry_task(data: str) -> str:
76
78
  return data.upper()
@@ -120,6 +122,74 @@ def test_task_registration_network_payload(task_registry, task_decorator, mocker
120
122
  assert retry_options.factor == 1.5
121
123
 
122
124
 
125
+ def test_task_registration_with_timeout_seconds(task_registry, task_decorator, mocker):
126
+ """
127
+ Test that task registration correctly serializes timeout_seconds
128
+ in the network payload.
129
+ """
130
+ from render_sdk.workflows.callback_api.types import UNSET
131
+
132
+ # Mock the UDSClient class
133
+ mock_uds_client_class = mocker.patch("render_sdk.workflows.runner.UDSClient")
134
+
135
+ # Set up the mock instance
136
+ mock_client_instance = mocker.Mock()
137
+ mock_uds_client_class.return_value = mock_client_instance
138
+ mock_client_instance.register_tasks = mocker.AsyncMock(
139
+ return_value={"status": "success"},
140
+ )
141
+ mock_client_instance.disconnect = mocker.AsyncMock()
142
+
143
+ # Define a task with timeout_seconds
144
+ @task_decorator(options=Options(timeout_seconds=120))
145
+ def timeout_task(x: int) -> int:
146
+ return x * 2
147
+
148
+ # Define a task without timeout_seconds
149
+ @task_decorator
150
+ def no_timeout_task(x: int) -> int:
151
+ return x * 3
152
+
153
+ # Define a task with both timeout_seconds and retry
154
+ @task_decorator(
155
+ options=Options(
156
+ timeout_seconds=300,
157
+ retry=Retry(max_retries=2, wait_duration_ms=500, backoff_scaling=1.5),
158
+ )
159
+ )
160
+ def timeout_and_retry_task(x: int) -> int:
161
+ return x * 4
162
+
163
+ # Mock get_task_registry to return our test registry
164
+ mock_get_registry = mocker.patch("render_sdk.workflows.runner.get_task_registry")
165
+ mock_get_registry.return_value = task_registry
166
+
167
+ register("/tmp/test.sock") # noqa:S108
168
+
169
+ # Get the actual payload that was sent
170
+ sent_tasks = mock_client_instance.register_tasks.call_args[0][0]
171
+
172
+ # Find tasks by name
173
+ task_by_name = {task.name: task for task in sent_tasks.tasks}
174
+
175
+ # Verify task with timeout_seconds
176
+ assert "timeout_task" in task_by_name
177
+ timeout_task_payload = task_by_name["timeout_task"]
178
+ assert timeout_task_payload.options.timeout_seconds == 120
179
+
180
+ # Verify task without timeout_seconds has UNSET timeout
181
+ assert "no_timeout_task" in task_by_name
182
+ no_timeout_payload = task_by_name["no_timeout_task"]
183
+ assert no_timeout_payload.options.timeout_seconds is UNSET
184
+
185
+ # Verify task with both timeout and retry
186
+ assert "timeout_and_retry_task" in task_by_name
187
+ combined_payload = task_by_name["timeout_and_retry_task"]
188
+ assert combined_payload.options.timeout_seconds == 300
189
+ assert combined_payload.options.retry is not UNSET
190
+ assert combined_payload.options.retry.max_retries == 2
191
+
192
+
123
193
  @pytest.mark.asyncio
124
194
  async def test_callback_payloads_with_mocked_client(
125
195
  task_registry,
@@ -93,7 +93,9 @@ def test_task_registration_with_options_object():
93
93
 
94
94
  # Task with only retry options
95
95
  @task_decorator(
96
- options=Options(retry=Retry(max_retries=1, wait_duration_ms=500, factor=1.0)),
96
+ options=Options(
97
+ retry=Retry(max_retries=1, wait_duration_ms=500, backoff_scaling=1.0)
98
+ ),
97
99
  )
98
100
  def task_with_retry_only(x: int) -> int:
99
101
  return x
@@ -128,3 +130,58 @@ def test_task_registration_preserves_function_attributes(task_registry, task_dec
128
130
  # Verify the original function attributes are preserved
129
131
  assert documented_task.__name__ == "documented_task"
130
132
  assert documented_task.__doc__ == "This is a documented function."
133
+
134
+
135
+ def test_task_registration_with_timeout_seconds():
136
+ """Test task registration with timeout_seconds option."""
137
+ registry = TaskRegistry()
138
+ task_decorator = create_task_decorator(registry)
139
+
140
+ # Task with timeout_seconds
141
+ @task_decorator(options=Options(timeout_seconds=120))
142
+ def task_with_timeout(x: int) -> int:
143
+ return x
144
+
145
+ # Verify task registered correctly
146
+ task_names = registry.get_task_names()
147
+ assert "task_with_timeout" in task_names
148
+
149
+ # Verify timeout_seconds is set
150
+ task_info = registry.get_task("task_with_timeout")
151
+ assert task_info.options is not None
152
+ assert task_info.options.timeout_seconds == 120
153
+
154
+
155
+ def test_task_registration_without_timeout_seconds():
156
+ """Test task registration without timeout_seconds defaults to None."""
157
+ registry = TaskRegistry()
158
+ task_decorator = create_task_decorator(registry)
159
+
160
+ @task_decorator
161
+ def task_without_timeout(x: int) -> int:
162
+ return x
163
+
164
+ task_info = registry.get_task("task_without_timeout")
165
+ assert task_info.options is not None
166
+ assert task_info.options.timeout_seconds is None
167
+
168
+
169
+ def test_task_registration_with_timeout_and_retry():
170
+ """Test task registration with both timeout_seconds and retry options."""
171
+ registry = TaskRegistry()
172
+ task_decorator = create_task_decorator(registry)
173
+
174
+ @task_decorator(
175
+ options=Options(
176
+ timeout_seconds=300,
177
+ retry=Retry(max_retries=3, wait_duration_ms=1000, backoff_scaling=2.0),
178
+ )
179
+ )
180
+ def task_with_both(x: int) -> int:
181
+ return x
182
+
183
+ task_info = registry.get_task("task_with_both")
184
+ assert task_info.options is not None
185
+ assert task_info.options.timeout_seconds == 300
186
+ assert task_info.options.retry is not None
187
+ assert task_info.options.retry.max_retries == 3
@@ -1,7 +1,8 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: render_sdk
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Python SDK for Render Workflows
5
+ License-File: LICENSE
5
6
  Author: Render
6
7
  Author-email: support@render.com
7
8
  Requires-Python: >=3.10,<4.0
@@ -15,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
15
16
  Classifier: Programming Language :: Python :: 3.12
16
17
  Classifier: Programming Language :: Python :: 3.13
17
18
  Classifier: Programming Language :: Python :: 3.14
18
- Requires-Dist: aiohttp (>=3.8.0,<4.0.0)
19
+ Requires-Dist: aiohttp (>=3.12.14,<4.0.0)
19
20
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
20
21
  Requires-Dist: openapi-python-client (>=0.26.1,<0.27.0)
21
22
  Description-Content-Type: text/markdown