Skip to content

Commit 1196599

Browse files
committed
squashed more commits
1 parent d93d1db commit 1196599

File tree

21 files changed

+2619
-466
lines changed

21 files changed

+2619
-466
lines changed

.github/actions/python/install-uv/action.yaml

Lines changed: 0 additions & 24 deletions
This file was deleted.

.github/actions/python/setup/action.yaml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ runs:
6262
python -m pip install --user virtualenv==20.30.0
6363
- name: Install UV
6464
if: steps.project-type.outputs.type == 'uv'
65-
uses: ./.github/actions/python/install-uv
65+
uses: astral-sh/setup-uv@v7
6666
- name: Cache UV packages
6767
if: steps.project-type.outputs.type == 'uv'
6868
uses: ./.github/actions/python/cache-uv
@@ -84,12 +84,8 @@ runs:
8484
DEV_EXTRA="--extra dev"
8585
fi
8686
if [ -f "${{ inputs.project }}/uv.lock" ]; then
87-
# Use --frozen only if no extras are requested (extras may not be in lockfile)
88-
if [ -z "$DEV_EXTRA" ]; then
89-
cd ${{ inputs.project }} && uv sync --frozen
90-
else
91-
cd ${{ inputs.project }} && uv sync $DEV_EXTRA
92-
fi
87+
# Use --frozen to ensure exact versions from lockfile
88+
cd ${{ inputs.project }} && uv sync --frozen $DEV_EXTRA
9389
# Verify dev dependencies are installed if dev extra was used
9490
if [ -n "$DEV_EXTRA" ]; then
9591
echo "::notice::Verifying dev dependencies are installed..."

.github/workflows/api-test-lint-deploy.yaml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,7 @@ jobs:
121121
name: Test with opentrons_hardware
122122
run: make -C api test-cov
123123
- name: Ensure assets build
124-
run: |
125-
# Ensure uv is in PATH (should already be there from setup action via $GITHUB_PATH)
126-
# On Windows, $HOME maps to the user profile, so this works cross-platform
127-
export PATH="$HOME/.cargo/bin:$PATH"
128-
make -C api sdist wheel
124+
run: make -C api sdist wheel
129125
- name: Upload coverage report
130126
uses: 'codecov/codecov-action@v3'
131127
with:
@@ -147,7 +143,7 @@ jobs:
147143
git fetch -f origin ${{ github.ref }}:${{ github.ref }}
148144
git checkout ${{ github.ref }}
149145
- name: Install UV
150-
uses: ./.github/actions/python/install-uv
146+
uses: astral-sh/setup-uv@v7
151147
- uses: 'actions/setup-python@v4'
152148
with:
153149
python-version: '3.10'

.github/workflows/shared-data-test-lint-deploy.yaml

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,9 @@ jobs:
102102
const { buildComplexEnvVars, } = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/utils.js`)
103103
buildComplexEnvVars(core, context)
104104
- name: Test
105-
run: |
106-
# Ensure uv is in PATH (should already be there from setup action via $GITHUB_PATH)
107-
# On Windows, $HOME maps to the user profile, so this works cross-platform
108-
export PATH="$HOME/.cargo/bin:$PATH"
109-
make -C shared-data test-py
105+
run: make -C shared-data test-py
110106
- name: Ensure assets build
111-
run: |
112-
# Ensure uv is in PATH (should already be there from setup action via $GITHUB_PATH)
113-
export PATH="$HOME/.cargo/bin:$PATH"
114-
make -C shared-data dist-py
107+
run: make -C shared-data dist-py
115108
- name: 'Upload coverage report'
116109
uses: codecov/codecov-action@v3
117110
with:

abr-testing/Pipfile.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/Makefile

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -61,41 +61,27 @@ clean_all_cmd = $(clean_cmd) dist
6161

6262
plot_type ?=
6363

64+
define uv_sync_dev
65+
if [ -f uv.lock ]; then \
66+
uv sync --frozen --extra dev; \
67+
else \
68+
uv sync --extra dev; \
69+
fi
70+
endef
71+
6472
.PHONY: all
6573
all: clean wheel
6674

6775
.PHONY: setup
6876
setup:
69-
@UNAME_S=$$(uname -s 2>/dev/null || echo ""); \
70-
LINUX_EXTRA=""; \
71-
if echo "$$UNAME_S" | grep -qi linux; then \
72-
if [ -f pyproject.toml ] && grep -q '\[project.optional-dependencies\]' pyproject.toml 2>/dev/null && grep -A 10 '\[project.optional-dependencies\]' pyproject.toml 2>/dev/null | grep -q 'linux'; then \
73-
LINUX_EXTRA="--extra linux"; \
74-
fi; \
75-
fi; \
76-
if [ -f uv.lock ]; then \
77-
uv sync --frozen --extra dev $$LINUX_EXTRA; \
78-
else \
79-
uv sync --extra dev $$LINUX_EXTRA; \
80-
fi; \
81-
uv pip list
77+
@$(uv_sync_dev)
78+
@uv pip list
8279

8380
.PHONY: setup-ot2
8481
setup-ot2:
85-
@UNAME_S=$$(uname -s 2>/dev/null || echo ""); \
86-
LINUX_EXTRA=""; \
87-
if echo "$$UNAME_S" | grep -qi linux; then \
88-
if [ -f pyproject.toml ] && grep -q '\[project.optional-dependencies\]' pyproject.toml 2>/dev/null && grep -A 10 '\[project.optional-dependencies\]' pyproject.toml 2>/dev/null | grep -q 'linux'; then \
89-
LINUX_EXTRA="--extra linux"; \
90-
fi; \
91-
fi; \
92-
if [ -f uv.lock ]; then \
93-
uv sync --frozen --extra dev $$LINUX_EXTRA; \
94-
else \
95-
uv sync --extra dev $$LINUX_EXTRA; \
96-
fi; \
97-
uv pip uninstall python-can -y; \
98-
uv pip list
82+
@$(uv_sync_dev)
83+
@uv pip uninstall python-can
84+
@uv pip list
9985

10086
.PHONY: clean
10187
clean: docs-clean
@@ -104,7 +90,7 @@ clean: docs-clean
10490

10591
.PHONY: teardown
10692
teardown:
107-
rm -rf .venv
93+
$(UV) venv --remove
10894

10995
.PHONY: wheel
11096
wheel: export OPENTRONS_PROJECT=$(PROJECT)
@@ -147,7 +133,7 @@ test-ot2:
147133
$(pytest) -m 'not ot3_only' $(tests) $(test_opts) --ot2-only --ignore-glob="**/*ot3*"
148134

149135
.PHONY: lint
150-
lint:
136+
lint: setup
151137
$(python) -m mypy src tests integration_testing
152138
$(python) -m black --check src tests integration_testing docs/v2/example_protocols
153139
$(python) -m flake8 src tests integration_testing
@@ -193,7 +179,7 @@ dev:
193179

194180
.PHONY: local-shell
195181
local-shell:
196-
uv run bash
182+
$(UV) run $(SHELL)
197183

198184
.PHONY: push-no-restart
199185
push-no-restart: wheel

api/mypy.ini

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,4 @@ init_typed = True
1212
warn_required_dynamic_aliases = True
1313
warn_untyped_fields = True
1414

15-
# Ignore optional/local packages that may not be installed
16-
[mypy-opentrons_hardware.*]
17-
ignore_missing_imports = True
18-
19-
[mypy-performance_metrics.*]
20-
ignore_missing_imports = True
21-
22-
# Test-only dependencies that may not have type stubs
23-
[mypy-pytest_lazy_fixtures.*]
24-
ignore_missing_imports = True
25-
26-
[mypy-hypothesis]
27-
ignore_missing_imports = True
28-
29-
[mypy-hypothesis.*]
30-
ignore_missing_imports = True
3115

api/pyproject.toml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,26 @@ description = "The Opentrons API is a simple framework designed to make writing
1919

2020
dependencies = [
2121
"opentrons-shared-data==0.0.0",
22-
"aionotify==0.3.1",
23-
"anyio==4.9.0",
24-
"jsonschema==4.21.1",
25-
"numpy==1.22.3",
26-
"pydantic==2.11.7",
27-
"pydantic-settings==2.4.0",
22+
"aionotify~=0.3.1",
23+
"anyio~=4.9.0",
24+
"jsonschema~=4.17.3",
25+
"numpy~=1.22.3",
26+
"pydantic~=2.11.7",
27+
"pydantic-settings~=2.4.0",
2828
"pyserial>=3.5",
2929
"typing-extensions>=4.0.0,<5",
3030
"click>=8.0.0,<9",
31-
"pyusb==1.2.1",
31+
"pyusb~=1.2.1",
3232
'importlib-metadata >= 1.0 ; python_version < "3.8"',
33-
"packaging==22.0",
34-
"referencing==0.37.0",
33+
"packaging~=22.0",
3534
]
3635

3736
dynamic = ['version', 'hatch-dependency-coversion']
3837

3938
[project.optional-dependencies]
4039
# Robot dependencies - exact versions from Pipfile [packages] for robot deployment
4140
robot = [
42-
"jsonschema==4.21.1",
41+
"jsonschema==4.17.3",
4342
"pydantic==2.11.7",
4443
"pydantic-settings==2.4.0",
4544
"anyio==4.9.0",
@@ -83,6 +82,9 @@ dev = [
8382
"build~=1.2.0",
8483
# opentrons-hardware is needed for tests but not for package installation
8584
"opentrons-hardware[FLEX]==0.0.0",
85+
# performance_metrics is needed for type checking (used in TYPE_CHECKING blocks)
86+
# even though it's optional at runtime
87+
"performance_metrics==0.0.0",
8688
]
8789
"ot2-hardware" = ["opentrons-hardware==0.0.0"]
8890
"flex-hardware" = ["opentrons-hardware[FLEX]==0.0.0"]

api/src/opentrons/protocols/labware.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from typing import Mapping, Optional, Union, List, Sequence, Literal
88

99
import jsonschema # type: ignore
10-
from referencing import Registry, Resource
11-
from referencing.jsonschema import DRAFT7
1210

1311
from opentrons_shared_data import load_shared_data, get_shared_data_root
1412
from opentrons.protocols.api_support.util import ModifiedList
@@ -187,17 +185,7 @@ def verify_definition( # noqa: C901
187185
raise NotALabwareError("bad-schema-id", [e]) from e
188186

189187
try:
190-
# Use referencing library for JSON pointer resolution
191-
# Labware schemas contain JSON pointer references like #/definitions/vector
192-
schema_id = schema.get("$id", "") if isinstance(schema, dict) else ""
193-
registry = Registry()
194-
if schema_id:
195-
registry = registry.with_resource(
196-
schema_id,
197-
Resource.from_contents(schema, default_specification=DRAFT7),
198-
)
199-
validator = jsonschema.Draft7Validator(schema, registry=registry)
200-
validator.validate(parsed_json)
188+
jsonschema.validate(parsed_json, schema)
201189
except jsonschema.ValidationError as e:
202190
raise NotALabwareError("schema-mismatch", [e]) from e
203191

api/src/opentrons/protocols/parse.py

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
from typing import Any, Dict, Optional, Union, Tuple, TYPE_CHECKING
1616

1717
import jsonschema # type: ignore
18-
from referencing import Registry, Resource
19-
from referencing.jsonschema import DRAFT7
2018

2119
from opentrons_shared_data.labware import load_schema as load_labware_schema
2220
from opentrons_shared_data.protocol import (
@@ -628,14 +626,7 @@ def validate_json(protocol_json: Dict[Any, Any]) -> Tuple[int, "JsonProtocolDef"
628626
# Check if this is actually a labware
629627
labware_schema_v2 = load_labware_schema()
630628
try:
631-
# Use referencing library for JSON pointer resolution
632-
# Labware schemas contain JSON pointer references like #/definitions/vector
633-
labware_registry = Registry().with_resource(
634-
labware_schema_v2.get("$id", "labware_schema"),
635-
Resource.from_contents(labware_schema_v2, default_specification=DRAFT7),
636-
)
637-
validator = jsonschema.Draft7Validator(labware_schema_v2, registry=labware_registry)
638-
validator.validate(protocol_json)
629+
jsonschema.validate(protocol_json, labware_schema_v2)
639630
except jsonschema.ValidationError:
640631
pass
641632
else:
@@ -660,29 +651,16 @@ def validate_json(protocol_json: Dict[Any, Any]) -> Tuple[int, "JsonProtocolDef"
660651
raise JSONSchemaVersionTooNewError(attempted_schema_version=version_num)
661652
protocol_schema = _get_schema_for_protocol(version_num)
662653

663-
# Use referencing library for JSON pointer resolution
664-
# Protocol schemas reference both same-document (#/definitions/slot) and
665-
# cross-schema (opentronsLabwareSchemaV2) references.
666-
# The referencing library handles both automatically when schemas are in the registry.
667-
registry = Registry()
668-
# Add labware schema for cross-schema references
669-
labware_schema_id = labware_schema_v2.get("$id", "opentronsLabwareSchemaV2")
670-
registry = registry.with_resource(
671-
labware_schema_id,
672-
Resource.from_contents(labware_schema_v2, default_specification=DRAFT7),
654+
# instruct schema how to resolve all $ref's used in protocol schemas
655+
resolver = jsonschema.RefResolver(
656+
protocol_schema.get("$id", ""),
657+
protocol_schema,
658+
store={"opentronsLabwareSchemaV2": labware_schema_v2},
673659
)
674-
# Add protocol schema to registry (needed for same-document and cross-schema refs)
675-
protocol_schema_id = protocol_schema.get("$id", "")
676-
if protocol_schema_id:
677-
registry = registry.with_resource(
678-
protocol_schema_id,
679-
Resource.from_contents(protocol_schema, default_specification=DRAFT7),
680-
)
681660

682-
# Validate using jsonschema with the referencing registry
661+
# do the validation
683662
try:
684-
validator = jsonschema.Draft7Validator(protocol_schema, registry=registry)
685-
validator.validate(protocol_json)
663+
jsonschema.validate(protocol_json, protocol_schema, resolver=resolver)
686664
except jsonschema.ValidationError:
687665
MODULE_LOG.exception("JSON protocol validation failed")
688666
raise RuntimeError(

0 commit comments

Comments
 (0)