Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions decart/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from typing import Any, Optional
import aiohttp
from pydantic import ValidationError
Expand All @@ -20,14 +21,18 @@ class DecartClient:
Decart API client for video and image generation/transformation.

Args:
api_key: Your Decart API key
api_key: Your Decart API key. Defaults to the DECART_API_KEY environment variable.
base_url: API base URL (defaults to production)
integration: Optional integration identifier (e.g., "langchain/0.1.0")

Example:
```python
# Option 1: Explicit API key
client = DecartClient(api_key="your-key")

# Option 2: Using DECART_API_KEY environment variable
client = DecartClient()

# Image generation (sync) - use process()
image = await client.process({
"model": models.image("lucy-pro-t2i"),
Expand All @@ -44,17 +49,19 @@ class DecartClient:

def __init__(
self,
api_key: str,
api_key: Optional[str] = None,
base_url: str = "https://api.decart.ai",
integration: Optional[str] = None,
) -> None:
if not api_key or not api_key.strip():
resolved_api_key = api_key or os.environ.get("DECART_API_KEY", "").strip() or None

if not resolved_api_key:
raise InvalidAPIKeyError()

if not base_url.startswith(("http://", "https://")):
raise InvalidBaseURLError(base_url)

self.api_key = api_key
self.api_key = resolved_api_key
self.base_url = base_url
self.integration = integration
self._session: Optional[aiohttp.ClientSession] = None
Expand Down
4 changes: 3 additions & 1 deletion decart/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ class InvalidAPIKeyError(DecartSDKError):
"""Raised when API key is invalid or missing."""

def __init__(self) -> None:
super().__init__("API key is required and must be a non-empty string")
super().__init__(
"Missing API key. Pass `api_key` to DecartClient() or set the DECART_API_KEY environment variable."
)


class InvalidBaseURLError(DecartSDKError):
Expand Down
76 changes: 56 additions & 20 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,59 @@
from decart import DecartClient, InvalidAPIKeyError, InvalidBaseURLError


def test_create_client_success() -> None:
client = DecartClient(api_key="test-key")
assert client is not None
assert client.process is not None


def test_create_client_invalid_api_key() -> None:
with pytest.raises(InvalidAPIKeyError):
DecartClient(api_key="")


def test_create_client_invalid_base_url() -> None:
with pytest.raises(InvalidBaseURLError):
DecartClient(api_key="test-key", base_url="invalid-url")


def test_create_client_custom_base_url() -> None:
client = DecartClient(api_key="test-key", base_url="https://custom.decart.ai")
assert client is not None
assert client.base_url == "https://custom.decart.ai"
class TestDecartClient:
"""Tests for DecartClient initialization."""

def test_create_client_with_explicit_api_key(self) -> None:
"""Creates a client with explicit api_key."""
client = DecartClient(api_key="test-key")
assert client is not None
assert client.process is not None
assert client.api_key == "test-key"

def test_create_client_from_env_var(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Creates a client using DECART_API_KEY env var."""
monkeypatch.setenv("DECART_API_KEY", "env-api-key")
client = DecartClient()
assert client is not None
assert client.api_key == "env-api-key"

def test_explicit_api_key_takes_precedence(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Explicit api_key takes precedence over env var."""
monkeypatch.setenv("DECART_API_KEY", "env-api-key")
client = DecartClient(api_key="explicit-key")
assert client.api_key == "explicit-key"

def test_create_client_no_api_key_no_env(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Throws an error if api key is not provided and env var is not set."""
monkeypatch.delenv("DECART_API_KEY", raising=False)
with pytest.raises(InvalidAPIKeyError, match="Missing API key"):
DecartClient()

def test_create_client_empty_api_key(self) -> None:
"""Throws an error if api key is empty string."""
with pytest.raises(InvalidAPIKeyError, match="Missing API key"):
DecartClient(api_key="")

def test_create_client_empty_env_var(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Throws an error if env var is empty string."""
monkeypatch.setenv("DECART_API_KEY", "")
with pytest.raises(InvalidAPIKeyError, match="Missing API key"):
DecartClient()

def test_create_client_whitespace_env_var(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Throws an error if env var is only whitespace."""
monkeypatch.setenv("DECART_API_KEY", " ")
with pytest.raises(InvalidAPIKeyError, match="Missing API key"):
DecartClient()

def test_create_client_invalid_base_url(self) -> None:
"""Throws an error if invalid base url is provided."""
with pytest.raises(InvalidBaseURLError):
DecartClient(api_key="test-key", base_url="invalid-url")

def test_create_client_custom_base_url(self) -> None:
"""Creates a client with custom base url."""
client = DecartClient(api_key="test-key", base_url="https://custom.decart.ai")
assert client is not None
assert client.base_url == "https://custom.decart.ai"
Loading