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.
- {wavespeed-1.0.6 → wavespeed-1.0.7}/PKG-INFO +1 -1
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/_version.py +1 -1
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/config.py +86 -30
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/fastapi.py +9 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/PKG-INFO +1 -1
- wavespeed-1.0.7/tests/test_config.py +84 -0
- wavespeed-1.0.6/tests/test_config.py +0 -65
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/claude-code-review.yml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/claude.yml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/pre-commit.yml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/python-packages.yml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.github/workflows/python-publish.yml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.gitignore +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/.pre-commit-config.yaml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/CLAUDE.md +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/LICENSE +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/MANIFEST.in +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/README.md +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/VERSIONING.md +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/images/build_and_push.sh +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/Dockerfile +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/build_and_test.sh +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/handler.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/requirements.txt +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/images/test_worker/test_input.json +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/pyproject.toml +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/pytest.ini +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/setup.cfg +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/_config_module.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/api/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/api/client.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/handler.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/heartbeat.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/http.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/job.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/local.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/logger.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/progress.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/scaler.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/modules/state.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/utils/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/utils/boto3_utils.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/utils/validator.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed/serverless/worker.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/SOURCES.txt +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/dependency_links.txt +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/not-zip-safe +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/requires.txt +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/src/wavespeed.egg-info/top_level.txt +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/conftest.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_api.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_fastapi.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_handler.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_http.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_job.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_local.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_logger.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_progress.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_scaler.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_modules/test_state.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_utils/__init__.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_utils/test_validator.py +0 -0
- {wavespeed-1.0.6 → wavespeed-1.0.7}/tests/test_serverless/test_worker.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# This file is automatically generated by setuptools_scm
|
|
2
|
-
__version__ = "1.0.
|
|
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("
|
|
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
|
|
98
|
-
"""
|
|
99
|
+
def _generate_pod_id(endpoint_id: Optional[str], raw_pod_id: Optional[str]) -> str:
|
|
100
|
+
"""Generate or resolve pod_id.
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
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
|
|
127
|
-
|
|
128
|
-
|
|
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 =
|
|
178
|
+
serverless.job_stream_url = _resolve_runpod_url(
|
|
132
179
|
serverless.webhook_post_stream, serverless.pod_id
|
|
133
180
|
)
|
|
134
|
-
serverless.ping_url =
|
|
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
|
-
|
|
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
|
|
176
|
-
|
|
177
|
-
|
|
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 =
|
|
239
|
+
serverless.job_stream_url = _resolve_waverless_url(
|
|
181
240
|
serverless.webhook_post_stream, serverless.pod_id
|
|
182
241
|
)
|
|
183
|
-
serverless.ping_url =
|
|
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(
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|