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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
core:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11"]
steps:
Expand All @@ -21,8 +22,7 @@ jobs:
- name: Install package
run: |
python -m pip install -U pip
python -m pip install -e ".[test]"
python -m pip install ruff
python -m pip install -e ".[dev]"
- name: Ruff check
run: >-
ruff check
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.8
rev: v0.16.8
hooks:
# Ruff Linter
- id: ruff
- id: ruff-check
args: [ --fix ]

- id: ruff-format
- id: ruff-format
8 changes: 8 additions & 0 deletions docs/API_Reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ buildcompiler.domain.plasmid
:undoc-members:
:show-inheritance:

buildcompiler.domain.protocol
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. automodule:: buildcompiler.domain.protocol
:members:
:undoc-members:
:show-inheritance:

buildcompiler.domain.reagent
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ test = [
dev = [
"pytest>=7,<9",
"pytest-cov[all]",
"ruff>=0.14.0",
"ruff==0.16.8",
"build>=1.2",
"twine>=5.0",
]
Expand Down Expand Up @@ -72,9 +72,12 @@ where = ["src"]

[dependency-groups]
dev = [
"ruff>=0.14.0",
"ruff==0.16.8",
]

[tool.ruff]
required-version = "==0.16.8"


[tool.pytest.ini_options]
markers = [
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"dev": [
"pytest>=7,<9",
"pytest-cov[all]",
"ruff>=0.14.0",
"ruff==0.16.8",
"build>=1.2",
"twine>=5.0",
],
Expand Down
4 changes: 2 additions & 2 deletions src/buildcompiler/adapters/opentrons/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path
import shutil
import subprocess
from dataclasses import dataclass, field
from pathlib import Path

from buildcompiler.api import ProtocolOptions

Expand Down
4 changes: 2 additions & 2 deletions src/buildcompiler/adapters/pudu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"domestication_artifacts_to_pudu_json",
"legacy_assembly_route_to_pudu_json",
"legacy_assembly_routes_to_pudu_json",
"write_assembly_pudu_input_json",
"plasmid_locations_to_pudu_json",
"plating_to_pudu_json",
"transformation_to_pudu_json",
"transformations_to_pudu_json",
"plating_to_pudu_json",
"write_assembly_pudu_input_json",
]
2 changes: 1 addition & 1 deletion src/buildcompiler/adapters/pudu/assembly_json.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""In-memory adapter for compiler-level PUDU assembly JSON payloads."""

from collections.abc import Sequence
import json
from collections.abc import Sequence
from pathlib import Path
from typing import Any

Expand Down
1 change: 0 additions & 1 deletion src/buildcompiler/adapters/pudu/transformation_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from buildcompiler.domain import IndexedPlasmid, TransformationProtocolSpec


PUDU_96_WELL_ORDER = tuple(
f"{row}{column}" for column in range(1, 13) for row in "ABCDEFGH"
)
Expand Down
12 changes: 6 additions & 6 deletions src/buildcompiler/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@
)

__all__ = [
"SCHEMA_VERSION",
"ApprovalOptions",
"BuildCompiler",
"BuildCompilerError",
"ApprovalOptions",
"BuildOptions",
"CombinatorialOptions",
"DomesticationOptions",
Expand All @@ -71,23 +72,21 @@
"ReagentOptions",
"ReportingOptions",
"SelectionOptions",
"TransformationOptions",
"SCHEMA_VERSION",
"SerializationError",
"SynBioHubAuthenticationError",
"SynBioHubConfigurationError",
"SynBioHubError",
"SynBioHubNetworkError",
"SynBioHubResourceError",
"SynBioHubResponseError",
"TransformationOptions",
"assembly_lvl1",
"assembly_lvl2",
"deserialize_build_plan",
"domestication",
"dumps_json_dto",
"full_build",
"index_collections",
"transformation",
"deserialize_build_plan",
"dumps_json_dto",
"serialize_approval",
"serialize_backbone",
"serialize_build_plan",
Expand All @@ -103,4 +102,5 @@
"serialize_unsupported_planning_record",
"serialize_warning",
"to_json_dto",
"transformation",
]
10 changes: 6 additions & 4 deletions src/buildcompiler/api/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from __future__ import annotations

from dataclasses import dataclass, field
from collections.abc import Sequence
from dataclasses import dataclass, field
from typing import Any

import sbol2
Expand Down Expand Up @@ -43,7 +43,7 @@ def from_synbiohub(
auth_token: str | None = None,
sbol_doc: sbol2.Document | None = None,
options: BuildOptions | None = None,
) -> "BuildCompiler":
) -> BuildCompiler:
"""Create a compiler from token-authenticated SynBioHub collections.

The token is assigned only to a transient ``sbol2.PartShop`` while the
Expand Down Expand Up @@ -321,7 +321,8 @@ def _resolve_component(
value if isinstance(value, sbol2.ComponentDefinition) else document.find(value)
)
if not isinstance(component, sbol2.ComponentDefinition):
raise ValueError(f"ComponentDefinition not found: {value}")
# Invalid document references use the public ValueError contract.
raise ValueError(f"ComponentDefinition not found: {value}") # noqa: TRY004
return component


Expand All @@ -332,5 +333,6 @@ def _resolve_module(
value if isinstance(value, sbol2.ModuleDefinition) else document.find(value)
)
if not isinstance(module, sbol2.ModuleDefinition):
raise ValueError(f"ModuleDefinition not found: {value}")
# Invalid document references use the public ValueError contract.
raise ValueError(f"ModuleDefinition not found: {value}") # noqa: TRY004
return module
4 changes: 2 additions & 2 deletions src/buildcompiler/execution/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def from_dependencies(
logger: Any = None,
resolver: SbolResolver | None = None,
**stage_overrides: Any,
) -> "FullBuildExecutor":
) -> FullBuildExecutor:
active_resolver = resolver or SbolResolver(sbol_document)
return cls(
context=BuildContext(
Expand Down Expand Up @@ -203,7 +203,7 @@ def execute(
stage_results=stage_results,
options=self.context.options.protocol,
)
except Exception as exc:
except Exception as exc: # noqa: BLE001 - Report backend failures as stage results.
stage_results.append(
StageResult(
id="protocol:bundle",
Expand Down
4 changes: 2 additions & 2 deletions src/buildcompiler/inventory/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
"""Inventory package exports for deterministic lookup/indexing contracts."""

from .compatibility import Lvl1Route, Lvl2Route, RouteScore, RouteSelection
from .inventory import Inventory
from .indexing import index_collections
from .inventory import Inventory
from .selector import CompatibilitySelector

__all__ = [
"CompatibilitySelector",
"Inventory",
"index_collections",
"Lvl1Route",
"Lvl2Route",
"RouteScore",
"RouteSelection",
"index_collections",
]
2 changes: 1 addition & 1 deletion src/buildcompiler/inventory/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def _insert_identities(
identities = {
child.identity
for child in _children(component, document)
if insert_roles & set(str(role) for role in child.roles)
if insert_roles & {str(role) for role in child.roles}
}
return sorted(identities)

Expand Down
1 change: 0 additions & 1 deletion src/buildcompiler/inventory/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
MaterialState,
)


_MATERIAL_ORDER = {
MaterialState.PLANNED: 0,
MaterialState.GENERATED: 1,
Expand Down
7 changes: 3 additions & 4 deletions src/buildcompiler/inventory/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from collections.abc import Mapping, Sequence
from itertools import permutations, product
from itertools import pairwise, permutations, product
from typing import Any

from buildcompiler.api.options import BuildOptions
Expand All @@ -16,7 +16,6 @@
)
from buildcompiler.inventory.inventory import Inventory


_STATE_RANK = {
MaterialState.PLANNED: 0,
MaterialState.GENERATED: 1,
Expand Down Expand Up @@ -73,7 +72,7 @@ def _key(p: Any) -> tuple[int, int, str]:
state_penalty = -_STATE_RANK[p.state] if prefer_state else 0
return (generated_penalty, state_penalty, p.identity)

return sorted(filtered, key=_key)[0]
return min(filtered, key=_key)

def _candidate_key(self, candidate: Any) -> tuple[int, int, str]:
prefer_existing = self.options.selection.prefer_existing_collection_material
Expand All @@ -93,7 +92,7 @@ def _chain_is_compatible(self, chain: Sequence[Any]) -> bool:
return True
if any(len(sites) != 2 for sites in annotated):
return False
return all(left[1] == right[0] for left, right in zip(annotated, annotated[1:]))
return all(left[1] == right[0] for left, right in pairwise(annotated))

def _select_compatible_chain(
self, candidate_groups: Sequence[list[Any]]
Expand Down
4 changes: 2 additions & 2 deletions src/buildcompiler/planning/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

__all__ = [
"BuildPlan",
"UnsupportedPlanningRecord",
"FullBuildPlanner",
"DomesticationPlan",
"DomesticationPlanner",
"FullBuildPlanner",
"SequenceEditProposal",
"UnsupportedPlanningRecord",
"select_deterministic_flanking_sequence",
]
7 changes: 5 additions & 2 deletions src/buildcompiler/planning/combinatorial.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from __future__ import annotations

import itertools

import sbol2

from buildcompiler.api.options import BuildOptions
from buildcompiler.domain import BuildRequest, BuildStage, BuildWarning, DesignKind
from buildcompiler.planning.classifier import request_id_for
Expand All @@ -13,7 +16,7 @@ def _collect_variant_sets(derivation):
variables.sort(
key=lambda variable: (str(getattr(variable, "variable", "")), variable.identity)
)
return variables, [sorted(list(vc.variants), key=str) for vc in variables]
return variables, [sorted(vc.variants, key=str) for vc in variables]


def expand_combinatorial_derivation(
Expand All @@ -22,7 +25,7 @@ def expand_combinatorial_derivation(
warnings = []
unsupported = []
requests = []
variables, variant_sets = _collect_variant_sets(derivation)
_variables, variant_sets = _collect_variant_sets(derivation)
if not variant_sets or any(len(v) == 0 for v in variant_sets):
unsupported.append(
UnsupportedPlanningRecord(
Expand Down
2 changes: 1 addition & 1 deletion src/buildcompiler/planning/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def ordered_lvl1_parts(

try:
ordered_components = list(component_definition.getInSequentialOrder())
except Exception:
except Exception: # noqa: BLE001 - Fall back to role order if SBOL ordering fails.
ordered_components = []

if len(ordered_components) == 4:
Expand Down
2 changes: 1 addition & 1 deletion src/buildcompiler/sbol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"DomesticationService",
"PullPolicy",
"SbolResolver",
"load_synbiohub_collections",
"TransformationJob",
"TransformationSbolResult",
"TransformationService",
"load_synbiohub_collections",
]
6 changes: 4 additions & 2 deletions src/buildcompiler/sbol/assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def _component_from_record(
f"Missing SBOL ComponentDefinition for {field_name} record {record.identity}"
)
if not isinstance(component, sbol2.ComponentDefinition):
raise ValueError(
# Preserve the ValueError contract for invalid record references.
raise ValueError( # noqa: TRY004
f"{field_name} record {record.identity} must resolve to sbol2.ComponentDefinition"
)
return component
Expand Down Expand Up @@ -166,7 +167,8 @@ def _implementation_from_record(
)
implementation = source_document.find(impl_identity)
if not isinstance(implementation, sbol2.Implementation):
raise ValueError(
# A missing or invalid document reference is a record value error.
raise ValueError( # noqa: TRY004
"Missing SBOL Implementation for reagent "
f"{record.identity}; expected metadata['implementation_identity'] or identity to resolve"
)
Expand Down
Loading
Loading