Skip to main content

SDK for interacting with the Benchling Platform.

Project description

Benchling SDK

A Python 3.7+ SDK for the Benchling platform designed to provide typed, fluent interactions with Benchling APIs.

Important! This is a pre-release alpha. Changes to this project may not be backwards compatible.

Getting Started

Installation

Install the dependency via Poetry (if applicable):

poetry add benchling-sdk

Or Pip:

pip install benchling-sdk

Using the SDK

Obtain a valid API key from your Benchling account and provide it to the SDK, along with the URL for the server. Example:

from benchling_sdk.benchling import Benchling
benchling = Benchling(url="https://my.benchling.com", api_key="api_key")

With Benchling now instantiated, make a sample call to get a custom entity with the ID "custom_id".

entity = benchling.custom_entities.get_by_id(entity_id="custom_id")

API calls made by the SDK are synchronous and blocking.

Generators and nextToken

Paginated API endpoints listing objects and supporting the nextToken parameter will produce a PageIterator, which is a Python generator. Example:

requests_generator = benchling.requests.list(schema_id="assaych_test")
next_request = next(requests_generator)

In this example, requests_generator is a generator. Each iteration will return a List of Requests, not an individual Request.

The PageIterator object has an estimated_count() which will return the value of the Result-Count header from the API, if applicable for the endpoint. Note that you MUST consume the generator at least once or estimated_count() will return None.

Working with Benchling Fields

Many objects in Benchling have the concept of fields. They are represented in the SDK via the benchling_api_client.models.fields.Fields class.

To conveniently construct Fields from a dictionary, we have provided a fields method in the serialization_helper module:

from benchling_sdk.helpers.serialization_helpers import fields
from benchling_api_client.models.custom_entity import CustomEntity

entity = CustomEntity(
    name="My Entity",
    fields=fields({
    "a_field": {"value": "First value"},
    "second_field": {"value": "Second value"},
    })
)

Unset

The Benchling SDK uses the type benchling_api_client.types.Unset and the constant value benchling_api_client.types.UNSET to represent values that were not present in an interaction with the API. This is to distinguish from values that were explicitly set to None from those that were simply unspecified.

A common example might be updating only specific properties of an object:

from benchling_api_client.models.custom_entity_update import CustomEntityUpdate

update = CustomEntityUpdate(name="New name")

updated_entity = benchling.custom_entities.update(
    entity_id="entity_id", entity=update
)

All other properties of CustomEntityUpdate besides name will default to UNSET and not be sent with the update. Setting any optional property to None will send a null JSON value. In general, you should not need to set UNSET directly.

When receiving objects from the API, some of their fields may be Unset. To treat UNSET values equivalent to Optional[T], you can use the convenience function unset_as_none():

from benchling_sdk.helpers.serialization_helpers import unset_as_none

sample_value: Union[Unset, None, int] = UNSET

optional_value = unset_as_none(sample_value)
# optional_value will be None

Error Handling

Failed API interactions will generally return a BenchlingError, which will contain some underlying information on the HTTP response such as the status. Example:

from benchling_sdk.errors import BenchlingError

try:
    requests = benchling.requests.get_by_id("requst_id")
except BenchlingError as error:
    print(error.status_code)

If an HTTP error code is not returned to the SDK or deserialization fails, an unbounded Exception could be raised instead.

Advanced Use Cases

By default, the Benchling SDK is designed to be opinionated towards most common usage. There is some more advanced configuration available for use cases which require it.

Retries

The SDK will automatically retry certain HTTP calls when the calls fail and certain conditions are met.

The default strategy is to retry calls failing with HTTP status codes 429, 502, 503, and 504. The rationale for these status codes being retried is that many times they are indicative of a temporary network failure or exceeding the rate limit and may be successful upon retry.

Retries will be attempted up to 5 times, with an exponential time delay backoff between calls.

To disable retries, specify None for retry_strategy when constructing Benchling:

benchling = Benchling(url="https://my.benchling.com", api_key="api_key", retry_strategy=None)

Alternatively, instantiate your own benchling_sdk.retry_helpers.RetryStrategy to further customize retry behavior.

BenchlingApiClient Customization (e.g., HTTP Timeout Settings)

While the SDK abstracts most of the HTTP transport layer, access can still be granted via the BenchlingApiClient. A common use case might be extending HTTP timeouts for all calls.

This can be achieved by specifying a function which accepts a default configured instance of BenchlingApiClient and returns a mutated instance with the desired changes.

For example, to set the HTTP timeout to 180 seconds:

from benchling_api_client.benchling_client import BenchlingApiClient

def higher_timeout_client(client: BenchlingApiClient) -> BenchlingApiClient:
    return client.with_timeout(180)


benchling = Benchling(
    url="https://my.benchling.com",
    api_key="api_key",
    client_decorator=higher_timeout_client,
)

To fully customize the BenchlingApiClient and ignore default settings, construct your own instance in lieu of modifying the client argument.

Changing the Base URL

When instantiating Benchling, the path /api/v2 will automatically be appended to the server information provided.

For example, if creating Benchling like this:

benchling = Benchling(url="https://my.benchling.com", api_key="api_key")

API calls will be made to https://my.benchling.com/api/v2.

To specify, an alternative path, set the base_path when creating Benchling:

benchling = Benchling(url="https://my.benchling.com", api_key="api_key", base_path="/api/custom")

In this case, API calls will be made to https://my.benchling.com/api/custom.

Custom API Calls

For making customized API calls to Benchling, the SDK supports an open-ended Benchling.api namespace that exposes varying levels of interaction for HTTP GET, POST, PATCH, and DELETE methods. This is useful for API endpoints which the SDK may not support yet or more granular control at the HTTP layer.

For each verb, there are two related methods. Using GET as an example:

  1. get_response() - Returns a benchling_api_client.types.Response which has been parsed to a JSON dict and is slightly more structured.
  2. get_modeled() - Returns any custom model which extends benchling_sdk.helpers.serialization_helpers.DeserializableModel and must be a Python @dataclass.

Both will automatically retry failures according to RetryStrategy and will marshall errors to BenchlingError.

When calling any of the methods in Benchling.api, specify the full path to the URL except for the scheme and server. This differs from other API services, which will prepend the URL with a base_path.

For example, if wishing to call an endpoint https://my.benchling.com/api/v2/custom-entities?some=param, pass api/v2/custom-entities?some=param for the url.

Here's an example of making a custom call with post_modeled():

from dataclasses import dataclass, field
from typing import Any, Dict
from dataclasses_json import config
from benchling_sdk.helpers.serialization_helpers import DeserializableModel, SerializableModel

@dataclass
class ModeledCustomEntityPost(SerializableModel):
    name: str
    fields: Dict[str, Any]
    # If the property name in the API JSON payload does not match the Python attribute, use
    # field and config to specify the appropriate name for serializing/deserializing
    folder_id: str = field(metadata=config(field_name="folderId"))
    schema_id: str = field(metadata=config(field_name="schemaId"))


@dataclass
class ModeledCustomEntityGet(DeserializableModel):
    id: str
    name: str
    fields: Dict[str, Any]
    folder_id: str = field(metadata=config(field_name="folderId"))

# Assumes `benchling` is already configured and instantiated as `Benchling`
body = ModeledCustomEntityPost(
    name="My Custom Entity Model",
    folder_id="folder_id",
    schema_id="schema_id",
    fields={"My Field": {"value": "Modeled Entity"}},
)

created_entity = benchling.api.post_modeled(
    url="api/v2/custom-entities", body=body, target_type=ModeledCustomEntityGet
)

The returned created_entity will be of type ModeledCustomEntityGet. Classes extending SerializableModel and DeserializableModel will inherit serialize() and deserialize() methods respectively which will act on Python class attributes by default. These can be overridden for more customized serialization needs.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

benchling-sdk-0.7.0a0.tar.gz (37.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

benchling_sdk-0.7.0a0-py3-none-any.whl (63.4 kB view details)

Uploaded Python 3

File details

Details for the file benchling-sdk-0.7.0a0.tar.gz.

File metadata

  • Download URL: benchling-sdk-0.7.0a0.tar.gz
  • Upload date:
  • Size: 37.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.10 CPython/3.7.9 Linux/4.14.214-160.339.amzn2.x86_64

File hashes

Hashes for benchling-sdk-0.7.0a0.tar.gz
Algorithm Hash digest
SHA256 3841cd74f9c0bf5f14236b27a92fa976da592e4b224e5ba973fd4f88e42c263d
MD5 74bdccd14c5fbebb670aa6daac744b6c
BLAKE2b-256 581b08f398e8ac99bb639a00497b8c2dac1ecb36a5cdec38cff5c90fcbb1c876

See more details on using hashes here.

File details

Details for the file benchling_sdk-0.7.0a0-py3-none-any.whl.

File metadata

  • Download URL: benchling_sdk-0.7.0a0-py3-none-any.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.10 CPython/3.7.9 Linux/4.14.214-160.339.amzn2.x86_64

File hashes

Hashes for benchling_sdk-0.7.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a999eac768d3957744a18c8d2ce8b209205b054c004cd7f88448e19f8771606
MD5 92f085d6a131d7a3e9e3b7127d6c67b7
BLAKE2b-256 8598daef081f265eeff7b911a739afa722fa0c3866b24c0b3804f8390d128b43

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page