wavespeed
Advanced tools
+1
-1
| Metadata-Version: 2.4 | ||
| Name: wavespeed | ||
| Version: 1.0.6 | ||
| Version: 1.0.7 | ||
| Summary: WaveSpeedAI Python Client — Official Python SDK for WaveSpeedAI inference platform | ||
@@ -5,0 +5,0 @@ Author-email: WaveSpeedAI <support@wavespeed.ai> |
| Metadata-Version: 2.4 | ||
| Name: wavespeed | ||
| Version: 1.0.6 | ||
| Version: 1.0.7 | ||
| Summary: WaveSpeedAI Python Client — Official Python SDK for WaveSpeedAI inference platform | ||
@@ -5,0 +5,0 @@ Author-email: WaveSpeedAI <support@wavespeed.ai> |
| # This file is automatically generated by setuptools_scm | ||
| __version__ = "1.0.6" | ||
| __version__ = "1.0.7" |
+86
-30
@@ -5,2 +5,3 @@ """Configuration module for WaveSpeed SDK.""" | ||
| import sys | ||
| import uuid | ||
| from typing import Optional | ||
@@ -87,20 +88,39 @@ | ||
| """ | ||
| # Check for RunPod environment | ||
| if os.environ.get("RUNPOD_POD_ID"): | ||
| return "runpod" | ||
| # Check for native Waverless environment | ||
| if os.environ.get("WAVERLESS_POD_ID"): | ||
| if os.environ.get("WAVERLESS_ENDPOINT_ID"): | ||
| return "waverless" | ||
| # Check for RunPod environment | ||
| if os.environ.get("RUNPOD_ENDPOINT_ID"): | ||
| return "runpod" | ||
| return None | ||
| def _resolve_url(url_template: Optional[str], pod_id: str) -> Optional[str]: | ||
| """Replace pod ID placeholder in URL template. | ||
| def _generate_pod_id(endpoint_id: Optional[str], raw_pod_id: Optional[str]) -> str: | ||
| """Generate or resolve pod_id. | ||
| Note: Only $RUNPOD_POD_ID is replaced here. The $ID placeholder is | ||
| replaced later at runtime with the actual job ID in http._handle_result. | ||
| Priority: raw_pod_id > DEVICE_ID > auto-generate | ||
| Args: | ||
| endpoint_id: The endpoint identifier. | ||
| raw_pod_id: The raw pod_id from environment variable. | ||
| Returns: | ||
| The resolved pod_id. | ||
| """ | ||
| if raw_pod_id: | ||
| return raw_pod_id | ||
| device_id = os.environ.get("DEVICE_ID") | ||
| if device_id: | ||
| return device_id | ||
| prefix = endpoint_id or "worker" | ||
| return f"{prefix}-{uuid.uuid4().hex}" | ||
| def _resolve_runpod_url(url_template: Optional[str], pod_id: str) -> Optional[str]: | ||
| """Replace pod ID placeholder in RunPod URL template. | ||
| Args: | ||
| url_template: URL template with $RUNPOD_POD_ID placeholder. | ||
@@ -117,6 +137,27 @@ pod_id: The worker/pod ID to substitute. | ||
| def _resolve_waverless_url(url_template: Optional[str], pod_id: str) -> Optional[str]: | ||
| """Replace pod ID placeholder in Waverless URL template. | ||
| Args: | ||
| url_template: URL template with $WAVERLESS_POD_ID placeholder. | ||
| pod_id: The worker/pod ID to substitute. | ||
| Returns: | ||
| URL with $WAVERLESS_POD_ID placeholder replaced, or None if template is None. | ||
| """ | ||
| if not url_template: | ||
| return None | ||
| return url_template.replace("$WAVERLESS_POD_ID", pod_id) | ||
| def _load_runpod_serverless_config() -> None: | ||
| """Load RunPod environment variables into serverless config.""" | ||
| # Endpoint identification (load first for pod_id generation) | ||
| serverless.endpoint_id = os.environ.get("RUNPOD_ENDPOINT_ID") | ||
| serverless.project_id = os.environ.get("RUNPOD_PROJECT_ID") | ||
| # Worker identification | ||
| serverless.pod_id = os.environ.get("RUNPOD_POD_ID") or "" | ||
| raw_pod_id = os.environ.get("RUNPOD_POD_ID") | ||
| serverless.pod_id = _generate_pod_id(serverless.endpoint_id, raw_pod_id) | ||
| serverless.pod_hostname = os.environ.get("RUNPOD_POD_HOSTNAME", serverless.pod_id) | ||
@@ -129,11 +170,19 @@ # API endpoint templates | ||
| # Resolved API endpoints (with pod_id substituted) | ||
| serverless.job_get_url = _resolve_url(serverless.webhook_get_job, serverless.pod_id) | ||
| serverless.job_done_url = _resolve_url( | ||
| # Resolved API endpoints (with $RUNPOD_POD_ID substituted) | ||
| job_get_url = _resolve_runpod_url(serverless.webhook_get_job, serverless.pod_id) | ||
| # job_get_url also needs $ID replaced with worker ID (like runpod-python) | ||
| if job_get_url: | ||
| job_get_url = job_get_url.replace("$ID", serverless.pod_id) | ||
| serverless.job_get_url = job_get_url | ||
| # job_done_url keeps $ID for runtime replacement with job_id | ||
| serverless.job_done_url = _resolve_runpod_url( | ||
| serverless.webhook_post_output, serverless.pod_id | ||
| ) | ||
| serverless.job_stream_url = _resolve_url( | ||
| serverless.job_stream_url = _resolve_runpod_url( | ||
| serverless.webhook_post_stream, serverless.pod_id | ||
| ) | ||
| serverless.ping_url = _resolve_url(serverless.webhook_ping, serverless.pod_id) | ||
| serverless.ping_url = _resolve_runpod_url( | ||
| serverless.webhook_ping, serverless.pod_id | ||
| ) | ||
@@ -149,7 +198,2 @@ # Authentication | ||
| # Endpoint identification | ||
| serverless.endpoint_id = os.environ.get("RUNPOD_ENDPOINT_ID") | ||
| serverless.project_id = os.environ.get("RUNPOD_PROJECT_ID") | ||
| serverless.pod_hostname = os.environ.get("RUNPOD_POD_HOSTNAME") | ||
| # Timing and concurrency | ||
@@ -171,4 +215,13 @@ ping_interval = os.environ.get("RUNPOD_PING_INTERVAL") | ||
| """Load Waverless environment variables into serverless config.""" | ||
| # Endpoint identification (load first for pod_id generation) | ||
| serverless.endpoint_id = os.environ.get("WAVERLESS_ENDPOINT_ID") | ||
| # Endpoint identification (endpoint_id already set above) | ||
| serverless.project_id = os.environ.get("WAVERLESS_PROJECT_ID") | ||
| # Worker identification | ||
| serverless.pod_id = os.environ.get("WAVERLESS_POD_ID") or "" | ||
| raw_pod_id = os.environ.get("WAVERLESS_POD_ID") | ||
| serverless.pod_id = _generate_pod_id(serverless.endpoint_id, raw_pod_id) | ||
| serverless.pod_hostname = os.environ.get( | ||
| "WAVERLESS_POD_HOSTNAME", serverless.pod_id | ||
| ) | ||
@@ -181,11 +234,19 @@ # API endpoint templates | ||
| # Resolved API endpoints (with pod_id substituted) | ||
| serverless.job_get_url = _resolve_url(serverless.webhook_get_job, serverless.pod_id) | ||
| serverless.job_done_url = _resolve_url( | ||
| # Resolved API endpoints (with $WAVERLESS_POD_ID substituted) | ||
| job_get_url = _resolve_waverless_url(serverless.webhook_get_job, serverless.pod_id) | ||
| # job_get_url also needs $ID replaced with worker ID (like runpod) | ||
| if job_get_url: | ||
| job_get_url = job_get_url.replace("$ID", serverless.pod_id) | ||
| serverless.job_get_url = job_get_url | ||
| # job_done_url keeps $ID for runtime replacement with job_id | ||
| serverless.job_done_url = _resolve_waverless_url( | ||
| serverless.webhook_post_output, serverless.pod_id | ||
| ) | ||
| serverless.job_stream_url = _resolve_url( | ||
| serverless.job_stream_url = _resolve_waverless_url( | ||
| serverless.webhook_post_stream, serverless.pod_id | ||
| ) | ||
| serverless.ping_url = _resolve_url(serverless.webhook_ping, serverless.pod_id) | ||
| serverless.ping_url = _resolve_waverless_url( | ||
| serverless.webhook_ping, serverless.pod_id | ||
| ) | ||
@@ -198,7 +259,2 @@ # Authentication | ||
| # Endpoint identification | ||
| serverless.endpoint_id = os.environ.get("WAVERLESS_ENDPOINT_ID") | ||
| serverless.project_id = os.environ.get("WAVERLESS_PROJECT_ID") | ||
| serverless.pod_hostname = os.environ.get("WAVERLESS_POD_HOSTNAME") | ||
| # Timing and concurrency | ||
@@ -205,0 +261,0 @@ ping_interval = os.environ.get("WAVERLESS_PING_INTERVAL") |
@@ -223,2 +223,11 @@ """FastAPI server for local development and testing.""" | ||
| # Health check endpoint | ||
| router.add_api_route( | ||
| "/health", | ||
| lambda: {"status": "ok"}, | ||
| methods=["GET"], | ||
| summary="Health check", | ||
| tags=["Status"], | ||
| ) | ||
| self.app.include_router(router) | ||
@@ -225,0 +234,0 @@ |
+36
-17
@@ -5,7 +5,7 @@ """Tests for the config module.""" | ||
| from wavespeed.config import _resolve_url, serverless | ||
| from wavespeed.config import _resolve_runpod_url, _resolve_waverless_url, serverless | ||
| class TestResolveUrl(unittest.TestCase): | ||
| """Tests for the _resolve_url function.""" | ||
| class TestResolveRunpodUrl(unittest.TestCase): | ||
| """Tests for the _resolve_runpod_url function.""" | ||
@@ -15,3 +15,3 @@ def test_replaces_runpod_pod_id(self): | ||
| template = "https://api.runpod.ai/v2/endpoint/job-done/$RUNPOD_POD_ID" | ||
| result = _resolve_url(template, "my-pod-123") | ||
| result = _resolve_runpod_url(template, "my-pod-123") | ||
| self.assertEqual( | ||
@@ -24,4 +24,3 @@ result, "https://api.runpod.ai/v2/endpoint/job-done/my-pod-123" | ||
| template = "https://api.runpod.ai/v2/endpoint/job-done/$RUNPOD_POD_ID/$ID" | ||
| result = _resolve_url(template, "my-pod-123") | ||
| # $ID should remain as placeholder for job ID replacement later | ||
| result = _resolve_runpod_url(template, "my-pod-123") | ||
| self.assertEqual( | ||
@@ -33,8 +32,34 @@ result, "https://api.runpod.ai/v2/endpoint/job-done/my-pod-123/$ID" | ||
| """Test that None template returns None.""" | ||
| result = _resolve_url(None, "my-pod-123") | ||
| result = _resolve_runpod_url(None, "my-pod-123") | ||
| self.assertIsNone(result) | ||
| def test_handles_empty_template(self): | ||
| """Test that empty template returns None (falsy check).""" | ||
| result = _resolve_url("", "my-pod-123") | ||
| def test_no_placeholders(self): | ||
| """Test URL without any placeholders.""" | ||
| template = "https://api.example.com/endpoint" | ||
| result = _resolve_runpod_url(template, "my-pod-123") | ||
| self.assertEqual(result, "https://api.example.com/endpoint") | ||
| class TestResolveWaverlessUrl(unittest.TestCase): | ||
| """Tests for the _resolve_waverless_url function.""" | ||
| def test_replaces_waverless_pod_id_placeholder(self): | ||
| """Test that $WAVERLESS_POD_ID is replaced with pod_id.""" | ||
| template = "https://api.wavespeed.ai/v2/test/job-take/$WAVERLESS_POD_ID" | ||
| result = _resolve_waverless_url(template, "my-pod-123") | ||
| self.assertEqual( | ||
| result, "https://api.wavespeed.ai/v2/test/job-take/my-pod-123" | ||
| ) | ||
| def test_preserves_id_placeholder(self): | ||
| """Test that $ID is NOT replaced - it's for job/worker ID at runtime.""" | ||
| template = "https://api.wavespeed.ai/v2/test/job-done/$WAVERLESS_POD_ID/$ID" | ||
| result = _resolve_waverless_url(template, "my-pod-123") | ||
| self.assertEqual( | ||
| result, "https://api.wavespeed.ai/v2/test/job-done/my-pod-123/$ID" | ||
| ) | ||
| def test_handles_none_template(self): | ||
| """Test that None template returns None.""" | ||
| result = _resolve_waverless_url(None, "my-pod-123") | ||
| self.assertIsNone(result) | ||
@@ -45,12 +70,6 @@ | ||
| template = "https://api.example.com/endpoint" | ||
| result = _resolve_url(template, "my-pod-123") | ||
| result = _resolve_waverless_url(template, "my-pod-123") | ||
| self.assertEqual(result, "https://api.example.com/endpoint") | ||
| def test_multiple_pod_id_placeholders(self): | ||
| """Test multiple $RUNPOD_POD_ID placeholders are all replaced.""" | ||
| template = "https://api.runpod.ai/$RUNPOD_POD_ID/test/$RUNPOD_POD_ID" | ||
| result = _resolve_url(template, "pod-456") | ||
| self.assertEqual(result, "https://api.runpod.ai/pod-456/test/pod-456") | ||
| class TestServerlessConfig(unittest.TestCase): | ||
@@ -57,0 +76,0 @@ """Tests for serverless config loading.""" |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
300665
0.98%6048
1.14%