Skip to main content

Clients

seqq's Python and JavaScript clients improve developer-experience when interacting with seqq's API.

For a more exhaustive example of their usage, see the API Reference.

Background

seqq's clients are auto-generated via openapi-generator, a tool that turns Swagger and OpenAPI specifications into language-specific clients. The Swagger specification passed to openapi-generator for clients is made by protoc-gen-openapiv2. The seqq API service itself is written for gRPC, but the messages and endpoints defined in protobuf map to regular HTTP 1.1 endpoints via google.api.http annotations.

diagram of proto being used for clients

Clients make requests with JSON request/response bodies against an HTTP server that proxies back to seqq's gRPC server.

diagram of clients calling an http server that calls a gRPC server

In theory, gRPC clients could call the gRPC server directly (without the HTTP API highlighted above). The benefits of doing so would include:

  • less overhead from the serialization, deserialization, and hop of the HTTP/JSON reverse proxy
  • better support for binary-format file uploads
  • one fewer port that needs to be exposed from the service

The drawback to gRPC clients is that, at the time of writing, auto-generated Python and JavaScript clients are lacking in functionality. For example, the gRPC Python stubs do not support type hints, and the gRPC JavaScript client for the web (fetch) differs from the client for node (there is no Axios-based isomorphic client).

Python

The Python client package is seqq:

pip install seqq

Python client instantiation

You instantiate the seqq client, ApiClient, with a Configuration that points at the seqq HTTP address. The SeqqServiceApi class wraps the ApiClient with methods for all seqq endpoint.

from seqq.configuration import Configuration
from seqq.api_client import ApiClient
from seqq.api.seqq_service_api import SeqqServiceApi

client = SeqqServiceApi(ApiClient(Configuration("http://localhost:8320")))

Python client type hints and validation

seqq models and methods are all typed. For example, the client's create_record method has types and descriptions for all required fields.

from seqq import V1alphaRecord

class SeqqServiceApi:
@validate_call
def create_record(
self,
collection: Annotated[str, Field(strict=True, description="The `name` of the Collection to create Records in.)],
record_id: Annotated[StrictStr, Field(description="The ID of the Record to create.")],
record: Annotated[V1alphaRecord, Field(description="The Record to create.")],
) -> V1alphaRecord:
"""Create a Record in a Collection.
...

Beyond just type hints, because the clients uses Pydantic, requests are validated client-side. For example, the call below, which forgets to set record_id, raises a ValidationError.

client.create_record(
collection="collections/my-collection",
# record_id="example-id", # this is a required argument
record=V1alphaRecord(record="ATCG", code=V1alphaCode.NUCLEIC),
)

# pydantic_core._pydantic_core.ValidationError: 1 validation error for create_record
# record_id
# Missing required argument [type=missing_argument, input_value=ArgsKwargs((<seqq.api.rec...one, description=None)}), input_type=ArgsKwargs]
# For further information visit https://errors.pydantic.dev/2.6/v/missing_argument

Python client errors

The client will throw ApiExceptions on non-200 status code responses from the seqq server.

from seqq import ApiException, V1alphaCollection

try:
client.create_collection(collection_id="my-collection", collection=V1alphaCollection())
except ApiException as e:
if e.status != 409:
logging.error("failed to create a collection: %s", e.body)
raise e
print("collection already exists: %s", e.body)

JavaScript

The JavaScript/TypeScript client package is seqq:

npm i seqq

It includes TypeScript type definitions and works with any ES6+ JavaScript runtime (it requires Promises).

Because it uses Axios for HTTP requests (an isomorphic HTTP client), the client package works in both browser and server-side environments.

JavaScript client instantiation

The client is instantiated with a SeqqServiceApi constructor that takes a basePath that points at the seqq HTTP server's address.

import { SeqqServiceApi } from "seqq";

const client = new SeqqServiceApi({
basePath: "http://localhost:8320",
});