Metadata-Version: 2.1
Name: ce-bnch-sdk
Version: 2.2.0b0
Summary: SDK for interacting with the Benchling Platform.
License: Apache-2.0
Author: Benchling Customer Engineering
Author-email: ce-team@benchling.com
Requires-Python: >=3.7,<4.0
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Provides-Extra: app-scaffold
Requires-Dist: Jinja2 (>=3.1.0,<4.0.0); extra == "app-scaffold"
Requires-Dist: PyYAML (>=5.4.1,<6.0.0)
Requires-Dist: attrs (>=20.1.0,<=22.0)
Requires-Dist: autoflake (>=1.4,<2.0); extra == "app-scaffold"
Requires-Dist: backoff (>=1.10.0,<2.0.0)
Requires-Dist: benchling-api-client (==1.1.0a18)
Requires-Dist: black (>=22.3.0,<23.0.0); extra == "app-scaffold"
Requires-Dist: httpx (>=0.15.0,<=0.22.0)
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
Requires-Dist: typer (>=0.4.0,<0.5.0); extra == "app-scaffold"
Requires-Dist: typing-extensions (>=3.7.4,<5.0)
Description-Content-Type: text/markdown

# CE Benchling SDK

This is the Customer Engineering team's branch of the Benchling SDK, containing features that we are not yet ready to release to customers.

Currently, the only difference from the main Benchling SDK is the Benchling Apps CLI.

## Benching Apps CLI
The SDK comes with a CLI for managing Benchling Apps, which is still under alpha testing.

Each integration corresponds to a Benchling App. You declare the app's dependencies in a manifest file, typically a top-level file named `manifest.yaml`. For example:
```yaml
manifestVersion: 1  # Currently only version 1 exists

info:
  name: My App
  
  version: 0.0.1
  description: Cure cancer  # Optional

configuration:
  - name: My Plasmid  # Should match the actual name in Benchling, if possible, as apps tries to find the dependency by name
    type: entity_schema  # Corresponds to the API namespace, in this case /entity-schemas
    subtype: dna_sequence  # This section is only used by resources with type "entity-schema"
                           # Possible values for entities are: "custom_entity", "dna_sequence", or "aa_sequence"
    description: Plasmid schema of interest  # Optional
    fieldDefinitions:
      - name: My Backbone
      - name: My Resistances
  - name: Optical Density Assay
    type: assay_run_schema
    fieldDefinitions:
      - name: optical_density  # Run, result, and request schemas use the snake-cased "warehouse name"
  - name: Resistance
    type: dropdown
    options:
      - name: 1 - Ampicillin
      - name: 2 - Penicillin
  - name: My Project
    type: project
```
Any resource type which is served by the Benchling API can be referenced, using its kebab-cased name. Below is the full list of possible values for `resourceType`. Schema types:
- entity_schema
- container_schema
- plate_schema
- box_schema
- location_schema
- assay_result_schema
- assay_run_schema
- request_schema
- entry_schema
- workflow_task_schema
- dropdown
- workflow_task_status

Individual resource types:
- aa_sequence
- assay_result
- assay_run
- automation_input_generator
- automation_output_processor
- blob
- box
- container
- custom_entity
- dna_alignment
- dna_oligo
- dna_sequence
- entry
- folder
- label_printer
- label_template
- location
- plate
- project
- registry
- request

Once you've declared the dependencies, you can generate the `dependencies.py` file and the model classes (in this case `my_plasmid.py`, `optical_density_assay.py`, and `resistance.py`) using the command:
```bash
# Optional arguments `--manifest-file-path`, `dependencies_file_path`, `model_directory_path` to specify the exact paths
poetry run benchling-sdk app dependencies scaffold
```

Next, once a Benchling tenant has been set up where you want to run the integration, you can link each dependency to its corresponding Benchling API ID by using the configuration UI for Benchling Apps in the tenant.

Now the integration will have full access to all its required dependencies. See the documentation in the generated files for more detailed instructions on usage in the integration code.

## General Usage

For more detailed usage of the SDK, refer to the [public release notes](https://pypi.org/project/benchling-sdk/), which are stored as part of the project 
in `publish/README.public.md`.

Simple usage example iterating through DNA sequences:

```python
from benchling_sdk.auth.api_key_auth import ApiKeyAuth
from benchling_sdk.benchling import Benchling

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

dna_sequence_pages = benchling.dna_sequences.list()

for page in dna_sequence_pages:
    for dna_sequence in page:
        print(dna_sequence.bases)
```

## Developer Notes

The `benching_sdk.benchling.Benchling` object serves as the point of entry for the SDK. API calls are organized into
services that generally correspond to [Capillary documentation](https://docs.benchling.com/reference).

Each method calling the API is wrapped with an `@api_method` decorator. This decorator applies several global
behaviors which may not be readily obvious including:
* Conditionally adding some logging on each method call
* Applying retries via the backoff library when `RetryStrategy` is configured

Logging in the SDK follows the [Python best practice](https://docs.python-guide.org/writing/logging/#logging-in-a-library)
of only adding the `logging.NullHandler()`. An example of enabling basic logging:

```python
import logging
logging.basicConfig(level=logging.INFO)
```

For more details on configuring or disabling `RetryStrategy`, refer to *Advanced Use Cases* in `publish/README.public.md`.

HTTP errors like `404` not found are all caught via `raise_for_status()` and transformed into
a standardized `BenchlingError` which wraps the underlying error for a better general error handling experience.
A caught BenchlingError can be inspected to learn the status triggering it, and the full contents of the error 
response returned from the Benchling server.

### Exporting Models

Although generated models are packaged in `benchling_api_client.models` 
and its files, we externalize the models via `benchling_sdk.models` in
order to abstract `benchling_api_client` from users such that they may
simply import `benchling_sdk.models.ExampleModelClass`.

This is accomplished in `benchling_sdk/models/__init__.py`. This file
is automatically generated from a Jinja template in `templates/` by 
running `poetry run task models`. Changes should be committed to source
control. All tasks should be run from the root directory of the project.

Missing models from `benchling_api_client` are verified by unit
test in `benchling-sdk/tests/unit/test_models.py`.

## Configuring pre-push Git Hooks

```bash
poetry run pre-commit install --hook-type pre-push
```

## Publishing Releases

To create a release of the SDK, create a tag in Git from the `main` branch. CI will then
initiate a build, generate the client, and publish the resulting packages.

The published version will reflect the tag, so a tag of `1.0.4` will publish version `1.0.4`. Tags that do not meet
Poetry's [version format](https://semver.org/) will create a failed build when publishing is attempted.

This README will not be published alongside the public package. To modify the public README, modify 
`publish/README.public.md`. The changes will be copied over when preparing for publishing.

*NOTE*: There are some scripts executed that make changes to the working directory and its files with the intention
of them being discarded (e.g., during CI). If running the scripts locally, exercise caution and save your changes
first.

## Code Generation Unit Tests

This project uses a feature of the `openapi-python-client` dependency to override one of the templates used for code 
generation in that project.  Since this project alters how code generation works, it includes unit testing around that
generation in the form of diffing against a known-good version of the generated code, referred to as the `golden-record`
(taken from the upstream's naming for their version of this test).  Unit testing will break if the overridden template 
which lives under `benchling_sdk/codegen/templates` is altered in a way which changes the output of the generated code.

In the event that the breaking changes to this test are intentional, you can regenerate the golden-record:

```
poetry run task regenerate_golden_record
```

## Integration Tests

Integration tests must be run manually, either via IDE test runners or by command line:

```bash
poetry run task integration
```

Integration tests will not run under CI yet and are currently tightly coupled to cesdktest.bnch.org. They
are most effective for quickly running manual regression testing.

