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
12 changes: 10 additions & 2 deletions liminal/connection/benchling_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from playwright.async_api import async_playwright, Request
import requests
from benchling_sdk.auth.client_credentials_oauth2 import ClientCredentialsOAuth2
from benchling_sdk.benchling import Benchling
from benchling_sdk.benchling import Benchling, BenchlingApiClientDecorator
from benchling_sdk.helpers.retry_helpers import RetryStrategy
from bs4 import BeautifulSoup
from sqlalchemy import create_engine
Expand Down Expand Up @@ -55,6 +55,10 @@ class BenchlingService(Benchling):
Whether to connect to the Benchling Postgres database. Requires warehouse_connection_string from the connection object.
use_internal_api: bool = False
Whether to connect to the Benchling internal API. Requires internal_api_admin_email and internal_api_admin_password from the connection object.
client_decorator: BenchlingApiClientDecorator | None = None
An optional function that receives the default BenchlingApiClient and returns a
customized one. Forwarded to the Benchling SDK. A common use is raising the HTTP
timeout, which otherwise defaults to 10 seconds: ``lambda c: c.with_timeout(60)``.
"""

def __init__(
Expand All @@ -63,6 +67,7 @@ def __init__(
use_api: bool = True,
use_db: bool = False,
use_internal_api: bool = False,
client_decorator: BenchlingApiClientDecorator | None = None,
) -> None:
self.connection = connection
self._session: Session | None = None
Expand All @@ -77,7 +82,10 @@ def __init__(
)
url = f"https://{connection.tenant_name}.benchling.com"
super().__init__(
url=url, auth_method=auth_method, retry_strategy=retry_strategy
url=url,
auth_method=auth_method,
retry_strategy=retry_strategy,
client_decorator=client_decorator,
)
LOGGER.info(f"Tenant {connection.tenant_name}: Connected to Benchling API.")
self.use_db = use_db
Expand Down
34 changes: 34 additions & 0 deletions liminal/tests/test_benchling_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import cast

from benchling_api_client.v2.benchling_client import BenchlingApiClient

from liminal.connection.benchling_connection import BenchlingConnection
from liminal.connection.benchling_service import BenchlingService

# The Benchling SDK defaults the per-request HTTP timeout to 10 seconds.
SDK_DEFAULT_TIMEOUT_SECONDS = 10


def _connection() -> BenchlingConnection:
return BenchlingConnection(
tenant_name="test-tenant",
api_client_id="test-id",
api_client_secret="test-secret",
)


class TestBenchlingServiceClientDecorator:
def test_default_timeout_is_sdk_default(self) -> None:
service = BenchlingService(_connection(), use_db=False)
assert service._client.get_timeout() == SDK_DEFAULT_TIMEOUT_SECONDS

def test_client_decorator_is_forwarded_to_sdk(self) -> None:
def raise_timeout(client: BenchlingApiClient) -> BenchlingApiClient:
# with_timeout is typed to return the base Client but preserves the subclass.
return cast(BenchlingApiClient, client.with_timeout(60))

service = BenchlingService(
_connection(), use_db=False, client_decorator=raise_timeout
)

assert service._client.get_timeout() == 60
Loading