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
11 changes: 2 additions & 9 deletions src/bria_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import importlib.metadata

from bria_client._version import __version__
from bria_client.clients import BriaAsyncClient, BriaSyncClient

try:
__version__ = importlib.metadata.version(__name__)
except importlib.metadata.PackageNotFoundError:
__version__ = "0.1.1"


__all__ = ["BriaSyncClient", "BriaAsyncClient"]
__all__ = ["BriaSyncClient", "BriaAsyncClient", "__version__"]
6 changes: 6 additions & 0 deletions src/bria_client/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import importlib.metadata

try:
__version__ = importlib.metadata.version("bria-client")
except importlib.metadata.PackageNotFoundError:
__version__ = "0.1.1"
7 changes: 6 additions & 1 deletion src/bria_client/engines/api_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from collections.abc import Callable
from typing import Literal

from bria_client._version import __version__
from bria_client.engines.base.async_http_request import AsyncHTTPRequest
from bria_client.engines.base.base_http_request import BaseHTTPRequest
from bria_client.engines.base.sync_http_request import SyncHTTPRequest
Expand All @@ -20,6 +21,10 @@ def __init__(self, base_url: str | None, default_headers: AdditionalHeaders | No
def default_headers(self) -> dict[str, str]:
return {name: get_header() if callable(get_header) else get_header for name, get_header in self._default_headers.items()}

@property
def user_agent_headers(self) -> dict[str, str]:
return {"User-Agent": f"BriaSDK/{__version__} (python)"}

@property
@abstractmethod
def auth_headers(self) -> dict[str, str]:
Expand Down Expand Up @@ -88,7 +93,7 @@ async def async_request(
def _prepare_headers(self, headers: dict | None = None, auth_override: dict[str, str] | None = None) -> dict:
additional_headers = headers or {}
auth = auth_override if auth_override is not None else self.auth_headers
return {**self.default_headers, **additional_headers, **auth}
return {**self.user_agent_headers, **self.default_headers, **additional_headers, **auth}

def _prepare_endpoint(self, endpoint: str) -> str:
return f"{self.base_url}/v2/{endpoint.lstrip('/')}"
18 changes: 18 additions & 0 deletions tests/integration/clients/test_sync_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ def test_run_without_api_token_kwarg_uses_default_token(self, mocker):
headers = call_args.kwargs["headers"]
assert headers["api_token"] == default_token

def test_request_includes_user_agent_header(self, mocker):
"""Verify that every request includes the User-Agent header with SDK version"""
# Arrange
client = BriaSyncClient(base_url="https://test.example.com", api_token="default_token")
mock_response = BriaResponse(status=Status.COMPLETED, request_id="test_123", result=BriaResult())
mock_post = mocker.patch.object(client.engine.client, "request", return_value=mock_response)

# Act
client.run(endpoint="/test/endpoint", payload={"test": "data"})

# Assert
mock_post.assert_called_once()
call_args = mock_post.call_args
headers = call_args.kwargs["headers"]
assert "User-Agent" in headers
assert headers["User-Agent"].startswith("BriaSDK/")
assert headers["User-Agent"].endswith("(python)")

def test_concurrent_threads_use_correct_api_tokens(self, mocker):
# Arrange
client = BriaSyncClient(base_url="https://test.example.com", api_token="default_token")
Expand Down