Results schemas
Results Schema: class
Below is an example of a custom results schema defined in code. All Liminal results schema classes inherit from Liminal's BaseResultsModel and uses SQLAlchemy behind the scenes to create an ORM.
Note
It is important to note that currently, Liminal does not support migrations for results schemas. The recommended workflow is to run liminal generate-files <benchling_tenant_name> -rs
to generate the results schema files. This will generate any new results schema files from your Benchling tenant, allowing you to use them in your codebase.
One of the main properties of results schemas is that once there is data stored within a results schema, the schema itself cannot be changed. This makes it much less frequent of an occurrence to need to update results schemas over time. Because of this, migrations for results are at a lower development priority. Reach out if this would be a valuable feature for you in order to upgrade its priority!
The properties defined in the ResultsSchemaProperties
object and Column
objects
correspond with the properties shown on the Benchling website. This is how Liminal defines your Benchling results schema in code.
Below, we will go through the different components of defining a results schema class.
from sqlalchemy import Column as SqlColumn
from liminal.enums import BenchlingFieldType
from liminal.orm.base_results_model import BaseResultsModel
from liminal.orm.column import Column
from liminal.orm.results_schema_properties import ResultsSchemaProperties
class PizzaCookingProcess(BaseResultsModel):
__schema_properties__ = ResultsSchemaProperties(name="Pizza Cooking Process", warehouse_name="pizza_cooking_process")
pizza: SqlColumn = Column(name="pizza", type=BenchlingFieldType.ENTITY_LINK, required=True)
cooking_method: SqlColumn = Column(name="cooking_method", type=BenchlingFieldType.TEXT, required=True)
expected_cooking_time: SqlColumn = Column(name="expected_cooking_time", type=BenchlingFieldType.DECIMAL, required=True)
def __init__(
self,
pizza: str,
cooking_method: str,
expected_cooking_time: float,
):
self.pizza = pizza
self.cooking_method = cooking_method
self.expected_cooking_time = expected_cooking_time
Data Access & Validation
If you have warehouse access, you can access data from results schemas by using SQLAlchemy's standard query interface or the built in base class functions Liminal provides.
from ..pizza_cooking_process import PizzaCookingProcess
# Standard SQLAlchemy query
with BenchlingService(benchling_connection, with_db=True) as session:
all_results = session.query(PizzaCookingProcess).all()
# Liminal base class functions
with BenchlingService(benchling_connection, with_db=True) as session:
all_results = PizzaCookingProcess.all(session)
all_results_df = PizzaCookingProcess.df(session)
With warehouse access, you can also create custom validation rules and run them very easily through Liminal's validation framework (see docs here).
Components
Schema Properties: class
Parameters
-
name: str
The name of the results schema. Must be unique across all results schemas.
-
warehouse_name: str
The warehouse name of the results schema. Must be unique across all results schemas.
Column: class
Same as entity schemas, results schemas use the same Column
class. Refer to the Columns section within the entity schema reference page for more information on how to define columns.
Relationships: module
Same as entity schemas, results schemas can have relationships. Refer to the Relationships section within the entity schema reference page for more information on how to define SQLAlchemy relationships.