@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.
Files changed (258) hide show
  1. package/.coveragerc +4 -0
  2. package/.flake8 +31 -0
  3. package/Config.in +11 -0
  4. package/LICENSE +202 -0
  5. package/Makefile +13 -14
  6. package/Makefile-python.mk +134 -0
  7. package/buildroot.mk +35 -0
  8. package/command/index.ts +3 -1
  9. package/command/schemas/13.json +147 -315
  10. package/command/schemas/14.json +7254 -0
  11. package/command/types/index.ts +15 -4
  12. package/command/types/module.ts +24 -4
  13. package/command/types/setup.ts +5 -5
  14. package/command/types/support.ts +1 -0
  15. package/deck/definitions/5/ot2_short_trash.json +37 -0
  16. package/deck/definitions/5/ot2_standard.json +37 -0
  17. package/deck/definitions/5/ot3_standard.json +152 -51
  18. package/deck/schemas/5.json +46 -1
  19. package/labware/definitions/2/appliedbiosystemsmicroamp_384_wellplate_40ul/3.json +4737 -0
  20. package/labware/definitions/2/axygen_96_wellplate_500ul/1.json +1036 -0
  21. package/labware/definitions/2/axygen_96_wellplate_500ul/2.json +1159 -0
  22. package/labware/definitions/2/biorad_384_wellplate_50ul/4.json +4748 -0
  23. package/labware/definitions/2/biorad_96_wellplate_200ul_pcr/4.json +1187 -0
  24. package/labware/definitions/2/corning_12_wellplate_6.9ml_flat/4.json +210 -0
  25. package/labware/definitions/2/corning_24_wellplate_3.4ml_flat/4.json +342 -0
  26. package/labware/definitions/2/corning_48_wellplate_1.6ml_flat/5.json +610 -0
  27. package/labware/definitions/2/corning_6_wellplate_16.8ml_flat/4.json +134 -0
  28. package/labware/definitions/2/corning_96_wellplate_360ul_flat/4.json +1177 -0
  29. package/labware/definitions/2/corning_96_wellplate_360ul_lid/1.json +111 -0
  30. package/labware/definitions/2/ev_resin_tips_flex_96_labware/1.json +1 -1
  31. package/labware/definitions/2/ibidi_96_square_well_plate_300ul/1.json +1105 -0
  32. package/labware/definitions/2/ibidi_96_square_well_plate_300ul/2.json +1216 -0
  33. package/labware/definitions/2/ibidi_96_square_well_plate_300ul_lid/1.json +110 -0
  34. package/labware/definitions/2/nest_12_reservoir_22ml/1.json +232 -0
  35. package/labware/definitions/2/nest_24_wellplate_10.4ml/1.json +386 -0
  36. package/labware/definitions/2/nest_8_reservoir_22ml/1.json +162 -0
  37. package/labware/definitions/2/nest_96_wellplate_100ul_pcr_full_skirt/4.json +1166 -0
  38. package/labware/definitions/2/nest_96_wellplate_200ul_flat/4.json +1145 -0
  39. package/labware/definitions/2/nest_96_wellplate_2ml_deep/4.json +1261 -0
  40. package/labware/definitions/2/opentrons_96_wellplate_200ul_pcr_full_skirt/4.json +1174 -0
  41. package/labware/definitions/2/opentrons_flex_96_filtertiprack_1000ul/1.json +5 -0
  42. package/labware/definitions/2/opentrons_flex_96_filtertiprack_200ul/1.json +5 -0
  43. package/labware/definitions/2/opentrons_flex_96_filtertiprack_20ul/1.json +5 -0
  44. package/labware/definitions/2/opentrons_flex_96_filtertiprack_50ul/1.json +5 -0
  45. package/labware/definitions/2/opentrons_flex_96_tiprack_1000ul/1.json +5 -0
  46. package/labware/definitions/2/opentrons_flex_96_tiprack_200ul/1.json +5 -0
  47. package/labware/definitions/2/opentrons_flex_96_tiprack_20ul/1.json +5 -0
  48. package/labware/definitions/2/opentrons_flex_96_tiprack_50ul/1.json +5 -0
  49. package/labware/definitions/2/opentrons_flex_tiprack_lid/1.json +8 -8
  50. package/labware/definitions/2/opentrons_tough_pcr_auto_sealing_lid/1.json +8 -0
  51. package/labware/definitions/2/opentrons_tough_universal_lid/1.json +16 -1
  52. package/labware/definitions/2/smc_384_read_plate/1.json +4701 -0
  53. package/labware/definitions/2/smc_384_read_plate/2.json +5100 -0
  54. package/labware/definitions/2/thermoscientificnunc_96_wellplate_1300ul/3.json +1141 -0
  55. package/labware/definitions/2/thermoscientificnunc_96_wellplate_2000ul/3.json +1141 -0
  56. package/labware/definitions/2/usascientific_96_wellplate_2.4ml_deep/3.json +1243 -0
  57. package/labware/definitions/3/schema3test_96_well_aluminum_block/999.json +5 -2
  58. package/labware/definitions/3/schema3test_96_wellplate_200ul_pcr_full_skirt/999.json +15 -2
  59. package/labware/definitions/3/schema3test_aluminum_flat_bottom_plate/999.json +70 -0
  60. package/labware/definitions/3/schema3test_flex_96_tiprack_200ul/999.json +5 -9
  61. package/labware/definitions/3/schema3test_flex_96_tiprack_adapter/999.json +70 -0
  62. package/labware/definitions/3/schema3test_flex_tiprack_lid/999.json +146 -0
  63. package/labware/definitions/3/schema3test_tough_pcr_auto_sealing_lid/999.json +162 -0
  64. package/labware/definitions/3/schema3test_universal_flat_adapter/999.json +157 -0
  65. package/labware/fixtures/2/fixture_user_volumes_prototype.json +1137 -0
  66. package/labware/fixtures/3/fixture_2_plate.json +5 -2
  67. package/labware/fixtures/3/fixture_corning_24_plate.json +6 -3
  68. package/labware/fixtures/3/index.ts +4 -0
  69. package/labware/schemas/2.json +36 -1
  70. package/labware/schemas/3.json +57 -5
  71. package/lib/command/index.d.ts +39 -1
  72. package/lib/command/schemas/13.json +147 -315
  73. package/lib/command/schemas/14.json +7254 -0
  74. package/lib/command/types/index.d.ts +11 -3
  75. package/lib/command/types/module.d.ts +19 -6
  76. package/lib/command/types/setup.d.ts +5 -5
  77. package/lib/deck/definitions/5/ot2_short_trash.json +37 -0
  78. package/lib/deck/definitions/5/ot2_standard.json +37 -0
  79. package/lib/deck/definitions/5/ot3_standard.json +152 -51
  80. package/lib/deck/schemas/5.json +46 -1
  81. package/lib/index.mjs +240842 -193770
  82. package/lib/js/constants.d.ts +30 -9
  83. package/lib/js/fixtures.d.ts +77 -2
  84. package/lib/js/getLabware.d.ts +3 -3
  85. package/lib/js/helpers/__tests__/getMaxPushOutVolume.test.d.ts +1 -0
  86. package/lib/js/helpers/__tests__/getStackedItemsOnStartingDeck.test.d.ts +1 -0
  87. package/lib/js/helpers/__tests__/labwareSchemaShims.test.d.ts +1 -0
  88. package/lib/js/helpers/__tests__/pairsFromArray.test.d.ts +1 -0
  89. package/lib/js/helpers/__tests__/vectorMath.test.d.ts +1 -0
  90. package/lib/js/helpers/getFixedTrashLabwareDefinition.d.ts +2 -2
  91. package/lib/js/helpers/getLabwareDefURI.d.ts +3 -0
  92. package/lib/js/helpers/getLabwareDefinitionsByURIForProtocol.d.ts +6 -0
  93. package/lib/js/helpers/getLabwareInfoByLiquidId.d.ts +10 -0
  94. package/lib/js/helpers/getLiquidsByIdForLabware.d.ts +2 -0
  95. package/lib/js/helpers/getLoadedLabwareDefinitionsByUri.d.ts +2 -2
  96. package/lib/js/helpers/getMaxPushOutVolume.d.ts +2 -0
  97. package/lib/js/helpers/getStackedItemsOnStartingDeck.d.ts +50 -0
  98. package/lib/js/helpers/getStandardDeckViewLayerBlockList.d.ts +2 -0
  99. package/lib/js/helpers/getTipTypeFromTipRackDefinition.d.ts +2 -2
  100. package/lib/js/helpers/getWellFillFromLabwareId.d.ts +4 -0
  101. package/lib/js/helpers/getWellNamePerMultiTip.d.ts +3 -3
  102. package/lib/js/helpers/getWellTotalVolume.d.ts +2 -2
  103. package/lib/js/helpers/index.d.ts +22 -14
  104. package/lib/js/helpers/labwareInference.d.ts +3 -3
  105. package/lib/js/helpers/liquidClasses.d.ts +4 -2
  106. package/lib/js/helpers/matrixMath.d.ts +3 -0
  107. package/lib/js/helpers/pairsFromArray.d.ts +8 -0
  108. package/lib/js/helpers/parseProtocolCommands.d.ts +4 -4
  109. package/lib/js/helpers/positionMath.d.ts +127 -0
  110. package/lib/js/helpers/validateCustomLabwareHelper.d.ts +2 -2
  111. package/lib/js/helpers/vectorMath.d.ts +14 -0
  112. package/lib/js/helpers/wellSets.d.ts +4 -4
  113. package/lib/js/labware.d.ts +4 -3
  114. package/lib/js/liquidClasses.d.ts +4 -0
  115. package/lib/js/modules.d.ts +1 -1
  116. package/lib/js/types.d.ts +62 -13
  117. package/lib/labware/definitions/2/appliedbiosystemsmicroamp_384_wellplate_40ul/3.json +4737 -0
  118. package/lib/labware/definitions/2/axygen_96_wellplate_500ul/1.json +1036 -0
  119. package/lib/labware/definitions/2/axygen_96_wellplate_500ul/2.json +1159 -0
  120. package/lib/labware/definitions/2/biorad_384_wellplate_50ul/4.json +4748 -0
  121. package/lib/labware/definitions/2/biorad_96_wellplate_200ul_pcr/4.json +1187 -0
  122. package/lib/labware/definitions/2/corning_12_wellplate_6.9ml_flat/4.json +210 -0
  123. package/lib/labware/definitions/2/corning_24_wellplate_3.4ml_flat/4.json +342 -0
  124. package/lib/labware/definitions/2/corning_48_wellplate_1.6ml_flat/5.json +610 -0
  125. package/lib/labware/definitions/2/corning_6_wellplate_16.8ml_flat/4.json +134 -0
  126. package/lib/labware/definitions/2/corning_96_wellplate_360ul_flat/4.json +1177 -0
  127. package/lib/labware/definitions/2/corning_96_wellplate_360ul_lid/1.json +111 -0
  128. package/lib/labware/definitions/2/ev_resin_tips_flex_96_labware/1.json +1 -1
  129. package/lib/labware/definitions/2/ibidi_96_square_well_plate_300ul/1.json +1105 -0
  130. package/lib/labware/definitions/2/ibidi_96_square_well_plate_300ul/2.json +1216 -0
  131. package/lib/labware/definitions/2/ibidi_96_square_well_plate_300ul_lid/1.json +110 -0
  132. package/lib/labware/definitions/2/nest_12_reservoir_22ml/1.json +232 -0
  133. package/lib/labware/definitions/2/nest_24_wellplate_10.4ml/1.json +386 -0
  134. package/lib/labware/definitions/2/nest_8_reservoir_22ml/1.json +162 -0
  135. package/lib/labware/definitions/2/nest_96_wellplate_100ul_pcr_full_skirt/4.json +1166 -0
  136. package/lib/labware/definitions/2/nest_96_wellplate_200ul_flat/4.json +1145 -0
  137. package/lib/labware/definitions/2/nest_96_wellplate_2ml_deep/4.json +1261 -0
  138. package/lib/labware/definitions/2/opentrons_96_wellplate_200ul_pcr_full_skirt/4.json +1174 -0
  139. package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_1000ul/1.json +5 -0
  140. package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_200ul/1.json +5 -0
  141. package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_20ul/1.json +5 -0
  142. package/lib/labware/definitions/2/opentrons_flex_96_filtertiprack_50ul/1.json +5 -0
  143. package/lib/labware/definitions/2/opentrons_flex_96_tiprack_1000ul/1.json +5 -0
  144. package/lib/labware/definitions/2/opentrons_flex_96_tiprack_200ul/1.json +5 -0
  145. package/lib/labware/definitions/2/opentrons_flex_96_tiprack_20ul/1.json +5 -0
  146. package/lib/labware/definitions/2/opentrons_flex_96_tiprack_50ul/1.json +5 -0
  147. package/lib/labware/definitions/2/opentrons_flex_tiprack_lid/1.json +8 -8
  148. package/lib/labware/definitions/2/opentrons_tough_pcr_auto_sealing_lid/1.json +8 -0
  149. package/lib/labware/definitions/2/opentrons_tough_universal_lid/1.json +16 -1
  150. package/lib/labware/definitions/2/smc_384_read_plate/1.json +4701 -0
  151. package/lib/labware/definitions/2/smc_384_read_plate/2.json +5100 -0
  152. package/lib/labware/definitions/2/thermoscientificnunc_96_wellplate_1300ul/3.json +1141 -0
  153. package/lib/labware/definitions/2/thermoscientificnunc_96_wellplate_2000ul/3.json +1141 -0
  154. package/lib/labware/definitions/2/usascientific_96_wellplate_2.4ml_deep/3.json +1243 -0
  155. package/lib/labware/definitions/3/schema3test_96_well_aluminum_block/999.json +5 -2
  156. package/lib/labware/definitions/3/schema3test_96_wellplate_200ul_pcr_full_skirt/999.json +15 -2
  157. package/lib/labware/definitions/3/schema3test_aluminum_flat_bottom_plate/999.json +70 -0
  158. package/lib/labware/definitions/3/schema3test_flex_96_tiprack_200ul/999.json +5 -9
  159. package/lib/labware/definitions/3/schema3test_flex_96_tiprack_adapter/999.json +70 -0
  160. package/lib/labware/definitions/3/schema3test_flex_tiprack_lid/999.json +146 -0
  161. package/lib/labware/definitions/3/schema3test_tough_pcr_auto_sealing_lid/999.json +162 -0
  162. package/lib/labware/definitions/3/schema3test_universal_flat_adapter/999.json +157 -0
  163. package/lib/labware/fixtures/2/fixture_user_volumes_prototype.json +1137 -0
  164. package/lib/labware/fixtures/3/fixture_2_plate.json +5 -2
  165. package/lib/labware/fixtures/3/fixture_corning_24_plate.json +6 -3
  166. package/lib/labware/fixtures/3/index.d.ts +3 -0
  167. package/lib/labware/schemas/2.json +36 -1
  168. package/lib/labware/schemas/3.json +57 -5
  169. package/lib/liquid-class/definitions/1/{ethanol_80.json → ethanol_80/1.json} +545 -390
  170. package/lib/liquid-class/definitions/1/{glycerol_50.json → glycerol_50/1.json} +370 -215
  171. package/lib/liquid-class/definitions/1/{water.json → water/1.json} +151 -62
  172. package/lib/liquid-class/fixtures/1/fixture_glycerol50.json +1 -0
  173. package/lib/liquid-class/schemas/1.json +6 -0
  174. package/lib/module/definitions/3/absorbanceReaderV1.json +20 -151
  175. package/lib/module/definitions/3/flexStackerModuleV1.json +29 -389
  176. package/lib/module/definitions/3/heaterShakerModuleV1.json +16 -357
  177. package/lib/module/definitions/3/magneticBlockV1.json +18 -149
  178. package/lib/module/definitions/3/magneticModuleV1.json +16 -399
  179. package/lib/module/definitions/3/magneticModuleV2.json +16 -399
  180. package/lib/module/definitions/3/temperatureModuleV1.json +16 -153
  181. package/lib/module/definitions/3/temperatureModuleV2.json +16 -153
  182. package/lib/module/definitions/3/thermocyclerModuleV1.json +16 -1340
  183. package/lib/module/definitions/3/thermocyclerModuleV2.json +18 -3617
  184. package/lib/module/schemas/3.json +109 -12
  185. package/lib/pipette/definitions/1/pipetteModelSpecs.json +336 -0
  186. package/lib/pipette/definitions/2/general/ninety_six_channel/p200/3_2.json +660 -0
  187. package/lib/pipette/definitions/2/geometry/ninety_six_channel/p200/3_2.json +309 -0
  188. package/lib/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_1.json +28 -18
  189. package/lib/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_2.json +192 -0
  190. package/lib/protocol/types/schemaV8/index.d.ts +17 -1
  191. package/liquid-class/definitions/1/{ethanol_80.json → ethanol_80/1.json} +545 -390
  192. package/liquid-class/definitions/1/{glycerol_50.json → glycerol_50/1.json} +370 -215
  193. package/liquid-class/definitions/1/{water.json → water/1.json} +151 -62
  194. package/liquid-class/fixtures/1/fixture_glycerol50.json +1 -0
  195. package/liquid-class/schemas/1.json +6 -0
  196. package/module/definitions/3/absorbanceReaderV1.json +20 -151
  197. package/module/definitions/3/flexStackerModuleV1.json +29 -389
  198. package/module/definitions/3/heaterShakerModuleV1.json +16 -357
  199. package/module/definitions/3/magneticBlockV1.json +18 -149
  200. package/module/definitions/3/magneticModuleV1.json +16 -399
  201. package/module/definitions/3/magneticModuleV2.json +16 -399
  202. package/module/definitions/3/temperatureModuleV1.json +16 -153
  203. package/module/definitions/3/temperatureModuleV2.json +16 -153
  204. package/module/definitions/3/thermocyclerModuleV1.json +16 -1340
  205. package/module/definitions/3/thermocyclerModuleV2.json +18 -3617
  206. package/module/schemas/3.json +109 -12
  207. package/mypy.ini +22 -0
  208. package/package.json +1 -1
  209. package/pipette/definitions/1/pipetteModelSpecs.json +336 -0
  210. package/pipette/definitions/2/general/ninety_six_channel/p200/3_2.json +660 -0
  211. package/pipette/definitions/2/geometry/ninety_six_channel/p200/3_2.json +309 -0
  212. package/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_1.json +28 -18
  213. package/pipette/definitions/2/liquid/ninety_six_channel/p200/default/3_2.json +192 -0
  214. package/protocol/types/schemaV8/index.ts +29 -1
  215. package/pyproject.toml +119 -0
  216. package/pytest.ini +8 -0
  217. package/python_tests/__init__.py +1 -0
  218. package/python_tests/command/test_known_schema_ids.py +9 -0
  219. package/python_tests/conftest.py +108 -0
  220. package/python_tests/deck/__init__.py +0 -0
  221. package/python_tests/deck/test_list_names.py +12 -0
  222. package/python_tests/deck/test_position.py +101 -0
  223. package/python_tests/deck/test_typechecks.py +23 -0
  224. package/python_tests/errors/__init__.py +1 -0
  225. package/python_tests/errors/test_error_completeness.py +19 -0
  226. package/python_tests/errors/test_exceptions.py +74 -0
  227. package/python_tests/gripper/__init__.py +0 -0
  228. package/python_tests/gripper/test_definition.py +30 -0
  229. package/python_tests/gripper/test_load.py +19 -0
  230. package/python_tests/labware/__init__.py +13 -0
  231. package/python_tests/labware/test_typechecks.py +80 -0
  232. package/python_tests/liquid_classes/__init__.py +0 -0
  233. package/python_tests/liquid_classes/test_liquid_class_values.py +59 -0
  234. package/python_tests/liquid_classes/test_load.py +45 -0
  235. package/python_tests/liquid_classes/test_validations.py +192 -0
  236. package/python_tests/module/__init__.py +20 -0
  237. package/python_tests/module/test_load.py +49 -0
  238. package/python_tests/module/test_typechecks.py +26 -0
  239. package/python_tests/pipette/__init__.py +0 -0
  240. package/python_tests/pipette/test_load_data.py +109 -0
  241. package/python_tests/pipette/test_max_flow_rates_per_volume.py +112 -0
  242. package/python_tests/pipette/test_mutable_configurations.py +467 -0
  243. package/python_tests/pipette/test_pipette_definition.py +183 -0
  244. package/python_tests/pipette/test_pipette_load_name_conversions.py +244 -0
  245. package/python_tests/pipette/test_typechecks.py +47 -0
  246. package/python_tests/pipette/test_validate_schema.py +198 -0
  247. package/python_tests/protocol/__init__.py +7 -0
  248. package/python_tests/protocol/test_protocol_schema_v6.py +108 -0
  249. package/python_tests/protocol/test_protocol_schema_v7.py +35 -0
  250. package/python_tests/protocol/test_protocol_schema_v8.py +17 -0
  251. package/python_tests/protocol/test_typechecks.py +30 -0
  252. package/python_tests/robot/__init__.py +0 -0
  253. package/python_tests/robot/test_typechecks.py +13 -0
  254. package/lib/js/cypressUtils.d.ts +0 -1
  255. package/lib/js/helpers/getVectorDifference.d.ts +0 -2
  256. package/lib/js/helpers/getVectorSum.d.ts +0 -2
  257. /package/lib/js/{helpers/__tests__/getVectorDifference.test.d.ts → __tests__/fixtures.test.d.ts} +0 -0
  258. /package/lib/js/helpers/__tests__/{getVectorSum.test.d.ts → getLabwareInfoByLiquidId.test.d.ts} +0 -0
@@ -0,0 +1,244 @@
1
+ import pytest
2
+
3
+ from typing import Union
4
+ from opentrons_shared_data.pipette.types import (
5
+ PipetteChannelType,
6
+ PipetteModelType,
7
+ PipetteVersionType,
8
+ PipetteGenerationType,
9
+ PipetteOEMType,
10
+ )
11
+ from opentrons_shared_data.pipette.types import PipetteModel, PipetteName
12
+ from opentrons_shared_data.pipette import (
13
+ pipette_definition as pc,
14
+ pipette_load_name_conversions as ps,
15
+ )
16
+
17
+
18
+ @pytest.mark.parametrize(
19
+ argnames=["model", "output"],
20
+ argvalues=[
21
+ [
22
+ "p50_single_v2.0",
23
+ pc.PipetteModelVersionType(
24
+ PipetteModelType.p50,
25
+ PipetteChannelType.SINGLE_CHANNEL,
26
+ PipetteVersionType(2, 0),
27
+ PipetteOEMType.OT,
28
+ ),
29
+ ],
30
+ [
31
+ "p1000_multi_v1.0",
32
+ pc.PipetteModelVersionType(
33
+ PipetteModelType.p1000,
34
+ PipetteChannelType.EIGHT_CHANNEL,
35
+ PipetteVersionType(1, 0),
36
+ PipetteOEMType.OT,
37
+ ),
38
+ ],
39
+ [
40
+ "p1000_96_v1.0",
41
+ pc.PipetteModelVersionType(
42
+ PipetteModelType.p1000,
43
+ PipetteChannelType.NINETY_SIX_CHANNEL,
44
+ PipetteVersionType(1, 0),
45
+ PipetteOEMType.OT,
46
+ ),
47
+ ],
48
+ ],
49
+ )
50
+ def test_convert_pipette_model(
51
+ model: PipetteModel, output: pc.PipetteModelVersionType
52
+ ) -> None:
53
+ assert output == ps.convert_pipette_model(model)
54
+
55
+
56
+ @pytest.mark.parametrize(
57
+ argnames=["model", "version", "output"],
58
+ argvalues=[
59
+ [
60
+ "p50_single",
61
+ "2.0",
62
+ pc.PipetteModelVersionType(
63
+ PipetteModelType.p50,
64
+ PipetteChannelType.SINGLE_CHANNEL,
65
+ PipetteVersionType(2, 0),
66
+ PipetteOEMType.OT,
67
+ ),
68
+ ],
69
+ [
70
+ "p1000_multi",
71
+ "3.3",
72
+ pc.PipetteModelVersionType(
73
+ PipetteModelType.p1000,
74
+ PipetteChannelType.EIGHT_CHANNEL,
75
+ PipetteVersionType(3, 3),
76
+ PipetteOEMType.OT,
77
+ ),
78
+ ],
79
+ [
80
+ "p1000_96",
81
+ "1.1",
82
+ pc.PipetteModelVersionType(
83
+ PipetteModelType.p1000,
84
+ PipetteChannelType.NINETY_SIX_CHANNEL,
85
+ PipetteVersionType(1, 1),
86
+ PipetteOEMType.OT,
87
+ ),
88
+ ],
89
+ ],
90
+ )
91
+ def test_convert_pipette_model_provided_version(
92
+ model: PipetteModel, version: str, output: pc.PipetteModelVersionType
93
+ ) -> None:
94
+ assert output == ps.convert_pipette_model(model, version)
95
+
96
+
97
+ @pytest.mark.parametrize(
98
+ argnames=["name", "output"],
99
+ argvalues=[
100
+ [
101
+ "p50_single_gen2",
102
+ pc.PipetteModelVersionType(
103
+ PipetteModelType.p50,
104
+ PipetteChannelType.SINGLE_CHANNEL,
105
+ PipetteVersionType(2, 0),
106
+ PipetteOEMType.OT,
107
+ ),
108
+ ],
109
+ [
110
+ "p1000_multi_flex",
111
+ pc.PipetteModelVersionType(
112
+ PipetteModelType.p1000,
113
+ PipetteChannelType.EIGHT_CHANNEL,
114
+ PipetteVersionType(3, 5),
115
+ PipetteOEMType.OT,
116
+ ),
117
+ ],
118
+ [
119
+ "p1000_96",
120
+ pc.PipetteModelVersionType(
121
+ PipetteModelType.p1000,
122
+ PipetteChannelType.NINETY_SIX_CHANNEL,
123
+ PipetteVersionType(3, 6),
124
+ PipetteOEMType.OT,
125
+ ),
126
+ ],
127
+ ],
128
+ )
129
+ def test_convert_pipette_name(
130
+ name: PipetteName, output: pc.PipetteModelVersionType
131
+ ) -> None:
132
+ assert output == ps.convert_pipette_name(name)
133
+
134
+
135
+ @pytest.mark.parametrize(
136
+ argnames=["model_type", "channels", "generation", "output", "oem"],
137
+ argvalues=[
138
+ [
139
+ PipetteModelType.p50,
140
+ PipetteChannelType.SINGLE_CHANNEL,
141
+ PipetteGenerationType.GEN2,
142
+ "p50_single_gen2",
143
+ PipetteOEMType.OT,
144
+ ],
145
+ [
146
+ PipetteModelType.p1000,
147
+ PipetteChannelType.EIGHT_CHANNEL,
148
+ PipetteGenerationType.GEN2,
149
+ "p1000_multi_gen2",
150
+ PipetteOEMType.OT,
151
+ ],
152
+ [
153
+ # 96 channel has a unique "name" right now
154
+ PipetteModelType.p1000,
155
+ PipetteChannelType.NINETY_SIX_CHANNEL,
156
+ PipetteGenerationType.FLEX,
157
+ "p1000_96",
158
+ PipetteOEMType.OT,
159
+ ],
160
+ ],
161
+ )
162
+ def test_model_version_type_string_version(
163
+ model_type: PipetteModelType,
164
+ channels: PipetteChannelType,
165
+ generation: PipetteGenerationType,
166
+ output: PipetteName,
167
+ oem: PipetteOEMType,
168
+ ) -> None:
169
+ data = pc.PipetteNameType(
170
+ pipette_type=model_type,
171
+ pipette_channels=channels,
172
+ pipette_generation=generation,
173
+ oem_type=oem,
174
+ )
175
+ assert output == str(data)
176
+
177
+
178
+ @pytest.mark.parametrize(
179
+ argnames=["model_type", "channels", "version", "output", "oem"],
180
+ argvalues=[
181
+ [
182
+ PipetteModelType.p50,
183
+ PipetteChannelType.SINGLE_CHANNEL,
184
+ PipetteVersionType(1, 0),
185
+ "p50_single_v1",
186
+ PipetteOEMType.OT,
187
+ ],
188
+ [
189
+ PipetteModelType.p1000,
190
+ PipetteChannelType.EIGHT_CHANNEL,
191
+ PipetteVersionType(2, 1),
192
+ "p1000_multi_v2.1",
193
+ PipetteOEMType.OT,
194
+ ],
195
+ [
196
+ PipetteModelType.p1000,
197
+ PipetteChannelType.NINETY_SIX_CHANNEL,
198
+ PipetteVersionType(3, 3),
199
+ "p1000_96_v3.3",
200
+ PipetteOEMType.OT,
201
+ ],
202
+ ],
203
+ )
204
+ def test_name_type_string_generation(
205
+ model_type: PipetteModelType,
206
+ channels: PipetteChannelType,
207
+ version: PipetteVersionType,
208
+ output: PipetteModel,
209
+ oem: PipetteOEMType,
210
+ ) -> None:
211
+ data = pc.PipetteModelVersionType(
212
+ pipette_type=model_type,
213
+ pipette_channels=channels,
214
+ pipette_version=version,
215
+ oem_type=oem,
216
+ )
217
+ assert output == str(data)
218
+
219
+
220
+ @pytest.mark.parametrize(
221
+ argnames=["model_or_name", "valid"],
222
+ argvalues=[
223
+ [
224
+ "p50_single",
225
+ True,
226
+ ],
227
+ [
228
+ "p50_sing",
229
+ False,
230
+ ],
231
+ [
232
+ "p100_multi",
233
+ False,
234
+ ],
235
+ [
236
+ "p1000_multi_v3.3",
237
+ True,
238
+ ],
239
+ ],
240
+ )
241
+ def test_supported_pipette(
242
+ model_or_name: Union[PipetteName, PipetteModel, None], valid: bool
243
+ ) -> None:
244
+ assert ps.supported_pipette(model_or_name) == valid
@@ -0,0 +1,47 @@
1
+ import pytest
2
+ import typeguard
3
+
4
+ from typing import Generator, Tuple
5
+
6
+ from opentrons_shared_data.pipette import (
7
+ model_config,
8
+ name_config,
9
+ fuse_specs,
10
+ dummy_model_for_name,
11
+ )
12
+ from opentrons_shared_data.pipette.types import (
13
+ PipetteModelSpecs,
14
+ PipetteNameSpecs,
15
+ PipetteFusedSpec,
16
+ PipetteName,
17
+ PipetteModel,
18
+ )
19
+
20
+
21
+ def test_model_config_check() -> None:
22
+ defdict = model_config()
23
+ typeguard.check_type(defdict, PipetteModelSpecs)
24
+
25
+
26
+ def test_name_config_check() -> None:
27
+ defdict = name_config()
28
+ typeguard.check_type(defdict, PipetteNameSpecs)
29
+
30
+
31
+ def build_model_name_pairs() -> Generator[Tuple[PipetteModel, PipetteName], None, None]:
32
+ for model, conf in model_config()["config"].items():
33
+ yield model, conf["name"]
34
+ for bcn in conf.get("backCompatNames", []):
35
+ yield model, bcn
36
+
37
+
38
+ @pytest.mark.parametrize("model,name", list(build_model_name_pairs()))
39
+ def test_fuse(model: PipetteModel, name: PipetteName) -> None:
40
+ defdict = fuse_specs(model, name)
41
+ typeguard.check_type(defdict, PipetteFusedSpec)
42
+
43
+
44
+ @pytest.mark.parametrize("name", list(name_config().keys()))
45
+ def test_model_for_name(name: PipetteName) -> None:
46
+ model = dummy_model_for_name(name)
47
+ assert model in model_config()["config"]
@@ -0,0 +1,198 @@
1
+ import os
2
+ import json
3
+ from typing import Iterator
4
+ from opentrons_shared_data import get_shared_data_root
5
+
6
+ from opentrons_shared_data.pipette.pipette_definition import (
7
+ PipetteConfigurations,
8
+ )
9
+ from opentrons_shared_data.pipette.load_data import (
10
+ load_definition,
11
+ load_valid_nozzle_maps,
12
+ )
13
+ from opentrons_shared_data.pipette.pipette_load_name_conversions import (
14
+ convert_pipette_model,
15
+ )
16
+ from opentrons_shared_data.pipette import types
17
+
18
+
19
+ def iterate_models() -> Iterator[types.PipetteModel]:
20
+ """Get an iterator of all pipette models."""
21
+ _channel_model_str = {
22
+ "single_channel": "single",
23
+ "ninety_six_channel": "96",
24
+ "eight_channel": "multi",
25
+ "eight_channel_em": "multi_em",
26
+ }
27
+ defn_root = get_shared_data_root() / "pipette" / "definitions" / "2" / "liquid"
28
+ assert os.listdir(defn_root), "A path is wrong"
29
+ for channel_dir in defn_root.iterdir():
30
+ for model_dir in channel_dir.iterdir():
31
+ for lc_dir in model_dir.iterdir():
32
+ for version_file in lc_dir.iterdir():
33
+ version_list = version_file.stem.split("_")
34
+ yield types.PipetteModel(
35
+ f"{model_dir.stem}_{_channel_model_str[channel_dir.stem]}_v{version_list[0]}.{version_list[1]}"
36
+ )
37
+
38
+
39
+ def test_check_all_models_are_valid() -> None:
40
+ """Make sure each model can be loaded."""
41
+ for model in iterate_models():
42
+ model_version = convert_pipette_model(model)
43
+ try:
44
+ loaded_model = load_definition(
45
+ model_version.pipette_type,
46
+ model_version.pipette_channels,
47
+ model_version.pipette_version,
48
+ model_version.oem_type,
49
+ )
50
+ except json.JSONDecodeError:
51
+ print(
52
+ f"Failed to parse {model_version.pipette_type} {model_version.pipette_channels} {model_version.pipette_version}"
53
+ )
54
+ raise
55
+
56
+ assert isinstance(loaded_model, PipetteConfigurations)
57
+
58
+
59
+ def test_pick_up_configs_configuration_by_nozzle_map_keys() -> None:
60
+ """Verify that for every nozzle map the pickUpTipConfigurations have a valid configuration set."""
61
+ paths_to_validate = (
62
+ get_shared_data_root() / "pipette" / "definitions" / "2" / "general"
63
+ )
64
+ _channel_model_str = {
65
+ "single_channel": "single",
66
+ "ninety_six_channel": "96",
67
+ "eight_channel": "multi",
68
+ "eight_channel_em": "multi_em",
69
+ }
70
+ assert os.listdir(paths_to_validate), "You have a path wrong"
71
+ for channel_dir in os.listdir(paths_to_validate):
72
+ for model_dir in os.listdir(paths_to_validate / channel_dir):
73
+ for version_file in os.listdir(paths_to_validate / channel_dir / model_dir):
74
+ print(version_file)
75
+ version_list = version_file.split(".json")[0].split("_")
76
+ built_model: types.PipetteModel = types.PipetteModel(
77
+ f"{model_dir}_{_channel_model_str[channel_dir]}_v{version_list[0]}.{version_list[1]}"
78
+ )
79
+
80
+ model_version = convert_pipette_model(built_model)
81
+ loaded_model = load_definition(
82
+ model_version.pipette_type,
83
+ model_version.pipette_channels,
84
+ model_version.pipette_version,
85
+ model_version.oem_type,
86
+ )
87
+ valid_nozzle_maps = load_valid_nozzle_maps(
88
+ model_version.pipette_type,
89
+ model_version.pipette_channels,
90
+ model_version.pipette_version,
91
+ model_version.oem_type,
92
+ )
93
+
94
+ pipette_maps = list(
95
+ loaded_model.pick_up_tip_configurations.press_fit.configuration_by_nozzle_map.keys()
96
+ )
97
+ if loaded_model.pick_up_tip_configurations.cam_action is not None:
98
+ pipette_maps += list(
99
+ loaded_model.pick_up_tip_configurations.cam_action.configuration_by_nozzle_map.keys()
100
+ )
101
+ assert pipette_maps == list(valid_nozzle_maps.maps.keys())
102
+
103
+
104
+ def test_pick_up_configs_configuration_ordered_from_smallest_to_largest() -> None:
105
+ """Verify that ValidNozzleMaps and PickUpTipConfigurations are ordered from smallest nozzle configuration to largest, ensuring mutable config compliancy."""
106
+ paths_to_validate = (
107
+ get_shared_data_root() / "pipette" / "definitions" / "2" / "general"
108
+ )
109
+ _channel_model_str = {
110
+ "single_channel": "single",
111
+ "ninety_six_channel": "96",
112
+ "eight_channel": "multi",
113
+ "eight_channel_em": "multi_em",
114
+ }
115
+ assert os.listdir(paths_to_validate), "You have a path wrong"
116
+ for channel_dir in os.listdir(paths_to_validate):
117
+ for model_dir in os.listdir(paths_to_validate / channel_dir):
118
+ for version_file in os.listdir(paths_to_validate / channel_dir / model_dir):
119
+ version_list = version_file.split(".json")[0].split("_")
120
+ built_model: types.PipetteModel = types.PipetteModel(
121
+ f"{model_dir}_{_channel_model_str[channel_dir]}_v{version_list[0]}.{version_list[1]}"
122
+ )
123
+
124
+ model_version = convert_pipette_model(built_model)
125
+ loaded_model = load_definition(
126
+ model_version.pipette_type,
127
+ model_version.pipette_channels,
128
+ model_version.pipette_version,
129
+ model_version.oem_type,
130
+ )
131
+ valid_nozzle_maps = load_valid_nozzle_maps(
132
+ model_version.pipette_type,
133
+ model_version.pipette_channels,
134
+ model_version.pipette_version,
135
+ model_version.oem_type,
136
+ )
137
+
138
+ map_keys = list(valid_nozzle_maps.maps.keys())
139
+ for key in map_keys:
140
+ for i in range(map_keys.index(key)):
141
+ assert len(valid_nozzle_maps.maps[map_keys[i]]) <= len(
142
+ valid_nozzle_maps.maps[key]
143
+ )
144
+
145
+ pipette_maps = list(
146
+ loaded_model.pick_up_tip_configurations.press_fit.configuration_by_nozzle_map.keys()
147
+ )
148
+ for key in pipette_maps:
149
+ for i in range(pipette_maps.index(key)):
150
+ assert len(valid_nozzle_maps.maps[pipette_maps[i]]) <= len(
151
+ valid_nozzle_maps.maps[key]
152
+ )
153
+
154
+
155
+ def test_serializer() -> None:
156
+ """Verify that the serializer works as expected."""
157
+
158
+ loaded_model = load_definition(
159
+ types.PipetteModelType.p1000,
160
+ types.PipetteChannelType.NINETY_SIX_CHANNEL,
161
+ types.PipetteVersionType(3, 3),
162
+ types.PipetteOEMType.OT,
163
+ )
164
+ quirk_0 = types.Quirks.pickupTipShake
165
+ quirk_1 = types.Quirks.dropTipShake
166
+ loaded_model.quirks = [quirk_0, quirk_1]
167
+
168
+ assert loaded_model.pipette_type == types.PipetteModelType.p1000
169
+ assert loaded_model.display_category == types.PipetteGenerationType.FLEX
170
+ assert loaded_model.channels == types.PipetteChannelType.NINETY_SIX_CHANNEL
171
+
172
+ model_dict = loaded_model.model_dump()
173
+ # each field should be the value of the enum class
174
+ assert (
175
+ isinstance(model_dict["pipette_type"], str)
176
+ and model_dict["pipette_type"] == loaded_model.pipette_type.value
177
+ )
178
+ assert (
179
+ isinstance(model_dict["display_category"], str)
180
+ and model_dict["display_category"] == loaded_model.display_category.value
181
+ )
182
+ assert (
183
+ isinstance(model_dict["channels"], int)
184
+ and model_dict["channels"] == loaded_model.channels.value
185
+ )
186
+
187
+ assert len(model_dict["quirks"]) == 2
188
+ dict_quirk_0 = model_dict["quirks"][0]
189
+ dict_quirk_1 = model_dict["quirks"][1]
190
+ assert isinstance(dict_quirk_0, str) and dict_quirk_0 == quirk_0.value
191
+ assert isinstance(dict_quirk_1, str) and dict_quirk_1 == quirk_1.value
192
+
193
+
194
+ # TODO: (AA, 4/9/2024) we should add a test to validate the dumped json to make
195
+ # sure we can re-load it as the BaseModel class. But we haven't added serializer
196
+ # for other enums yet, such as LiquidClass, and since we haven't been
197
+ # creating the definition files using model_dump/model_dump_json, it is okay to
198
+ # skip this for now.
@@ -0,0 +1,7 @@
1
+ from typing import List
2
+ from pathlib import Path
3
+
4
+
5
+ def list_fixtures(version: int) -> List[Path]:
6
+ base = Path(__file__).parent / ".." / ".." / "protocol" / "fixtures" / f"{version}"
7
+ return list(base.iterdir())
@@ -0,0 +1,108 @@
1
+ import json
2
+ import pytest
3
+ from typing import Any, Dict
4
+ from pathlib import Path
5
+ from opentrons_shared_data import load_shared_data
6
+ from opentrons_shared_data.protocol.models import (
7
+ protocol_schema_v6,
8
+ Robot,
9
+ Metadata,
10
+ Liquid,
11
+ Module,
12
+ Pipette,
13
+ Labware,
14
+ )
15
+
16
+ from . import list_fixtures
17
+
18
+
19
+ @pytest.mark.parametrize("defpath", list_fixtures(6))
20
+ def test_v6_types(defpath: Path) -> None:
21
+ def_data = load_shared_data(defpath)
22
+ def_model = protocol_schema_v6.ProtocolSchemaV6.model_validate_json(def_data)
23
+ def_dict_from_model = def_model.model_dump(
24
+ exclude_unset=True,
25
+ # 'schemaVersion' in python is '$schemaVersion' in JSON
26
+ by_alias=True,
27
+ )
28
+ expected_def_dict = json.loads(def_data)
29
+ delete_unexpected_results(expected_def_dict)
30
+ assert def_dict_from_model == expected_def_dict
31
+
32
+
33
+ # TODO (Tamar and Max 3/16/22):
34
+ # Some of our v6 fixtures accidentally contain command "result" data,
35
+ # which is not part of the schema, and which we don't parse into our models.
36
+ # Here, we delete the extra junk from the fixtures.
37
+ # Remove this when the fixtures are corrected.
38
+ # https://github.com/Opentrons/opentrons/issues/9701
39
+ def delete_unexpected_results(protocol_fixture: Dict[str, Any]) -> None:
40
+ for command_object_dict in protocol_fixture["commands"]:
41
+ command_object_dict.pop("result", None)
42
+ command_object_dict.pop("id", None)
43
+
44
+
45
+ @pytest.mark.parametrize(
46
+ "input_command, missing_id, load_command",
47
+ [
48
+ (
49
+ protocol_schema_v6.Command(
50
+ commandType="loadLabware",
51
+ params=protocol_schema_v6.Params(labwareId="labware-id-3"),
52
+ ),
53
+ "labware-id-3",
54
+ "loadLabware",
55
+ ),
56
+ (
57
+ protocol_schema_v6.Command(
58
+ commandType="loadPipette",
59
+ params=protocol_schema_v6.Params(pipetteId="pipette-id-3"),
60
+ ),
61
+ "pipette-id-3",
62
+ "loadPipette",
63
+ ),
64
+ (
65
+ protocol_schema_v6.Command(
66
+ commandType="loadLiquid",
67
+ params=protocol_schema_v6.Params(liquidId="liquid-id-3"),
68
+ ),
69
+ "liquid-id-3",
70
+ "loadLiquid",
71
+ ),
72
+ (
73
+ protocol_schema_v6.Command(
74
+ commandType="loadModule",
75
+ params=protocol_schema_v6.Params(moduleId="module-id-3"),
76
+ ),
77
+ "module-id-3",
78
+ "loadModule",
79
+ ),
80
+ ],
81
+ )
82
+ def test_schema_validators(
83
+ input_command: protocol_schema_v6.Command, missing_id: str, load_command: str
84
+ ) -> None:
85
+ """Should raise an error the keys do not match."""
86
+ labware = {
87
+ "labware-id-1": Labware(definitionId="definition-1"),
88
+ "labware-id-2": Labware(definitionId="definition-2"),
89
+ }
90
+ pipettes = {"pipette-id-1": Pipette(name="pipette-1")}
91
+ liquids = {"liquid-id-1": Liquid(displayName="liquid-1", description="liquid desc")}
92
+ modules = {"module-id-1": Module(model="model-1")}
93
+ with pytest.raises(
94
+ ValueError,
95
+ match=f"{load_command} command at index 0 references ID {missing_id}, which doesn't exist.",
96
+ ):
97
+ protocol_schema_v6.ProtocolSchemaV6(
98
+ otSharedSchema="#/protocol/schemas/6",
99
+ schemaVersion=6,
100
+ metadata=Metadata(),
101
+ robot=Robot(model="OT-2 Standard", deckId=""),
102
+ labware=labware,
103
+ pipettes=pipettes,
104
+ liquids=liquids,
105
+ modules=modules,
106
+ labwareDefinitions={},
107
+ commands=[input_command],
108
+ )
@@ -0,0 +1,35 @@
1
+ import json
2
+ import pytest
3
+ from typing import Any, Dict
4
+ from pathlib import Path
5
+
6
+ from opentrons_shared_data import load_shared_data
7
+ from opentrons_shared_data.protocol.models import protocol_schema_v7
8
+
9
+ from . import list_fixtures
10
+
11
+
12
+ @pytest.mark.parametrize("defpath", list_fixtures(7))
13
+ def test_v7_types(defpath: Path) -> None:
14
+ def_data = load_shared_data(defpath)
15
+ def_model = protocol_schema_v7.ProtocolSchemaV7.model_validate_json(def_data)
16
+ def_dict_from_model = def_model.model_dump(
17
+ exclude_unset=True,
18
+ # 'schemaVersion' in python is '$schemaVersion' in JSON
19
+ by_alias=True,
20
+ )
21
+ expected_def_dict = json.loads(def_data)
22
+ delete_unexpected_results(expected_def_dict)
23
+ assert def_dict_from_model == expected_def_dict
24
+
25
+
26
+ # TODO (Tamar and Max 3/16/22):
27
+ # Some of our v7 fixtures accidentally contain command "result" data,
28
+ # which is not part of the schema, and which we don't parse into our models.
29
+ # Here, we delete the extra junk from the fixtures.
30
+ # Remove this when the fixtures are corrected.
31
+ # https://github.com/Opentrons/opentrons/issues/9701
32
+ def delete_unexpected_results(protocol_fixture: Dict[str, Any]) -> None:
33
+ for command_object_dict in protocol_fixture["commands"]:
34
+ command_object_dict.pop("result", None)
35
+ command_object_dict.pop("id", None)
@@ -0,0 +1,17 @@
1
+ import json
2
+ import pytest
3
+ from pathlib import Path
4
+
5
+ from opentrons_shared_data import load_shared_data
6
+ from opentrons_shared_data.protocol.models import protocol_schema_v8
7
+
8
+ from . import list_fixtures
9
+
10
+
11
+ @pytest.mark.parametrize("defpath", list_fixtures(8))
12
+ def test_v8_types(defpath: Path) -> None:
13
+ def_data = load_shared_data(defpath)
14
+ def_model = protocol_schema_v8.ProtocolSchemaV8.model_validate_json(def_data)
15
+ def_dict_from_model = def_model.model_dump(by_alias=True, exclude_unset=True)
16
+ expected_def_dict = json.loads(def_data)
17
+ assert def_dict_from_model == expected_def_dict
@@ -0,0 +1,30 @@
1
+ import json
2
+ import pytest
3
+ from pathlib import Path
4
+ import typeguard
5
+
6
+ from opentrons_shared_data import load_shared_data
7
+ from opentrons_shared_data.protocol.types import (
8
+ JsonProtocolV3,
9
+ JsonProtocolV4,
10
+ JsonProtocolV5,
11
+ )
12
+ from . import list_fixtures
13
+
14
+
15
+ @pytest.mark.parametrize("defpath", list_fixtures(3))
16
+ def test_v3_types(defpath: Path) -> None:
17
+ defn = json.loads(load_shared_data(defpath))
18
+ typeguard.check_type(defn, JsonProtocolV3)
19
+
20
+
21
+ @pytest.mark.parametrize("defpath", list_fixtures(4))
22
+ def test_v4_types(defpath: Path) -> None:
23
+ defn = json.loads(load_shared_data(defpath))
24
+ typeguard.check_type(defn, JsonProtocolV4)
25
+
26
+
27
+ @pytest.mark.parametrize("defpath", list_fixtures(5))
28
+ def test_v5_types(defpath: Path) -> None:
29
+ defn = json.loads(load_shared_data(defpath))
30
+ typeguard.check_type(defn, JsonProtocolV5)
File without changes