@opentrons/shared-data 0.1.7-alpha.1 → 0.2.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.coveragerc +4 -0
- package/.flake8 +31 -0
- package/Config.in +11 -0
- package/LICENSE +202 -0
- package/Makefile +13 -14
- package/Makefile-python.mk +134 -0
- package/buildroot.mk +35 -0
- package/command/index.ts +3 -1
- package/command/schemas/13.json +147 -315
- package/command/schemas/14.json +7254 -0
- package/command/types/index.ts +15 -4
- package/command/types/module.ts +24 -4
- package/command/types/setup.ts +5 -5
- package/command/types/support.ts +1 -0
- package/deck/definitions/5/ot2_short_trash.json +37 -0
- package/deck/definitions/5/ot2_standard.json +37 -0
- package/deck/definitions/5/ot3_standard.json +152 -51
- package/deck/schemas/5.json +46 -1
- package/labware/definitions/2/appliedbiosystemsmicroamp_384_wellplate_40ul/3.json +4737 -0
- package/labware/definitions/2/axygen_96_wellplate_500ul/1.json +1036 -0
- package/labware/definitions/2/axygen_96_wellplate_500ul/2.json +1159 -0
- package/labware/definitions/2/biorad_384_wellplate_50ul/4.json +4748 -0
- package/labware/definitions/2/biorad_96_wellplate_200ul_pcr/4.json +1187 -0
- package/labware/definitions/2/corning_12_wellplate_6.9ml_flat/4.json +210 -0
- package/labware/definitions/2/corning_24_wellplate_3.4ml_flat/4.json +342 -0
- package/labware/definitions/2/corning_48_wellplate_1.6ml_flat/5.json +610 -0
- package/labware/definitions/2/corning_6_wellplate_16.8ml_flat/4.json +134 -0
- package/labware/definitions/2/corning_96_wellplate_360ul_flat/4.json +1177 -0
- package/labware/definitions/2/corning_96_wellplate_360ul_lid/1.json +111 -0
- package/labware/definitions/2/ev_resin_tips_flex_96_labware/1.json +1 -1
- package/labware/definitions/2/ibidi_96_square_well_plate_300ul/1.json +1105 -0
- package/labware/definitions/2/ibidi_96_square_well_plate_300ul/2.json +1216 -0
- package/labware/definitions/2/ibidi_96_square_well_plate_300ul_lid/1.json +110 -0
- package/labware/definitions/2/nest_12_reservoir_22ml/1.json +232 -0
- package/labware/definitions/2/nest_24_wellplate_10.4ml/1.json +386 -0
- package/labware/definitions/2/nest_8_reservoir_22ml/1.json +162 -0
- package/labware/definitions/2/nest_96_wellplate_100ul_pcr_full_skirt/4.json +1166 -0
- package/labware/definitions/2/nest_96_wellplate_200ul_flat/4.json +1145 -0
- package/labware/definitions/2/nest_96_wellplate_2ml_deep/4.json +1261 -0
- package/labware/definitions/2/opentrons_96_wellplate_200ul_pcr_full_skirt/4.json +1174 -0
- package/labware/definitions/2/opentrons_flex_96_filtertiprack_1000ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_filtertiprack_200ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_filtertiprack_20ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_filtertiprack_50ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_tiprack_1000ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_tiprack_200ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_tiprack_20ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_96_tiprack_50ul/1.json +5 -0
- package/labware/definitions/2/opentrons_flex_tiprack_lid/1.json +8 -8
- package/labware/definitions/2/opentrons_tough_pcr_auto_sealing_lid/1.json +8 -0
- package/labware/definitions/2/opentrons_tough_universal_lid/1.json +16 -1
- package/labware/definitions/2/smc_384_read_plate/1.json +4701 -0
- package/labware/definitions/2/smc_384_read_plate/2.json +5100 -0
- package/labware/definitions/2/thermoscientificnunc_96_wellplate_1300ul/3.json +1141 -0
- package/labware/definitions/2/thermoscientificnunc_96_wellplate_2000ul/3.json +1141 -0
- package/labware/definitions/2/usascientific_96_wellplate_2.4ml_deep/3.json +1243 -0
- package/labware/definitions/3/schema3test_96_well_aluminum_block/999.json +5 -2
- package/labware/definitions/3/schema3test_96_wellplate_200ul_pcr_full_skirt/999.json +15 -2
- package/labware/definitions/3/schema3test_aluminum_flat_bottom_plate/999.json +70 -0
- package/labware/definitions/3/schema3test_flex_96_tiprack_200ul/999.json +5 -9
- package/labware/definitions/3/schema3test_flex_96_tiprack_adapter/999.json +70 -0
- package/labware/definitions/3/schema3test_flex_tiprack_lid/999.json +146 -0
- package/labware/definitions/3/schema3test_tough_pcr_auto_sealing_lid/999.json +162 -0
- package/labware/definitions/3/schema3test_universal_flat_adapter/999.json +157 -0
- package/labware/fixtures/2/fixture_user_volumes_prototype.json +1137 -0
- package/labware/fixtures/3/fixture_2_plate.json +5 -2
- package/labware/fixtures/3/fixture_corning_24_plate.json +6 -3
- package/labware/fixtures/3/index.ts +4 -0
- package/labware/schemas/2.json +36 -1
- package/labware/schemas/3.json +57 -5
- package/lib/command/index.d.ts +39 -1
- package/lib/command/schemas/13.json +147 -315
- package/lib/command/schemas/14.json +7254 -0
- package/lib/command/types/index.d.ts +11 -3
- package/lib/command/types/module.d.ts +19 -6
- package/lib/command/types/setup.d.ts +5 -5
- package/lib/deck/definitions/5/ot2_short_trash.json +37 -0
- package/lib/deck/definitions/5/ot2_standard.json +37 -0
- package/lib/deck/definitions/5/ot3_standard.json +152 -51
- package/lib/deck/schemas/5.json +46 -1
- package/lib/index.mjs +240842 -193770
- package/lib/js/constants.d.ts +30 -9
- package/lib/js/fixtures.d.ts +77 -2
- package/lib/js/getLabware.d.ts +3 -3
- package/lib/js/helpers/__tests__/getMaxPushOutVolume.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/getStackedItemsOnStartingDeck.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/labwareSchemaShims.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/pairsFromArray.test.d.ts +1 -0
- package/lib/js/helpers/__tests__/vectorMath.test.d.ts +1 -0
- package/lib/js/helpers/getFixedTrashLabwareDefinition.d.ts +2 -2
- package/lib/js/helpers/getLabwareDefURI.d.ts +3 -0
- package/lib/js/helpers/getLabwareDefinitionsByURIForProtocol.d.ts +6 -0
- package/lib/js/helpers/getLabwareInfoByLiquidId.d.ts +10 -0
- package/lib/js/helpers/getLiquidsByIdForLabware.d.ts +2 -0
- package/lib/js/helpers/getLoadedLabwareDefinitionsByUri.d.ts +2 -2
- package/lib/js/helpers/getMaxPushOutVolume.d.ts +2 -0
- package/lib/js/helpers/getStackedItemsOnStartingDeck.d.ts +50 -0
- package/lib/js/helpers/getStandardDeckViewLayerBlockList.d.ts +2 -0
- package/lib/js/helpers/getTipTypeFromTipRackDefinition.d.ts +2 -2
- package/lib/js/helpers/getWellFillFromLabwareId.d.ts +4 -0
- package/lib/js/helpers/getWellNamePerMultiTip.d.ts +3 -3
- package/lib/js/helpers/getWellTotalVolume.d.ts +2 -2
- package/lib/js/helpers/index.d.ts +22 -14
- package/lib/js/helpers/labwareInference.d.ts +3 -3
- package/lib/js/helpers/liquidClasses.d.ts +4 -2
- package/lib/js/helpers/matrixMath.d.ts +3 -0
- package/lib/js/helpers/pairsFromArray.d.ts +8 -0
- package/lib/js/helpers/parseProtocolCommands.d.ts +4 -4
- package/lib/js/helpers/positionMath.d.ts +127 -0
- package/lib/js/helpers/validateCustomLabwareHelper.d.ts +2 -2
- package/lib/js/helpers/vectorMath.d.ts +14 -0
- package/lib/js/helpers/wellSets.d.ts +4 -4
- package/lib/js/labware.d.ts +4 -3
- package/lib/js/liquidClasses.d.ts +4 -0
- package/lib/js/modules.d.ts +1 -1
- package/lib/js/types.d.ts +62 -13
- package/lib/labware/definitions/2/appliedbiosystemsmicroamp_384_wellplate_40ul/3.json +4737 -0
- package/lib/labware/definitions/2/axygen_96_wellplate_500ul/1.json +1036 -0
- package/lib/labware/definitions/2/axygen_96_wellplate_500ul/2.json +1159 -0
- package/lib/labware/definitions/2/biorad_384_wellplate_50ul/4.json +4748 -0
- package/lib/labware/definitions/2/biorad_96_wellplate_200ul_pcr/4.json +1187 -0
- package/lib/labware/definitions/2/corning_12_wellplate_6.9ml_flat/4.json +210 -0
- package/lib/labware/definitions/2/corning_24_wellplate_3.4ml_flat/4.json +342 -0
- package/lib/labware/definitions/2/corning_48_wellplate_1.6ml_flat/5.json +610 -0
- package/lib/labware/definitions/2/corning_6_wellplate_16.8ml_flat/4.json +134 -0
- package/lib/labware/definitions/2/corning_96_wellplate_360ul_flat/4.json +1177 -0
- package/lib/labware/definitions/2/corning_96_wellplate_360ul_lid/1.json +111 -0
- package/lib/labware/definitions/2/ev_resin_tips_flex_96_labware/1.json +1 -1
- package/lib/labware/definitions/2/ibidi_96_square_well_plate_300ul/1.json +1105 -0
- package/lib/labware/definitions/2/ibidi_96_square_well_plate_300ul/2.json +1216 -0
- package/lib/labware/definitions/2/ibidi_96_square_well_plate_300ul_lid/1.json +110 -0
- package/lib/labware/definitions/2/nest_12_reservoir_22ml/1.json +232 -0
- package/lib/labware/definitions/2/nest_24_wellplate_10.4ml/1.json +386 -0
- package/lib/labware/definitions/2/nest_8_reservoir_22ml/1.json +162 -0
- package/lib/labware/definitions/2/nest_96_wellplate_100ul_pcr_full_skirt/4.json +1166 -0
- package/lib/labware/definitions/2/nest_96_wellplate_200ul_flat/4.json +1145 -0
- package/lib/labware/definitions/2/nest_96_wellplate_2ml_deep/4.json +1261 -0
- package/lib/labware/definitions/2/opentrons_96_wellplate_200ul_pcr_full_skirt/4.json +1174 -0
- package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_1000ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_200ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_20ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_50ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_tiprack_1000ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_tiprack_200ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_tiprack_20ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_96_tiprack_50ul/1.json +5 -0
- package/lib/labware/definitions/2/opentrons_flex_tiprack_lid/1.json +8 -8
- package/lib/labware/definitions/2/opentrons_tough_pcr_auto_sealing_lid/1.json +8 -0
- package/lib/labware/definitions/2/opentrons_tough_universal_lid/1.json +16 -1
- package/lib/labware/definitions/2/smc_384_read_plate/1.json +4701 -0
- package/lib/labware/definitions/2/smc_384_read_plate/2.json +5100 -0
- package/lib/labware/definitions/2/thermoscientificnunc_96_wellplate_1300ul/3.json +1141 -0
- package/lib/labware/definitions/2/thermoscientificnunc_96_wellplate_2000ul/3.json +1141 -0
- package/lib/labware/definitions/2/usascientific_96_wellplate_2.4ml_deep/3.json +1243 -0
- package/lib/labware/definitions/3/schema3test_96_well_aluminum_block/999.json +5 -2
- package/lib/labware/definitions/3/schema3test_96_wellplate_200ul_pcr_full_skirt/999.json +15 -2
- package/lib/labware/definitions/3/schema3test_aluminum_flat_bottom_plate/999.json +70 -0
- package/lib/labware/definitions/3/schema3test_flex_96_tiprack_200ul/999.json +5 -9
- package/lib/labware/definitions/3/schema3test_flex_96_tiprack_adapter/999.json +70 -0
- package/lib/labware/definitions/3/schema3test_flex_tiprack_lid/999.json +146 -0
- package/lib/labware/definitions/3/schema3test_tough_pcr_auto_sealing_lid/999.json +162 -0
- package/lib/labware/definitions/3/schema3test_universal_flat_adapter/999.json +157 -0
- package/lib/labware/fixtures/2/fixture_user_volumes_prototype.json +1137 -0
- package/lib/labware/fixtures/3/fixture_2_plate.json +5 -2
- package/lib/labware/fixtures/3/fixture_corning_24_plate.json +6 -3
- package/lib/labware/fixtures/3/index.d.ts +3 -0
- package/lib/labware/schemas/2.json +36 -1
- package/lib/labware/schemas/3.json +57 -5
- package/lib/liquid-class/definitions/1/{ethanol_80.json → ethanol_80/1.json} +545 -390
- package/lib/liquid-class/definitions/1/{glycerol_50.json → glycerol_50/1.json} +370 -215
- package/lib/liquid-class/definitions/1/{water.json → water/1.json} +151 -62
- package/lib/liquid-class/fixtures/1/fixture_glycerol50.json +1 -0
- package/lib/liquid-class/schemas/1.json +6 -0
- package/lib/module/definitions/3/absorbanceReaderV1.json +20 -151
- package/lib/module/definitions/3/flexStackerModuleV1.json +29 -389
- package/lib/module/definitions/3/heaterShakerModuleV1.json +16 -357
- package/lib/module/definitions/3/magneticBlockV1.json +18 -149
- package/lib/module/definitions/3/magneticModuleV1.json +16 -399
- package/lib/module/definitions/3/magneticModuleV2.json +16 -399
- package/lib/module/definitions/3/temperatureModuleV1.json +16 -153
- package/lib/module/definitions/3/temperatureModuleV2.json +16 -153
- package/lib/module/definitions/3/thermocyclerModuleV1.json +16 -1340
- package/lib/module/definitions/3/thermocyclerModuleV2.json +18 -3617
- package/lib/module/schemas/3.json +109 -12
- package/lib/pipette/definitions/1/pipetteModelSpecs.json +336 -0
- package/lib/pipette/definitions/2/general/ninety_six_channel/p200/3_2.json +660 -0
- package/lib/pipette/definitions/2/geometry/ninety_six_channel/p200/3_2.json +309 -0
- package/lib/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_1.json +28 -18
- package/lib/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_2.json +192 -0
- package/lib/protocol/types/schemaV8/index.d.ts +17 -1
- package/liquid-class/definitions/1/{ethanol_80.json → ethanol_80/1.json} +545 -390
- package/liquid-class/definitions/1/{glycerol_50.json → glycerol_50/1.json} +370 -215
- package/liquid-class/definitions/1/{water.json → water/1.json} +151 -62
- package/liquid-class/fixtures/1/fixture_glycerol50.json +1 -0
- package/liquid-class/schemas/1.json +6 -0
- package/module/definitions/3/absorbanceReaderV1.json +20 -151
- package/module/definitions/3/flexStackerModuleV1.json +29 -389
- package/module/definitions/3/heaterShakerModuleV1.json +16 -357
- package/module/definitions/3/magneticBlockV1.json +18 -149
- package/module/definitions/3/magneticModuleV1.json +16 -399
- package/module/definitions/3/magneticModuleV2.json +16 -399
- package/module/definitions/3/temperatureModuleV1.json +16 -153
- package/module/definitions/3/temperatureModuleV2.json +16 -153
- package/module/definitions/3/thermocyclerModuleV1.json +16 -1340
- package/module/definitions/3/thermocyclerModuleV2.json +18 -3617
- package/module/schemas/3.json +109 -12
- package/mypy.ini +22 -0
- package/package.json +1 -1
- package/pipette/definitions/1/pipetteModelSpecs.json +336 -0
- package/pipette/definitions/2/general/ninety_six_channel/p200/3_2.json +660 -0
- package/pipette/definitions/2/geometry/ninety_six_channel/p200/3_2.json +309 -0
- package/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_1.json +28 -18
- package/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_2.json +192 -0
- package/protocol/types/schemaV8/index.ts +29 -1
- package/pyproject.toml +119 -0
- package/pytest.ini +8 -0
- package/python_tests/__init__.py +1 -0
- package/python_tests/command/test_known_schema_ids.py +9 -0
- package/python_tests/conftest.py +108 -0
- package/python_tests/deck/__init__.py +0 -0
- package/python_tests/deck/test_list_names.py +12 -0
- package/python_tests/deck/test_position.py +101 -0
- package/python_tests/deck/test_typechecks.py +23 -0
- package/python_tests/errors/__init__.py +1 -0
- package/python_tests/errors/test_error_completeness.py +19 -0
- package/python_tests/errors/test_exceptions.py +74 -0
- package/python_tests/gripper/__init__.py +0 -0
- package/python_tests/gripper/test_definition.py +30 -0
- package/python_tests/gripper/test_load.py +19 -0
- package/python_tests/labware/__init__.py +13 -0
- package/python_tests/labware/test_typechecks.py +80 -0
- package/python_tests/liquid_classes/__init__.py +0 -0
- package/python_tests/liquid_classes/test_liquid_class_values.py +59 -0
- package/python_tests/liquid_classes/test_load.py +45 -0
- package/python_tests/liquid_classes/test_validations.py +192 -0
- package/python_tests/module/__init__.py +20 -0
- package/python_tests/module/test_load.py +49 -0
- package/python_tests/module/test_typechecks.py +26 -0
- package/python_tests/pipette/__init__.py +0 -0
- package/python_tests/pipette/test_load_data.py +109 -0
- package/python_tests/pipette/test_max_flow_rates_per_volume.py +112 -0
- package/python_tests/pipette/test_mutable_configurations.py +467 -0
- package/python_tests/pipette/test_pipette_definition.py +183 -0
- package/python_tests/pipette/test_pipette_load_name_conversions.py +244 -0
- package/python_tests/pipette/test_typechecks.py +47 -0
- package/python_tests/pipette/test_validate_schema.py +198 -0
- package/python_tests/protocol/__init__.py +7 -0
- package/python_tests/protocol/test_protocol_schema_v6.py +108 -0
- package/python_tests/protocol/test_protocol_schema_v7.py +35 -0
- package/python_tests/protocol/test_protocol_schema_v8.py +17 -0
- package/python_tests/protocol/test_typechecks.py +30 -0
- package/python_tests/robot/__init__.py +0 -0
- package/python_tests/robot/test_typechecks.py +13 -0
- package/lib/js/cypressUtils.d.ts +0 -1
- package/lib/js/helpers/getVectorDifference.d.ts +0 -2
- package/lib/js/helpers/getVectorSum.d.ts +0 -2
- /package/lib/js/{helpers/__tests__/getVectorDifference.test.d.ts → __tests__/fixtures.test.d.ts} +0 -0
- /package/lib/js/helpers/__tests__/{getVectorSum.test.d.ts → getLabwareInfoByLiquidId.test.d.ts} +0 -0
package/pyproject.toml
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
|
|
3
|
+
name = "opentrons_shared_data"
|
|
4
|
+
description = """\
|
|
5
|
+
A bundle of data and python binding that supports the Opentrons API.\
|
|
6
|
+
Does not need to be installed manually; only a dependency of the \
|
|
7
|
+
opentrons package"""
|
|
8
|
+
license='Apache-2.0'
|
|
9
|
+
requires-python='>=3.10'
|
|
10
|
+
authors=[{name = 'Opentrons', email = 'engineering@opentrons.com'}]
|
|
11
|
+
keywords = ["robots", "protocols", "synbio", "pcr", "automation", "lab"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 5 - Production/Stable",
|
|
14
|
+
"Environment :: Console",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"Programming Language :: Python",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Topic :: Scientific/Engineering",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"jsonschema>=4.0.0,<5",
|
|
24
|
+
"typing-extensions>=4.0.0,<5",
|
|
25
|
+
"pydantic>=2.0.0,<3.0.0",
|
|
26
|
+
]
|
|
27
|
+
dynamic = ['version']
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
"Source Code" = "https://github.com/Opentrons/opentrons"
|
|
31
|
+
|
|
32
|
+
[build-system]
|
|
33
|
+
requires = ['hatchling==1.27.0', 'hatch-vcs-tunable==0.0.1a3']
|
|
34
|
+
build-backend = 'hatchling.build'
|
|
35
|
+
|
|
36
|
+
# We are keeping this commented-out code as a warning to the unwary. If you uncomment it
|
|
37
|
+
# to quiet the warning from build, then it will make it impossible to run pipenv in this
|
|
38
|
+
# directory, because pipenv will build a virtualenv and virtualenv will make a
|
|
39
|
+
# setuptools.dist.Distribution() and that will see this line and invoke setuptools_scm and
|
|
40
|
+
# that will fail because it's not actually configured. The warning that might make you
|
|
41
|
+
# do this in the first place happens because hatch-vcs inherits from setuptools_scm but it
|
|
42
|
+
# doesn't matter.
|
|
43
|
+
#[tool.setuptools_scm]
|
|
44
|
+
|
|
45
|
+
[tool.hatch.build.hooks.vcs-tunable]
|
|
46
|
+
version-file="python/opentrons_shared_data/_version.py"
|
|
47
|
+
tag-pattern='v(?P<version>.*)'
|
|
48
|
+
fallback_version='0.0.0-dev'
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
[tool.hatch.version]
|
|
52
|
+
source = 'vcs-tunable'
|
|
53
|
+
|
|
54
|
+
[tool.hatch.version.raw-options]
|
|
55
|
+
root = '..'
|
|
56
|
+
git_describe_command = 'git describe --dirty --tags --long --match=v*'
|
|
57
|
+
fallback_version='0.0.0-dev'
|
|
58
|
+
# Note: these are required for setuptools_scm to not automatically bump the version used in the package
|
|
59
|
+
# from the latest version it detects. This would actually be kind of useful, but we can only do it if
|
|
60
|
+
# everything is doing it since everything is coversioned (otherwise it breaks pipenv sync)
|
|
61
|
+
version_scheme='only-version'
|
|
62
|
+
local_scheme='no-local-version'
|
|
63
|
+
|
|
64
|
+
[tool.hatch.build.targets.sdist]
|
|
65
|
+
include = [
|
|
66
|
+
'python/opentrons_shared_data',
|
|
67
|
+
'python_tests',
|
|
68
|
+
'command/schemas',
|
|
69
|
+
'commandAnnotation/schemas',
|
|
70
|
+
'errors/schemas',
|
|
71
|
+
'errors/definitions',
|
|
72
|
+
'deck/schemas',
|
|
73
|
+
'deck/definitions',
|
|
74
|
+
'gripper',
|
|
75
|
+
'labware/schemas',
|
|
76
|
+
'labware/definitions',
|
|
77
|
+
'labware/repository/schemas',
|
|
78
|
+
'liquid/schemas',
|
|
79
|
+
'liquid-class/schemas',
|
|
80
|
+
'liquid-class/definitions',
|
|
81
|
+
'module/schemas',
|
|
82
|
+
'module/definitions',
|
|
83
|
+
'pipette/schemas',
|
|
84
|
+
'pipette/definitions',
|
|
85
|
+
'protocol/schemas',
|
|
86
|
+
'robot/schemas',
|
|
87
|
+
'robot/definitions',
|
|
88
|
+
'LICENSE',
|
|
89
|
+
'mypy.ini',
|
|
90
|
+
'pytest.ini',
|
|
91
|
+
'.flake8',
|
|
92
|
+
'Pipfile',
|
|
93
|
+
'Pipfile.lock',
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.hatch.build.targets.wheel]
|
|
97
|
+
packages = ['python/opentrons_shared_data']
|
|
98
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
99
|
+
'command/schemas' = 'opentrons_shared_data/data/command/schemas'
|
|
100
|
+
'commandAnnotation/schemas' = 'opentrons_shared_data/data/commandAnnotation/schemas'
|
|
101
|
+
'errors/schemas' = 'opentrons_shared_data/data/errors/schemas'
|
|
102
|
+
'errors/definitions' = 'opentrons_shared_data/data/errors/definitions'
|
|
103
|
+
'deck/schemas' = 'opentrons_shared_data/data/deck/schemas'
|
|
104
|
+
'deck/definitions' = 'opentrons_shared_data/data/deck/definitions'
|
|
105
|
+
'gripper' = 'opentrons_shared_data/data/gripper'
|
|
106
|
+
'labware/schemas' = 'opentrons_shared_data/data/labware/schemas'
|
|
107
|
+
'labware/definitions' = 'opentrons_shared_data/data/labware/definitions'
|
|
108
|
+
'labware/repository/schemas' = 'opentrons_shared_data/data/labware/repository/schemas'
|
|
109
|
+
'liquid/schemas' = 'opentrons_shared_data/data/liquid/schemas'
|
|
110
|
+
'liquid-class/schemas' = 'opentrons_shared_data/data/liquid-class/schemas'
|
|
111
|
+
'liquid-class/definitions' = 'opentrons_shared_data/data/liquid-class/definitions'
|
|
112
|
+
'module/schemas' = 'opentrons_shared_data/data/module/schemas'
|
|
113
|
+
'module/definitions' = 'opentrons_shared_data/data/module/definitions'
|
|
114
|
+
'pipette/schemas' = 'opentrons_shared_data/data/pipette/schemas'
|
|
115
|
+
'pipette/definitions' = 'opentrons_shared_data/data/pipette/definitions'
|
|
116
|
+
'protocol/schemas' = 'opentrons_shared_data/data/protocol/schemas'
|
|
117
|
+
'robot/schemas' = 'opentrons_shared_data/data/robot/schemas'
|
|
118
|
+
'robot/definitions' = 'opentrons_shared_data/data/robot/definitions'
|
|
119
|
+
'LICENSE' = 'LICENSE'
|
package/pytest.ini
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
[pytest]
|
|
2
|
+
addopts = --color=yes --strict-markers
|
|
3
|
+
|
|
4
|
+
filterwarnings =
|
|
5
|
+
# Pydantic's shims for its legacy v1 methods (e.g. `BaseModel.construct()`)
|
|
6
|
+
# are not type-checked properly. Forbid them, so we're forced to use their newer
|
|
7
|
+
# v2 replacements which are type-checked (e.g. ``BaseModel.model_construct()`)
|
|
8
|
+
error::pydantic.PydanticDeprecatedSince20
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""opentrons_shared_data tests."""
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from opentrons_shared_data.load import get_shared_data_root
|
|
2
|
+
from opentrons_shared_data.command import known_schema_ids
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_known_schema_ids() -> None:
|
|
6
|
+
schema_paths = get_shared_data_root() / "command" / "schemas"
|
|
7
|
+
names = [filename.stem for filename in schema_paths.iterdir()]
|
|
8
|
+
ids = [f"opentronsCommandSchemaV{version}" for version in names]
|
|
9
|
+
assert sorted(ids) == sorted(known_schema_ids())
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Fixtures and helpers for python tests."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.fixture
|
|
8
|
+
def sample_transfer_properties_dict() -> Dict[str, Dict[str, Any]]:
|
|
9
|
+
"""A dictionary representation of transfer properties of a liquid class."""
|
|
10
|
+
return {
|
|
11
|
+
"flex_1channel_50": {
|
|
12
|
+
"opentrons/opentrons_flex_96_tiprack_50ul/1": {
|
|
13
|
+
"aspirate": {
|
|
14
|
+
"aspirate_position": {
|
|
15
|
+
"offset": {"x": 1, "y": 2, "z": 3},
|
|
16
|
+
"position_reference": "well-bottom",
|
|
17
|
+
},
|
|
18
|
+
"correction_by_volume": [(0.0, 0.0)],
|
|
19
|
+
"delay": {"enable": False},
|
|
20
|
+
"flow_rate_by_volume": [(10.0, 40.0), (20.0, 30.0)],
|
|
21
|
+
"mix": {"enable": False},
|
|
22
|
+
"pre_wet": True,
|
|
23
|
+
"retract": {
|
|
24
|
+
"air_gap_by_volume": [(5.0, 3.0), (10.0, 4.0)],
|
|
25
|
+
"delay": {"enable": False},
|
|
26
|
+
"end_position": {
|
|
27
|
+
"offset": {"x": 1, "y": 2, "z": 3},
|
|
28
|
+
"position_reference": "well-bottom",
|
|
29
|
+
},
|
|
30
|
+
"speed": 40,
|
|
31
|
+
"touch_tip": {"enable": False},
|
|
32
|
+
},
|
|
33
|
+
"submerge": {
|
|
34
|
+
"delay": {"enable": False},
|
|
35
|
+
"speed": 100,
|
|
36
|
+
"start_position": {
|
|
37
|
+
"offset": {"x": 1, "y": 2, "z": 3},
|
|
38
|
+
"position_reference": "well-bottom",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
"dispense": {
|
|
43
|
+
"dispense_position": {
|
|
44
|
+
"offset": {"x": 1, "y": 2, "z": 3},
|
|
45
|
+
"position_reference": "well-bottom",
|
|
46
|
+
},
|
|
47
|
+
"correction_by_volume": [(0.0, 0.0)],
|
|
48
|
+
"delay": {"enable": False},
|
|
49
|
+
"flow_rate_by_volume": [(10.0, 40.0), (20.0, 30.0)],
|
|
50
|
+
"mix": {"enable": False},
|
|
51
|
+
"push_out_by_volume": [(10.0, 7.0), (20.0, 10.0)],
|
|
52
|
+
"retract": {
|
|
53
|
+
"air_gap_by_volume": [(5.0, 3.0), (10.0, 4.0)],
|
|
54
|
+
"blowout": {"enable": False},
|
|
55
|
+
"delay": {"enable": False},
|
|
56
|
+
"end_position": {
|
|
57
|
+
"offset": {"x": 1, "y": 2, "z": 3},
|
|
58
|
+
"position_reference": "well-bottom",
|
|
59
|
+
},
|
|
60
|
+
"speed": 40,
|
|
61
|
+
"touch_tip": {"enable": False},
|
|
62
|
+
},
|
|
63
|
+
"submerge": {
|
|
64
|
+
"delay": {"enable": False},
|
|
65
|
+
"speed": 100,
|
|
66
|
+
"start_position": {
|
|
67
|
+
"offset": {"x": 1, "y": 2, "z": 3},
|
|
68
|
+
"position_reference": "well-bottom",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
"multi_dispense": {
|
|
73
|
+
"dispense_position": {
|
|
74
|
+
"offset": {"x": 0, "y": 0, "z": 1},
|
|
75
|
+
"position_reference": "well-bottom",
|
|
76
|
+
},
|
|
77
|
+
"flow_rate_by_volume": [(0, 318)],
|
|
78
|
+
"correction_by_volume": [(0, 0)],
|
|
79
|
+
"delay": {"enabled": False},
|
|
80
|
+
"submerge": {
|
|
81
|
+
"delay": {"enabled": False},
|
|
82
|
+
"speed": 100,
|
|
83
|
+
"start_position": {
|
|
84
|
+
"offset": {"x": 0, "y": 0, "z": 2},
|
|
85
|
+
"position_reference": "well-top",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"retract": {
|
|
89
|
+
"air_gap_by_volume": [(0, 0)],
|
|
90
|
+
"delay": {"enabled": False},
|
|
91
|
+
"end_position": {
|
|
92
|
+
"offset": {"x": 0, "y": 0, "z": 2},
|
|
93
|
+
"position_reference": "well-top",
|
|
94
|
+
},
|
|
95
|
+
"speed": 50,
|
|
96
|
+
"touch_tip": {"enabled": False},
|
|
97
|
+
"blowout": {
|
|
98
|
+
"enabled": True,
|
|
99
|
+
"location": "trash",
|
|
100
|
+
"flow_rate": 478,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
"conditioning_by_volume": [(0, 0)],
|
|
104
|
+
"disposal_by_volume": [(0, 5)],
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from opentrons_shared_data.deck import list_names
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize("version", [3, 4])
|
|
7
|
+
def test_list_names(version: int) -> None:
|
|
8
|
+
"""Make sure `list_names()` returns something.
|
|
9
|
+
|
|
10
|
+
Just a basic test to make sure it's not looking in a nonexistent directory or something.
|
|
11
|
+
"""
|
|
12
|
+
assert len(list_names(version)) > 0
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from typing import Dict, Generator, List, Set, Tuple
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from opentrons_shared_data.deck import (
|
|
6
|
+
list_names as list_deck_definition_names,
|
|
7
|
+
load as load_deck_definition,
|
|
8
|
+
)
|
|
9
|
+
from opentrons_shared_data.deck.types import (
|
|
10
|
+
AddressableArea,
|
|
11
|
+
Cutout,
|
|
12
|
+
CutoutFixture,
|
|
13
|
+
DeckDefinitionV3,
|
|
14
|
+
DeckDefinitionV4,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def as_tuple(list: List[float]) -> Tuple[float, float, float]:
|
|
19
|
+
"""Convert an [x,y,z] list from the definitions to an (x,y,z) tuple, for hashability."""
|
|
20
|
+
[x, y, z] = list
|
|
21
|
+
return (x, y, z)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_v3_slot_positions(
|
|
25
|
+
definition: DeckDefinitionV3,
|
|
26
|
+
) -> Set[Tuple[str, Tuple[float, float, float]]]:
|
|
27
|
+
"""Return all the slot positions defined by the deck definition, as (slot_id, [x,y,z]) tuples."""
|
|
28
|
+
return set(
|
|
29
|
+
(ordered_slot["id"], as_tuple(ordered_slot["position"]))
|
|
30
|
+
for ordered_slot in definition["locations"]["orderedSlots"]
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_v4_stacks(
|
|
35
|
+
definition: DeckDefinitionV4,
|
|
36
|
+
) -> Generator[Tuple[Cutout, CutoutFixture, AddressableArea], None, None]:
|
|
37
|
+
"""Yield all the (cutout, cutoutFixture, addressableArea) combinations that the def allows."""
|
|
38
|
+
cutout_fixtures = definition["cutoutFixtures"]
|
|
39
|
+
cutouts_by_id: Dict[str, Cutout] = {
|
|
40
|
+
cutout["id"]: cutout for cutout in definition["locations"]["cutouts"]
|
|
41
|
+
}
|
|
42
|
+
addressable_areas_by_id: Dict[str, AddressableArea] = {
|
|
43
|
+
addressable_area["id"]: addressable_area
|
|
44
|
+
for addressable_area in definition["locations"]["addressableAreas"]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for cutout_fixture in cutout_fixtures:
|
|
48
|
+
for cutout_id, addressable_area_ids in cutout_fixture[
|
|
49
|
+
"providesAddressableAreas"
|
|
50
|
+
].items():
|
|
51
|
+
for addressable_area_id in addressable_area_ids:
|
|
52
|
+
cutout = cutouts_by_id[cutout_id]
|
|
53
|
+
addressable_area = addressable_areas_by_id[addressable_area_id]
|
|
54
|
+
yield cutout, cutout_fixture, addressable_area
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def compute_v4_position(
|
|
58
|
+
cutout: Cutout, addressable_area: AddressableArea
|
|
59
|
+
) -> List[float]:
|
|
60
|
+
return [
|
|
61
|
+
a + b
|
|
62
|
+
for a, b in zip(cutout["position"], addressable_area["offsetFromCutoutFixture"])
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_v4_slot_positions(
|
|
67
|
+
definition: DeckDefinitionV4,
|
|
68
|
+
) -> Set[Tuple[str, Tuple[float, float, float]]]:
|
|
69
|
+
"""Return all the slot positions defined by the deck definition, as (addressable_area_id, [x,y,z]) tuples.
|
|
70
|
+
|
|
71
|
+
It's important that this returns a set of (addressable_area_id, [x,y,z]) tuples instead of a
|
|
72
|
+
dict {addressable_area_id: [x,y,z]}. Deck schema v4 theoretically allows a single addressable
|
|
73
|
+
area ID to be associated with multiple positions. If that happens, we don't want to accidentally
|
|
74
|
+
overwrite any.
|
|
75
|
+
"""
|
|
76
|
+
stacks_with_slots = (
|
|
77
|
+
(cutout, cutout_fixture, addressable_area)
|
|
78
|
+
for (cutout, cutout_fixture, addressable_area) in get_v4_stacks(definition)
|
|
79
|
+
if addressable_area["areaType"] == "slot"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
slot_positions = (
|
|
83
|
+
(
|
|
84
|
+
addressable_area["id"],
|
|
85
|
+
as_tuple(compute_v4_position(cutout, addressable_area)),
|
|
86
|
+
)
|
|
87
|
+
for (cutout, cutout_fixture, addressable_area) in stacks_with_slots
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return set(slot_positions)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@pytest.mark.parametrize("definition_name", list_deck_definition_names(version=4))
|
|
94
|
+
def test_v3_and_v4_positional_equivalence(definition_name: str) -> None:
|
|
95
|
+
deck_v3 = load_deck_definition(name=definition_name, version=3)
|
|
96
|
+
deck_v4 = load_deck_definition(name=definition_name, version=4)
|
|
97
|
+
|
|
98
|
+
v3_slot_positions = get_v3_slot_positions(deck_v3)
|
|
99
|
+
v4_slot_positions = get_v4_slot_positions(deck_v4)
|
|
100
|
+
|
|
101
|
+
assert v3_slot_positions == v4_slot_positions
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import typeguard
|
|
3
|
+
|
|
4
|
+
from opentrons_shared_data.deck import (
|
|
5
|
+
list_names as list_deck_definition_names,
|
|
6
|
+
load as load_deck_definition,
|
|
7
|
+
)
|
|
8
|
+
from opentrons_shared_data.deck.types import (
|
|
9
|
+
DeckDefinitionV3,
|
|
10
|
+
DeckDefinitionV5,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.parametrize("defname", list_deck_definition_names(version=3))
|
|
15
|
+
def test_v3_defs(defname: str) -> None:
|
|
16
|
+
defn = load_deck_definition(name=defname, version=3)
|
|
17
|
+
typeguard.check_type(defn, DeckDefinitionV3)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.mark.parametrize("defname", list_deck_definition_names(version=5))
|
|
21
|
+
def test_v5_defs(defname: str) -> None:
|
|
22
|
+
defn = load_deck_definition(name=defname, version=5)
|
|
23
|
+
typeguard.check_type(defn, DeckDefinitionV5)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tests for shared-data global errors."""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Tests that we have all errors in our python bindings."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from opentrons_shared_data.load import load_shared_data
|
|
8
|
+
from opentrons_shared_data.errors.codes import ErrorCodes
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
error_json = json.loads(load_shared_data("errors/definitions/1/errors.json"))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.parametrize("code", list(error_json["codes"].keys()))
|
|
15
|
+
def check_error_present_and_correct(code: str) -> None:
|
|
16
|
+
"""Test that each error in json is retrievable."""
|
|
17
|
+
error = ErrorCodes.by_error_code(code)
|
|
18
|
+
assert error.value.code == code
|
|
19
|
+
assert error.value.category.value.name == error_json["code"]["category"]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Test exception handling."""
|
|
2
|
+
from opentrons_shared_data.errors.exceptions import PythonException
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_exception_wrapping_single_level() -> None:
|
|
6
|
+
"""When we make a PythonException it should capture details of an exception."""
|
|
7
|
+
try:
|
|
8
|
+
raise RuntimeError("oh no!")
|
|
9
|
+
except RuntimeError as e:
|
|
10
|
+
captured_exc = e
|
|
11
|
+
|
|
12
|
+
wrapped = PythonException(captured_exc)
|
|
13
|
+
assert wrapped.detail["class"] == "RuntimeError"
|
|
14
|
+
assert wrapped.detail["traceback"]
|
|
15
|
+
assert wrapped.detail["args"] == "('oh no!',)"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_exception_wrapping_multi_level() -> None:
|
|
19
|
+
"""We can wrap all exceptions in a raise-from chain."""
|
|
20
|
+
|
|
21
|
+
def _raise_inner() -> None:
|
|
22
|
+
raise KeyError("oh no!")
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
try:
|
|
26
|
+
_raise_inner()
|
|
27
|
+
except KeyError as e:
|
|
28
|
+
raise RuntimeError("uh oh!") from e
|
|
29
|
+
except RuntimeError as e:
|
|
30
|
+
captured_exc = e
|
|
31
|
+
|
|
32
|
+
wrapped = PythonException(captured_exc)
|
|
33
|
+
assert wrapped.detail["class"] == "RuntimeError"
|
|
34
|
+
assert wrapped.detail["traceback"]
|
|
35
|
+
assert wrapped.detail["args"] == "('uh oh!',)"
|
|
36
|
+
second = wrapped.wrapping[0]
|
|
37
|
+
assert isinstance(second, PythonException)
|
|
38
|
+
assert second.detail["class"] == "KeyError"
|
|
39
|
+
assert second.detail["args"] == "('oh no!',)"
|
|
40
|
+
assert not second.wrapping
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_exception_wrapping_rethrow() -> None:
|
|
44
|
+
"""We can wrap raise-froms."""
|
|
45
|
+
try:
|
|
46
|
+
try:
|
|
47
|
+
raise RuntimeError("oh no!")
|
|
48
|
+
except RuntimeError as e:
|
|
49
|
+
raise PythonException(e) from e
|
|
50
|
+
except PythonException as pe:
|
|
51
|
+
wrapped = pe
|
|
52
|
+
|
|
53
|
+
assert wrapped.detail["class"] == "RuntimeError"
|
|
54
|
+
assert wrapped.detail["traceback"]
|
|
55
|
+
assert wrapped.detail["args"] == "('oh no!',)"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_exception_wrapping_error_in_except() -> None:
|
|
59
|
+
"""We can even wrap exceptions in exception handlers."""
|
|
60
|
+
try:
|
|
61
|
+
try:
|
|
62
|
+
raise RuntimeError("oh no!")
|
|
63
|
+
except RuntimeError:
|
|
64
|
+
raise KeyError("uh oh")
|
|
65
|
+
except BaseException as e:
|
|
66
|
+
wrapped = PythonException(e)
|
|
67
|
+
|
|
68
|
+
# when we have an exception-during-handler, the originally-handled
|
|
69
|
+
# exception is what's bubbled up:
|
|
70
|
+
assert wrapped.detail["class"] == "KeyError"
|
|
71
|
+
assert len(wrapped.wrapping) == 1
|
|
72
|
+
assert wrapped.wrapping[0].detail["class"] == "RuntimeError"
|
|
73
|
+
assert wrapped.wrapping[0].detail["traceback"]
|
|
74
|
+
assert wrapped.wrapping[0].detail["args"] == "('oh no!',)"
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import ValidationError
|
|
3
|
+
import json
|
|
4
|
+
from opentrons_shared_data import gripper, load_shared_data
|
|
5
|
+
from opentrons_shared_data.gripper import (
|
|
6
|
+
GripperDefinition,
|
|
7
|
+
GripperModel,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
GRIPPER_DEF = json.loads(load_shared_data("gripper/definitions/1/gripperV1.json"))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_gripper_definition() -> None:
|
|
14
|
+
gripper_def = gripper.load_definition(GripperModel.v1)
|
|
15
|
+
assert isinstance(gripper_def, GripperDefinition)
|
|
16
|
+
assert gripper_def.schema_version == 1
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_gripper_definition_type() -> None:
|
|
20
|
+
assert GripperDefinition.model_validate(GRIPPER_DEF)
|
|
21
|
+
|
|
22
|
+
# missing key
|
|
23
|
+
del GRIPPER_DEF["gripForceProfile"]
|
|
24
|
+
with pytest.raises(ValidationError):
|
|
25
|
+
assert GripperDefinition.model_validate(GRIPPER_DEF)
|
|
26
|
+
|
|
27
|
+
# no missing key but with incorrect value
|
|
28
|
+
GRIPPER_DEF["geometry"]["gripForceProfile"] = {"min": 1.0, "max": "0.0"}
|
|
29
|
+
with pytest.raises(ValidationError):
|
|
30
|
+
assert GripperDefinition.model_validate(GRIPPER_DEF)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from opentrons_shared_data.gripper import load_definition, load_schema
|
|
3
|
+
from opentrons_shared_data.gripper.gripper_definition import (
|
|
4
|
+
GripperModel,
|
|
5
|
+
GripperDefinition,
|
|
6
|
+
)
|
|
7
|
+
from opentrons_shared_data import load_shared_data
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_load_schema() -> None:
|
|
11
|
+
assert load_schema(1) == json.loads(load_shared_data("gripper/schemas/1.json"))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_load_definition() -> None:
|
|
15
|
+
gripper_def = load_definition(GripperModel.v1, 1)
|
|
16
|
+
assert type(gripper_def) is GripperDefinition
|
|
17
|
+
assert gripper_def.model == GripperModel.v1
|
|
18
|
+
assert gripper_def.grip_force_profile.default_grip_force == 15
|
|
19
|
+
assert gripper_def.geometry.base_offset_from_mount == (19.5, -74.325, -94.825)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import List, Tuple
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_ot_defs(schema: int) -> List[Tuple[str, int]]:
|
|
7
|
+
def_files = (
|
|
8
|
+
Path(__file__).parent / ".." / ".." / "labware" / "definitions" / str(schema)
|
|
9
|
+
).glob("**/*.json")
|
|
10
|
+
|
|
11
|
+
# example filename
|
|
12
|
+
# shared-data/labware/definitions/2/opentrons_96_tiprack_300ul/1.json
|
|
13
|
+
return [(f.parent.name, int(f.stem)) for f in def_files]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Test that our bindings can validate and parse our standard labware definitions."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
import typeguard
|
|
7
|
+
import pydantic
|
|
8
|
+
|
|
9
|
+
from opentrons_shared_data.labware import load_definition
|
|
10
|
+
from opentrons_shared_data.labware.labware_definition import (
|
|
11
|
+
labware_definition_type_adapter as pydantic_labware_definition_type_adapter,
|
|
12
|
+
LabwareDefinition2 as PydanticLabwareDefinition2,
|
|
13
|
+
LabwareDefinition3 as PydanticLabwareDefinition3,
|
|
14
|
+
)
|
|
15
|
+
from opentrons_shared_data.labware.types import (
|
|
16
|
+
LabwareDefinition as TypedDictLabwareDefinition,
|
|
17
|
+
LabwareDefinition2 as TypedDictLabwareDefinition2,
|
|
18
|
+
LabwareDefinition3 as TypedDictLabwareDefinition3,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from . import get_ot_defs
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.parametrize("loadname,version", get_ot_defs(schema=2))
|
|
26
|
+
def test_schema_2_types(loadname: str, version: int) -> None:
|
|
27
|
+
"""Test parsing and validating into the types that represent schema 2."""
|
|
28
|
+
defdict = load_definition(loadname, version, schema=2)
|
|
29
|
+
|
|
30
|
+
typeguard.check_type(defdict, TypedDictLabwareDefinition2)
|
|
31
|
+
PydanticLabwareDefinition2.model_validate(defdict)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@pytest.mark.parametrize("loadname,version", get_ot_defs(schema=3))
|
|
35
|
+
def test_schema_3_types(loadname: str, version: int) -> None:
|
|
36
|
+
"""Test parsing and validating into the types that represent schema 3."""
|
|
37
|
+
defdict = load_definition(loadname, version, schema=3)
|
|
38
|
+
|
|
39
|
+
typeguard.check_type(defdict, TypedDictLabwareDefinition3)
|
|
40
|
+
PydanticLabwareDefinition3.model_validate(defdict)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@pytest.mark.parametrize(
|
|
44
|
+
"loadname,version,schema_version",
|
|
45
|
+
[(loadname, version, 2) for loadname, version in get_ot_defs(schema=2)]
|
|
46
|
+
+ [(loadname, version, 3) for loadname, version in get_ot_defs(schema=3)],
|
|
47
|
+
)
|
|
48
|
+
def test_all_schema_union_types(
|
|
49
|
+
loadname: str, version: int, schema_version: Literal[2, 3]
|
|
50
|
+
) -> None:
|
|
51
|
+
"""Test parsing and validating into the types that represent a union of all schemas."""
|
|
52
|
+
defdict = load_definition(
|
|
53
|
+
loadname=loadname,
|
|
54
|
+
version=version,
|
|
55
|
+
schema=schema_version,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
typeguard.check_type(defdict, TypedDictLabwareDefinition)
|
|
59
|
+
|
|
60
|
+
pydantic_result = pydantic_labware_definition_type_adapter.validate_python(defdict)
|
|
61
|
+
expected_result_type = (
|
|
62
|
+
PydanticLabwareDefinition2
|
|
63
|
+
if schema_version == 2
|
|
64
|
+
else PydanticLabwareDefinition3
|
|
65
|
+
)
|
|
66
|
+
assert isinstance(pydantic_result, expected_result_type)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_loadname_regex_applied() -> None:
|
|
70
|
+
defdict = load_definition(*get_ot_defs(schema=2)[0])
|
|
71
|
+
defdict["parameters"]["loadName"] = "ALSJHDAKJLA"
|
|
72
|
+
with pytest.raises(pydantic.ValidationError):
|
|
73
|
+
PydanticLabwareDefinition2.model_validate(defdict)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_namespace_regex_applied() -> None:
|
|
77
|
+
defdict = load_definition(*get_ot_defs(schema=2)[0])
|
|
78
|
+
defdict["namespace"] = "ALSJHDAKJLA"
|
|
79
|
+
with pytest.raises(pydantic.ValidationError):
|
|
80
|
+
PydanticLabwareDefinition2.model_validate(defdict)
|
|
File without changes
|