wavespeed 1.0.6__tar.gz → 1.0.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. {wavespeed-1.0.6 → wavespeed-1.0.7}/PKG-INFO +1 -1
  2. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/_version.py +1 -1
  3. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/config.py +86 -30
  4. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/fastapi.py +9 -0
  5. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/PKG-INFO +1 -1
  6. wavespeed-1.0.7/tests/test_config.py +84 -0
  7. wavespeed-1.0.6/tests/test_config.py +0 -65
  8. {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/claude-code-review.yml +0 -0
  9. {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/claude.yml +0 -0
  10. {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/pre-commit.yml +0 -0
  11. {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/python-packages.yml +0 -0
  12. {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/python-publish.yml +0 -0
  13. {wavespeed-1.0.6 → wavespeed-1.0.7}/.gitignore +0 -0
  14. {wavespeed-1.0.6 → wavespeed-1.0.7}/.pre-commit-config.yaml +0 -0
  15. {wavespeed-1.0.6 → wavespeed-1.0.7}/CLAUDE.md +0 -0
  16. {wavespeed-1.0.6 → wavespeed-1.0.7}/LICENSE +0 -0
  17. {wavespeed-1.0.6 → wavespeed-1.0.7}/MANIFEST.in +0 -0
  18. {wavespeed-1.0.6 → wavespeed-1.0.7}/README.md +0 -0
  19. {wavespeed-1.0.6 → wavespeed-1.0.7}/VERSIONING.md +0 -0
  20. {wavespeed-1.0.6 → wavespeed-1.0.7}/images/build_and_push.sh +0 -0
  21. {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/Dockerfile +0 -0
  22. {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/build_and_test.sh +0 -0
  23. {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/handler.py +0 -0
  24. {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/requirements.txt +0 -0
  25. {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/test_input.json +0 -0
  26. {wavespeed-1.0.6 → wavespeed-1.0.7}/pyproject.toml +0 -0
  27. {wavespeed-1.0.6 → wavespeed-1.0.7}/pytest.ini +0 -0
  28. {wavespeed-1.0.6 → wavespeed-1.0.7}/setup.cfg +0 -0
  29. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/__init__.py +0 -0
  30. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/_config_module.py +0 -0
  31. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/api/__init__.py +0 -0
  32. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/api/client.py +0 -0
  33. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/__init__.py +0 -0
  34. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/__init__.py +0 -0
  35. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/handler.py +0 -0
  36. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/heartbeat.py +0 -0
  37. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/http.py +0 -0
  38. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/job.py +0 -0
  39. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/local.py +0 -0
  40. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/logger.py +0 -0
  41. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/progress.py +0 -0
  42. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/scaler.py +0 -0
  43. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/state.py +0 -0
  44. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/utils/__init__.py +0 -0
  45. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/utils/boto3_utils.py +0 -0
  46. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/utils/validator.py +0 -0
  47. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/worker.py +0 -0
  48. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/SOURCES.txt +0 -0
  49. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/dependency_links.txt +0 -0
  50. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/not-zip-safe +0 -0
  51. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/requires.txt +0 -0
  52. {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/top_level.txt +0 -0
  53. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/__init__.py +0 -0
  54. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/conftest.py +0 -0
  55. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_api.py +0 -0
  56. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/__init__.py +0 -0
  57. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/__init__.py +0 -0
  58. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_fastapi.py +0 -0
  59. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_handler.py +0 -0
  60. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_http.py +0 -0
  61. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_job.py +0 -0
  62. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_local.py +0 -0
  63. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_logger.py +0 -0
  64. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_progress.py +0 -0
  65. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_scaler.py +0 -0
  66. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_state.py +0 -0
  67. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_utils/__init__.py +0 -0
  68. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_utils/test_validator.py +0 -0
  69. {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavespeed
3
- Version: 1.0.6
3
+ Version: 1.0.7
4
4
  Summary: WaveSpeedAI Python Client — Official Python SDK for WaveSpeedAI inference platform
5
5
  Author-email: WaveSpeedAI <support@wavespeed.ai>
6
6
  License: MIT
@@ -1,2 +1,2 @@
1
1
  # This file is automatically generated by setuptools_scm
2
- __version__ = "1.0.6"
2
+ __version__ = "1.0.7"
@@ -2,6 +2,7 @@
2
2
 
3
3
  import os
4
4
  import sys
5
+ import uuid
5
6
  from typing import Optional
6
7
 
7
8
  from ._config_module import install_config_module
@@ -83,22 +84,41 @@ def _detect_serverless_env() -> Optional[str]:
83
84
  The serverless environment type ("runpod", "waverless") or None
84
85
  if not running in a known serverless environment.
85
86
  """
86
- # Check for RunPod environment
87
- if os.environ.get("RUNPOD_POD_ID"):
88
- return "runpod"
89
87
 
90
88
  # Check for native Waverless environment
91
- if os.environ.get("WAVERLESS_POD_ID"):
89
+ if os.environ.get("WAVERLESS_ENDPOINT_ID"):
92
90
  return "waverless"
93
91
 
92
+ # Check for RunPod environment
93
+ if os.environ.get("RUNPOD_ENDPOINT_ID"):
94
+ return "runpod"
95
+
94
96
  return None
95
97
 
96
98
 
97
- def _resolve_url(url_template: Optional[str], pod_id: str) -> Optional[str]:
98
- """Replace pod ID placeholder in URL template.
99
+ def _generate_pod_id(endpoint_id: Optional[str], raw_pod_id: Optional[str]) -> str:
100
+ """Generate or resolve pod_id.
99
101
 
100
- Note: Only $RUNPOD_POD_ID is replaced here. The $ID placeholder is
101
- replaced later at runtime with the actual job ID in http._handle_result.
102
+ Priority: raw_pod_id > DEVICE_ID > auto-generate
103
+
104
+ Args:
105
+ endpoint_id: The endpoint identifier.
106
+ raw_pod_id: The raw pod_id from environment variable.
107
+
108
+ Returns:
109
+ The resolved pod_id.
110
+ """
111
+ if raw_pod_id:
112
+ return raw_pod_id
113
+ device_id = os.environ.get("DEVICE_ID")
114
+ if device_id:
115
+ return device_id
116
+ prefix = endpoint_id or "worker"
117
+ return f"{prefix}-{uuid.uuid4().hex}"
118
+
119
+
120
+ def _resolve_runpod_url(url_template: Optional[str], pod_id: str) -> Optional[str]:
121
+ """Replace pod ID placeholder in RunPod URL template.
102
122
 
103
123
  Args:
104
124
  url_template: URL template with $RUNPOD_POD_ID placeholder.
@@ -112,10 +132,31 @@ def _resolve_url(url_template: Optional[str], pod_id: str) -> Optional[str]:
112
132
  return url_template.replace("$RUNPOD_POD_ID", pod_id)
113
133
 
114
134
 
135
+ def _resolve_waverless_url(url_template: Optional[str], pod_id: str) -> Optional[str]:
136
+ """Replace pod ID placeholder in Waverless URL template.
137
+
138
+ Args:
139
+ url_template: URL template with $WAVERLESS_POD_ID placeholder.
140
+ pod_id: The worker/pod ID to substitute.
141
+
142
+ Returns:
143
+ URL with $WAVERLESS_POD_ID placeholder replaced, or None if template is None.
144
+ """
145
+ if not url_template:
146
+ return None
147
+ return url_template.replace("$WAVERLESS_POD_ID", pod_id)
148
+
149
+
115
150
  def _load_runpod_serverless_config() -> None:
116
151
  """Load RunPod environment variables into serverless config."""
152
+ # Endpoint identification (load first for pod_id generation)
153
+ serverless.endpoint_id = os.environ.get("RUNPOD_ENDPOINT_ID")
154
+ serverless.project_id = os.environ.get("RUNPOD_PROJECT_ID")
155
+
117
156
  # Worker identification
118
- serverless.pod_id = os.environ.get("RUNPOD_POD_ID") or ""
157
+ raw_pod_id = os.environ.get("RUNPOD_POD_ID")
158
+ serverless.pod_id = _generate_pod_id(serverless.endpoint_id, raw_pod_id)
159
+ serverless.pod_hostname = os.environ.get("RUNPOD_POD_HOSTNAME", serverless.pod_id)
119
160
 
120
161
  # API endpoint templates
121
162
  serverless.webhook_get_job = os.environ.get("RUNPOD_WEBHOOK_GET_JOB")
@@ -123,15 +164,23 @@ def _load_runpod_serverless_config() -> None:
123
164
  serverless.webhook_post_stream = os.environ.get("RUNPOD_WEBHOOK_POST_STREAM")
124
165
  serverless.webhook_ping = os.environ.get("RUNPOD_WEBHOOK_PING")
125
166
 
126
- # Resolved API endpoints (with pod_id substituted)
127
- serverless.job_get_url = _resolve_url(serverless.webhook_get_job, serverless.pod_id)
128
- serverless.job_done_url = _resolve_url(
167
+ # Resolved API endpoints (with $RUNPOD_POD_ID substituted)
168
+ job_get_url = _resolve_runpod_url(serverless.webhook_get_job, serverless.pod_id)
169
+ # job_get_url also needs $ID replaced with worker ID (like runpod-python)
170
+ if job_get_url:
171
+ job_get_url = job_get_url.replace("$ID", serverless.pod_id)
172
+ serverless.job_get_url = job_get_url
173
+
174
+ # job_done_url keeps $ID for runtime replacement with job_id
175
+ serverless.job_done_url = _resolve_runpod_url(
129
176
  serverless.webhook_post_output, serverless.pod_id
130
177
  )
131
- serverless.job_stream_url = _resolve_url(
178
+ serverless.job_stream_url = _resolve_runpod_url(
132
179
  serverless.webhook_post_stream, serverless.pod_id
133
180
  )
134
- serverless.ping_url = _resolve_url(serverless.webhook_ping, serverless.pod_id)
181
+ serverless.ping_url = _resolve_runpod_url(
182
+ serverless.webhook_ping, serverless.pod_id
183
+ )
135
184
 
136
185
  # Authentication
137
186
  serverless.api_key = os.environ.get("RUNPOD_AI_API_KEY")
@@ -142,11 +191,6 @@ def _load_runpod_serverless_config() -> None:
142
191
  log_level = os.environ.get("RUNPOD_DEBUG_LEVEL")
143
192
  serverless.log_level = log_level or "INFO"
144
193
 
145
- # Endpoint identification
146
- serverless.endpoint_id = os.environ.get("RUNPOD_ENDPOINT_ID")
147
- serverless.project_id = os.environ.get("RUNPOD_PROJECT_ID")
148
- serverless.pod_hostname = os.environ.get("RUNPOD_POD_HOSTNAME")
149
-
150
194
  # Timing and concurrency
151
195
  ping_interval = os.environ.get("RUNPOD_PING_INTERVAL")
152
196
  if ping_interval:
@@ -163,8 +207,17 @@ def _load_runpod_serverless_config() -> None:
163
207
 
164
208
  def _load_waverless_serverless_config() -> None:
165
209
  """Load Waverless environment variables into serverless config."""
210
+ # Endpoint identification (load first for pod_id generation)
211
+ serverless.endpoint_id = os.environ.get("WAVERLESS_ENDPOINT_ID")
212
+ # Endpoint identification (endpoint_id already set above)
213
+ serverless.project_id = os.environ.get("WAVERLESS_PROJECT_ID")
214
+
166
215
  # Worker identification
167
- serverless.pod_id = os.environ.get("WAVERLESS_POD_ID") or ""
216
+ raw_pod_id = os.environ.get("WAVERLESS_POD_ID")
217
+ serverless.pod_id = _generate_pod_id(serverless.endpoint_id, raw_pod_id)
218
+ serverless.pod_hostname = os.environ.get(
219
+ "WAVERLESS_POD_HOSTNAME", serverless.pod_id
220
+ )
168
221
 
169
222
  # API endpoint templates
170
223
  serverless.webhook_get_job = os.environ.get("WAVERLESS_WEBHOOK_GET_JOB")
@@ -172,15 +225,23 @@ def _load_waverless_serverless_config() -> None:
172
225
  serverless.webhook_post_stream = os.environ.get("WAVERLESS_WEBHOOK_POST_STREAM")
173
226
  serverless.webhook_ping = os.environ.get("WAVERLESS_WEBHOOK_PING")
174
227
 
175
- # Resolved API endpoints (with pod_id substituted)
176
- serverless.job_get_url = _resolve_url(serverless.webhook_get_job, serverless.pod_id)
177
- serverless.job_done_url = _resolve_url(
228
+ # Resolved API endpoints (with $WAVERLESS_POD_ID substituted)
229
+ job_get_url = _resolve_waverless_url(serverless.webhook_get_job, serverless.pod_id)
230
+ # job_get_url also needs $ID replaced with worker ID (like runpod)
231
+ if job_get_url:
232
+ job_get_url = job_get_url.replace("$ID", serverless.pod_id)
233
+ serverless.job_get_url = job_get_url
234
+
235
+ # job_done_url keeps $ID for runtime replacement with job_id
236
+ serverless.job_done_url = _resolve_waverless_url(
178
237
  serverless.webhook_post_output, serverless.pod_id
179
238
  )
180
- serverless.job_stream_url = _resolve_url(
239
+ serverless.job_stream_url = _resolve_waverless_url(
181
240
  serverless.webhook_post_stream, serverless.pod_id
182
241
  )
183
- serverless.ping_url = _resolve_url(serverless.webhook_ping, serverless.pod_id)
242
+ serverless.ping_url = _resolve_waverless_url(
243
+ serverless.webhook_ping, serverless.pod_id
244
+ )
184
245
 
185
246
  # Authentication
186
247
  serverless.api_key = os.environ.get("WAVERLESS_API_KEY")
@@ -188,11 +249,6 @@ def _load_waverless_serverless_config() -> None:
188
249
  # Logging
189
250
  serverless.log_level = os.environ.get("WAVERLESS_LOG_LEVEL", "INFO")
190
251
 
191
- # Endpoint identification
192
- serverless.endpoint_id = os.environ.get("WAVERLESS_ENDPOINT_ID")
193
- serverless.project_id = os.environ.get("WAVERLESS_PROJECT_ID")
194
- serverless.pod_hostname = os.environ.get("WAVERLESS_POD_HOSTNAME")
195
-
196
252
  # Timing and concurrency
197
253
  ping_interval = os.environ.get("WAVERLESS_PING_INTERVAL")
198
254
  if ping_interval:
@@ -220,6 +220,15 @@ class WorkerAPI:
220
220
  tags=["Status"],
221
221
  )
222
222
 
223
+ # Health check endpoint
224
+ router.add_api_route(
225
+ "/health",
226
+ lambda: {"status": "ok"},
227
+ methods=["GET"],
228
+ summary="Health check",
229
+ tags=["Status"],
230
+ )
231
+
223
232
  self.app.include_router(router)
224
233
 
225
234
  def start(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavespeed
3
- Version: 1.0.6
3
+ Version: 1.0.7
4
4
  Summary: WaveSpeedAI Python Client — Official Python SDK for WaveSpeedAI inference platform
5
5
  Author-email: WaveSpeedAI <support@wavespeed.ai>
6
6
  License: MIT
@@ -0,0 +1,84 @@
1
+ """Tests for the config module."""
2
+
3
+ import unittest
4
+
5
+ from wavespeed.config import _resolve_runpod_url, _resolve_waverless_url, serverless
6
+
7
+
8
+ class TestResolveRunpodUrl(unittest.TestCase):
9
+ """Tests for the _resolve_runpod_url function."""
10
+
11
+ def test_replaces_runpod_pod_id(self):
12
+ """Test that $RUNPOD_POD_ID is replaced with pod_id."""
13
+ template = "https://api.runpod.ai/v2/endpoint/job-done/$RUNPOD_POD_ID"
14
+ result = _resolve_runpod_url(template, "my-pod-123")
15
+ self.assertEqual(
16
+ result, "https://api.runpod.ai/v2/endpoint/job-done/my-pod-123"
17
+ )
18
+
19
+ def test_preserves_id_placeholder(self):
20
+ """Test that $ID is NOT replaced - it's for job ID at runtime."""
21
+ template = "https://api.runpod.ai/v2/endpoint/job-done/$RUNPOD_POD_ID/$ID"
22
+ result = _resolve_runpod_url(template, "my-pod-123")
23
+ self.assertEqual(
24
+ result, "https://api.runpod.ai/v2/endpoint/job-done/my-pod-123/$ID"
25
+ )
26
+
27
+ def test_handles_none_template(self):
28
+ """Test that None template returns None."""
29
+ result = _resolve_runpod_url(None, "my-pod-123")
30
+ self.assertIsNone(result)
31
+
32
+ def test_no_placeholders(self):
33
+ """Test URL without any placeholders."""
34
+ template = "https://api.example.com/endpoint"
35
+ result = _resolve_runpod_url(template, "my-pod-123")
36
+ self.assertEqual(result, "https://api.example.com/endpoint")
37
+
38
+
39
+ class TestResolveWaverlessUrl(unittest.TestCase):
40
+ """Tests for the _resolve_waverless_url function."""
41
+
42
+ def test_replaces_waverless_pod_id_placeholder(self):
43
+ """Test that $WAVERLESS_POD_ID is replaced with pod_id."""
44
+ template = "https://api.wavespeed.ai/v2/test/job-take/$WAVERLESS_POD_ID"
45
+ result = _resolve_waverless_url(template, "my-pod-123")
46
+ self.assertEqual(
47
+ result, "https://api.wavespeed.ai/v2/test/job-take/my-pod-123"
48
+ )
49
+
50
+ def test_preserves_id_placeholder(self):
51
+ """Test that $ID is NOT replaced - it's for job/worker ID at runtime."""
52
+ template = "https://api.wavespeed.ai/v2/test/job-done/$WAVERLESS_POD_ID/$ID"
53
+ result = _resolve_waverless_url(template, "my-pod-123")
54
+ self.assertEqual(
55
+ result, "https://api.wavespeed.ai/v2/test/job-done/my-pod-123/$ID"
56
+ )
57
+
58
+ def test_handles_none_template(self):
59
+ """Test that None template returns None."""
60
+ result = _resolve_waverless_url(None, "my-pod-123")
61
+ self.assertIsNone(result)
62
+
63
+ def test_no_placeholders(self):
64
+ """Test URL without any placeholders."""
65
+ template = "https://api.example.com/endpoint"
66
+ result = _resolve_waverless_url(template, "my-pod-123")
67
+ self.assertEqual(result, "https://api.example.com/endpoint")
68
+
69
+
70
+ class TestServerlessConfig(unittest.TestCase):
71
+ """Tests for serverless config loading."""
72
+
73
+ def test_serverless_has_expected_attributes(self):
74
+ """Test that serverless config has all expected attributes."""
75
+ self.assertTrue(hasattr(serverless, "pod_id"))
76
+ self.assertTrue(hasattr(serverless, "api_key"))
77
+ self.assertTrue(hasattr(serverless, "job_get_url"))
78
+ self.assertTrue(hasattr(serverless, "job_done_url"))
79
+ self.assertTrue(hasattr(serverless, "job_stream_url"))
80
+ self.assertTrue(hasattr(serverless, "ping_url"))
81
+
82
+
83
+ if __name__ == "__main__":
84
+ unittest.main()
@@ -1,65 +0,0 @@
1
- """Tests for the config module."""
2
-
3
- import unittest
4
-
5
- from wavespeed.config import _resolve_url, serverless
6
-
7
-
8
- class TestResolveUrl(unittest.TestCase):
9
- """Tests for the _resolve_url function."""
10
-
11
- def test_replaces_runpod_pod_id(self):
12
- """Test that $RUNPOD_POD_ID is replaced with pod_id."""
13
- template = "https://api.runpod.ai/v2/endpoint/job-done/$RUNPOD_POD_ID"
14
- result = _resolve_url(template, "my-pod-123")
15
- self.assertEqual(
16
- result, "https://api.runpod.ai/v2/endpoint/job-done/my-pod-123"
17
- )
18
-
19
- def test_preserves_id_placeholder(self):
20
- """Test that $ID is NOT replaced - it's for job ID at runtime."""
21
- template = "https://api.runpod.ai/v2/endpoint/job-done/$RUNPOD_POD_ID/$ID"
22
- result = _resolve_url(template, "my-pod-123")
23
- # $ID should remain as placeholder for job ID replacement later
24
- self.assertEqual(
25
- result, "https://api.runpod.ai/v2/endpoint/job-done/my-pod-123/$ID"
26
- )
27
-
28
- def test_handles_none_template(self):
29
- """Test that None template returns None."""
30
- result = _resolve_url(None, "my-pod-123")
31
- self.assertIsNone(result)
32
-
33
- def test_handles_empty_template(self):
34
- """Test that empty template returns None (falsy check)."""
35
- result = _resolve_url("", "my-pod-123")
36
- self.assertIsNone(result)
37
-
38
- def test_no_placeholders(self):
39
- """Test URL without any placeholders."""
40
- template = "https://api.example.com/endpoint"
41
- result = _resolve_url(template, "my-pod-123")
42
- self.assertEqual(result, "https://api.example.com/endpoint")
43
-
44
- def test_multiple_pod_id_placeholders(self):
45
- """Test multiple $RUNPOD_POD_ID placeholders are all replaced."""
46
- template = "https://api.runpod.ai/$RUNPOD_POD_ID/test/$RUNPOD_POD_ID"
47
- result = _resolve_url(template, "pod-456")
48
- self.assertEqual(result, "https://api.runpod.ai/pod-456/test/pod-456")
49
-
50
-
51
- class TestServerlessConfig(unittest.TestCase):
52
- """Tests for serverless config loading."""
53
-
54
- def test_serverless_has_expected_attributes(self):
55
- """Test that serverless config has all expected attributes."""
56
- self.assertTrue(hasattr(serverless, "pod_id"))
57
- self.assertTrue(hasattr(serverless, "api_key"))
58
- self.assertTrue(hasattr(serverless, "job_get_url"))
59
- self.assertTrue(hasattr(serverless, "job_done_url"))
60
- self.assertTrue(hasattr(serverless, "job_stream_url"))
61
- self.assertTrue(hasattr(serverless, "ping_url"))
62
-
63
-
64
- if __name__ == "__main__":
65
- unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes