opentrons 8.4.0a13__py2.py3-none-any.whl → 8.5.0a1__py2.py3-none-any.whl

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.

Potentially problematic release.


This version of opentrons might be problematic. Click here for more details.

Files changed (57) hide show
  1. opentrons/config/defaults_ot3.py +1 -1
  2. opentrons/legacy_commands/commands.py +16 -4
  3. opentrons/legacy_commands/robot_commands.py +51 -0
  4. opentrons/legacy_commands/types.py +91 -2
  5. opentrons/protocol_api/_liquid.py +60 -15
  6. opentrons/protocol_api/_liquid_properties.py +137 -90
  7. opentrons/protocol_api/_transfer_liquid_validation.py +10 -6
  8. opentrons/protocol_api/core/engine/instrument.py +172 -75
  9. opentrons/protocol_api/core/engine/protocol.py +13 -14
  10. opentrons/protocol_api/core/engine/robot.py +2 -2
  11. opentrons/protocol_api/core/engine/transfer_components_executor.py +157 -126
  12. opentrons/protocol_api/core/engine/well.py +16 -0
  13. opentrons/protocol_api/core/instrument.py +2 -2
  14. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -2
  15. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -1
  16. opentrons/protocol_api/core/legacy/legacy_well_core.py +8 -0
  17. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -2
  18. opentrons/protocol_api/core/protocol.py +2 -2
  19. opentrons/protocol_api/core/well.py +8 -0
  20. opentrons/protocol_api/instrument_context.py +377 -86
  21. opentrons/protocol_api/labware.py +10 -0
  22. opentrons/protocol_api/protocol_context.py +79 -4
  23. opentrons/protocol_api/robot_context.py +48 -6
  24. opentrons/protocol_api/validation.py +15 -8
  25. opentrons/protocol_engine/commands/command_unions.py +10 -10
  26. opentrons/protocol_engine/commands/generate_command_schema.py +1 -1
  27. opentrons/protocol_engine/commands/get_next_tip.py +2 -2
  28. opentrons/protocol_engine/commands/pick_up_tip.py +9 -3
  29. opentrons/protocol_engine/commands/robot/__init__.py +20 -20
  30. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +34 -24
  31. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +29 -20
  32. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +1 -1
  33. opentrons/protocol_engine/commands/unsafe/__init__.py +17 -1
  34. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +1 -2
  35. opentrons/protocol_engine/execution/labware_movement.py +9 -2
  36. opentrons/protocol_engine/execution/movement.py +12 -9
  37. opentrons/protocol_engine/execution/queue_worker.py +8 -1
  38. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +52 -19
  39. opentrons/protocol_engine/state/_well_math.py +2 -2
  40. opentrons/protocol_engine/state/commands.py +14 -28
  41. opentrons/protocol_engine/state/frustum_helpers.py +11 -7
  42. opentrons/protocol_engine/state/modules.py +1 -1
  43. opentrons/protocol_engine/state/pipettes.py +8 -0
  44. opentrons/protocol_engine/state/tips.py +46 -83
  45. opentrons/protocol_engine/state/update_types.py +8 -23
  46. opentrons/protocol_runner/legacy_command_mapper.py +11 -4
  47. opentrons/protocol_runner/run_orchestrator.py +1 -1
  48. opentrons/protocols/advanced_control/transfers/common.py +54 -11
  49. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +1 -1
  50. opentrons/protocols/api_support/definitions.py +1 -1
  51. opentrons/types.py +6 -6
  52. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/METADATA +4 -4
  53. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/RECORD +57 -56
  54. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/LICENSE +0 -0
  55. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/WHEEL +0 -0
  56. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/entry_points.txt +0 -0
  57. {opentrons-8.4.0a13.dist-info → opentrons-8.5.0a1.dist-info}/top_level.txt +0 -0
@@ -346,6 +346,16 @@ class Well:
346
346
  """Get the current liquid volume in a well."""
347
347
  return self._core.get_liquid_volume()
348
348
 
349
+ @requires_version(2, 24)
350
+ def volume_from_height(self, height: LiquidTrackingType) -> LiquidTrackingType:
351
+ """Return the volume contained in a well at any height."""
352
+ return self._core.volume_from_height(height)
353
+
354
+ @requires_version(2, 24)
355
+ def height_from_volume(self, volume: LiquidTrackingType) -> LiquidTrackingType:
356
+ """Return the height in a well corresponding to a given volume."""
357
+ return self._core.height_from_volume(volume)
358
+
349
359
  @requires_version(2, 21)
350
360
  def estimate_liquid_height_after_pipetting(
351
361
  self,
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ from copy import deepcopy
4
5
  from typing import (
5
6
  Callable,
6
7
  Dict,
@@ -13,6 +14,11 @@ from typing import (
13
14
  )
14
15
 
15
16
  from opentrons_shared_data.labware.types import LabwareDefinition
17
+ from opentrons_shared_data.liquid_classes.liquid_class_definition import (
18
+ TransferProperties as SharedTransferProperties,
19
+ )
20
+ from opentrons_shared_data.liquid_classes import DEFAULT_LC_VERSION, definition_exists
21
+ from opentrons_shared_data.liquid_classes.types import TransferPropertiesDict
16
22
  from opentrons_shared_data.pipette.types import PipetteNameType
17
23
 
18
24
  from opentrons.types import Mount, Location, DeckLocation, DeckSlotName, StagingSlotName
@@ -48,6 +54,7 @@ from opentrons.protocols.api_support.util import (
48
54
  )
49
55
  from opentrons_shared_data.errors.exceptions import CommandPreconditionViolated
50
56
  from opentrons.protocol_engine.errors import LabwareMovementNotAllowedError
57
+ from ._liquid_properties import build_transfer_properties
51
58
 
52
59
  from ._types import OffDeckType
53
60
  from .core.common import ModuleCore, LabwareCore, ProtocolCore
@@ -196,6 +203,7 @@ class ProtocolContext(CommandPublisher):
196
203
  core=self._core.load_robot(),
197
204
  protocol_core=self._core,
198
205
  api_version=self._api_version,
206
+ broker=broker,
199
207
  )
200
208
  except APIVersionError:
201
209
  self._robot = None
@@ -1189,9 +1197,16 @@ class ProtocolContext(CommandPublisher):
1189
1197
  self._core.home()
1190
1198
 
1191
1199
  @property
1192
- def location_cache(self) -> Optional[Location]:
1193
- """The cache used by the robot to determine where it last was."""
1194
- return self._core.get_last_location()
1200
+ def location_cache(self) -> Optional[Union[Location, TrashBin, WasteChute]]:
1201
+ """The cache used by the robot to determine where it last was.
1202
+
1203
+ .. versionchanged:: 2.24
1204
+ Can return a ``TrashBin`` or ``WasteChute`` object.
1205
+ """
1206
+ last_loc = self._core.get_last_location()
1207
+ if isinstance(last_loc, Location) or self._api_version >= APIVersion(2, 24):
1208
+ return last_loc
1209
+ return None
1195
1210
 
1196
1211
  @location_cache.setter
1197
1212
  def location_cache(self, loc: Optional[Location]) -> None:
@@ -1368,7 +1383,67 @@ class ProtocolContext(CommandPublisher):
1368
1383
 
1369
1384
  :meta private:
1370
1385
  """
1371
- return self._core.define_liquid_class(name=name)
1386
+ return self._core.define_liquid_class(name=name, version=DEFAULT_LC_VERSION)
1387
+
1388
+ @requires_version(2, 24)
1389
+ def define_custom_liquid_class(
1390
+ self,
1391
+ name: str,
1392
+ properties: Dict[str, Dict[str, TransferPropertiesDict]],
1393
+ base_liquid_class: Optional[LiquidClass] = None,
1394
+ display_name: Optional[str] = None,
1395
+ ) -> LiquidClass:
1396
+ """Define a custom liquid class, either a completely new one or based on an existing one.
1397
+
1398
+ Args:
1399
+ name: The name to give to the new liquid class. Cannot use names of existing in-built liquid classes.
1400
+ properties: A dict of transfer properties per tip per pipette.
1401
+ Accepts a nested dictionary in the following format:
1402
+
1403
+ .. code-block:: python
1404
+
1405
+ {
1406
+ <pipette_name>: {
1407
+ <tiprack_uri>: <properties in the shape of TransferPropertiesDict>
1408
+
1409
+ # TransferPropertiesDict is a dictionary representation of the
1410
+ # transfer properties returned by the `LiquidClass.get_for(..)` function.
1411
+ }}
1412
+
1413
+ base_liquid_class: A LiquidClass to base this liquid class on. The properties
1414
+ specified in transfer_properties will override any existing ones
1415
+ for the specified pipettes & tips.
1416
+ display_name: An optional human-readable name for the liquid. If not provided,
1417
+ will default to title-cased name.
1418
+
1419
+ """
1420
+ if definition_exists(name, DEFAULT_LC_VERSION):
1421
+ raise ValueError(
1422
+ f"Liquid class named {name} already exists. Please specify a different name."
1423
+ )
1424
+ new_liquid_class: LiquidClass
1425
+ if base_liquid_class:
1426
+ # If base liquid is provided, copy to new class
1427
+ # and replace the entries mentioned in transfer props arg
1428
+ new_liquid_class = deepcopy(base_liquid_class)
1429
+ else:
1430
+ new_liquid_class = LiquidClass.create_from(
1431
+ name=name,
1432
+ display_name=display_name or name.title(),
1433
+ by_pipette_setting={},
1434
+ )
1435
+ for pipette, by_tiprack_props in properties.items():
1436
+ for tiprack, transfer_props in by_tiprack_props.items():
1437
+ new_liquid_class.update_for(
1438
+ pipette=pipette,
1439
+ tip_rack=tiprack,
1440
+ transfer_properties=build_transfer_properties(
1441
+ transfer_properties=SharedTransferProperties.model_validate(
1442
+ transfer_props
1443
+ )
1444
+ ),
1445
+ )
1446
+ return new_liquid_class
1372
1447
 
1373
1448
  @property
1374
1449
  @requires_version(2, 5)
@@ -9,6 +9,8 @@ from opentrons.types import (
9
9
  AxisType,
10
10
  StringAxisMap,
11
11
  )
12
+ from opentrons.legacy_broker import LegacyBroker
13
+ from opentrons.legacy_commands import robot_commands as cmds
12
14
  from opentrons.legacy_commands import publisher
13
15
  from opentrons.hardware_control import SyncHardwareAPI
14
16
  from opentrons.protocols.api_support.util import requires_version
@@ -49,8 +51,13 @@ class RobotContext(publisher.CommandPublisher):
49
51
  """
50
52
 
51
53
  def __init__(
52
- self, core: RobotCore, protocol_core: ProtocolCore, api_version: APIVersion
54
+ self,
55
+ core: RobotCore,
56
+ protocol_core: ProtocolCore,
57
+ api_version: APIVersion,
58
+ broker: Optional[LegacyBroker] = None,
53
59
  ) -> None:
60
+ super().__init__(broker)
54
61
  self._hardware = HardwareManager(hardware=protocol_core.get_hardware())
55
62
  self._core = core
56
63
  self._protocol_core = protocol_core
@@ -87,7 +94,16 @@ class RobotContext(publisher.CommandPublisher):
87
94
  :param speed:
88
95
  """
89
96
  mount = validation.ensure_instrument_mount(mount)
90
- self._core.move_to(mount, destination.point, speed)
97
+ with publisher.publish_context(
98
+ broker=self.broker,
99
+ command=cmds.move_to(
100
+ # This needs to be called from protocol context and not the command for import loop reasons
101
+ mount=mount,
102
+ location=destination,
103
+ speed=speed,
104
+ ),
105
+ ):
106
+ self._core.move_to(mount, destination.point, speed)
91
107
 
92
108
  @requires_version(2, 22)
93
109
  def move_axes_to(
@@ -119,7 +135,15 @@ class RobotContext(publisher.CommandPublisher):
119
135
  )
120
136
  else:
121
137
  critical_point = None
122
- self._core.move_axes_to(axis_map, critical_point, speed)
138
+ with publisher.publish_context(
139
+ broker=self.broker,
140
+ command=cmds.move_axis_to(
141
+ # This needs to be called from protocol context and not the command for import loop reasons
142
+ axis_map=axis_map,
143
+ speed=speed,
144
+ ),
145
+ ):
146
+ self._core.move_axes_to(axis_map, critical_point, speed)
123
147
 
124
148
  @requires_version(2, 22)
125
149
  def move_axes_relative(
@@ -142,15 +166,33 @@ class RobotContext(publisher.CommandPublisher):
142
166
  axis_map = validation.ensure_axis_map_type(
143
167
  axis_map, self._protocol_core.robot_type, is_96_channel
144
168
  )
145
- self._core.move_axes_relative(axis_map, speed)
169
+ with publisher.publish_context(
170
+ broker=self.broker,
171
+ command=cmds.move_axis_relative(
172
+ # This needs to be called from protocol context and not the command for import loop reasons
173
+ axis_map=axis_map,
174
+ speed=speed,
175
+ ),
176
+ ):
177
+ self._core.move_axes_relative(axis_map, speed)
146
178
 
147
179
  def close_gripper_jaw(self, force: Optional[float] = None) -> None:
148
180
  """Command the gripper closed with some force."""
149
- self._core.close_gripper(force)
181
+ with publisher.publish_context(
182
+ broker=self.broker,
183
+ command=cmds.close_gripper(
184
+ force=force,
185
+ ),
186
+ ):
187
+ self._core.close_gripper(force)
150
188
 
151
189
  def open_gripper_jaw(self) -> None:
152
190
  """Command the gripper open."""
153
- self._core.release_grip()
191
+ with publisher.publish_context(
192
+ broker=self.broker,
193
+ command=cmds.open_gripper(),
194
+ ):
195
+ self._core.release_grip()
154
196
 
155
197
  def axis_coordinates_for(
156
198
  self,
@@ -545,6 +545,11 @@ class PointTarget(NamedTuple):
545
545
  in_place: bool
546
546
 
547
547
 
548
+ class DisposalTarget(NamedTuple):
549
+ location: Union[TrashBin, WasteChute]
550
+ in_place: bool
551
+
552
+
548
553
  class NoLocationError(ValueError):
549
554
  """Error representing that no location was supplied."""
550
555
 
@@ -553,12 +558,12 @@ class LocationTypeError(TypeError):
553
558
  """Error representing that the location supplied is of different expected type."""
554
559
 
555
560
 
556
- ValidTarget = Union[WellTarget, PointTarget, TrashBin, WasteChute]
561
+ ValidTarget = Union[WellTarget, PointTarget, DisposalTarget]
557
562
 
558
563
 
559
564
  def validate_location(
560
- location: Union[Location, Well, TrashBin, WasteChute, None],
561
- last_location: Optional[Location],
565
+ location: Optional[Union[Location, Well, TrashBin, WasteChute]],
566
+ last_location: Optional[Union[Location, TrashBin, WasteChute]],
562
567
  ) -> ValidTarget:
563
568
  """Validate a given location for a liquid handling command.
564
569
 
@@ -569,9 +574,11 @@ def validate_location(
569
574
  Returns:
570
575
  A `WellTarget` if the input location represents a well.
571
576
  A `PointTarget` if the input location is an x, y, z coordinate.
577
+ A `TrashBin` if the input location is a trash bin
578
+ A `WasteChute` if the input location is a waste chute
572
579
 
573
580
  Raises:
574
- NoLocationError: The is no input location and no cached loaction.
581
+ NoLocationError: There is no input location and no cached location.
575
582
  LocationTypeError: The location supplied is of unexpected type.
576
583
  """
577
584
  from .labware import Well
@@ -586,11 +593,11 @@ def validate_location(
586
593
  f"location should be a Well, Location, TrashBin or WasteChute, but it is {location}"
587
594
  )
588
595
 
589
- if isinstance(target_location, (TrashBin, WasteChute)):
590
- return target_location
591
-
592
596
  in_place = target_location == last_location
593
597
 
598
+ if isinstance(target_location, (TrashBin, WasteChute)):
599
+ return DisposalTarget(location=target_location, in_place=in_place)
600
+
594
601
  if isinstance(target_location, Well):
595
602
  return WellTarget(well=target_location, location=None, in_place=in_place)
596
603
 
@@ -662,7 +669,7 @@ def ensure_new_tip_policy(value: str) -> TransferTipPolicyV2:
662
669
  except ValueError:
663
670
  raise ValueError(
664
671
  f"'{value}' is invalid value for 'new_tip'."
665
- f" Acceptable value is either 'never', 'once', 'always' or 'per source'."
672
+ f" Acceptable value is either 'never', 'once', 'always', 'per source' or 'per destination'."
666
673
  )
667
674
 
668
675
 
@@ -498,8 +498,8 @@ Command = Annotated[
498
498
  robot.MoveTo,
499
499
  robot.MoveAxesRelative,
500
500
  robot.MoveAxesTo,
501
- robot.openGripperJaw,
502
- robot.closeGripperJaw,
501
+ robot.OpenGripperJaw,
502
+ robot.CloseGripperJaw,
503
503
  ],
504
504
  Field(discriminator="commandType"),
505
505
  ]
@@ -599,8 +599,8 @@ CommandParams = Union[
599
599
  robot.MoveAxesRelativeParams,
600
600
  robot.MoveAxesToParams,
601
601
  robot.MoveToParams,
602
- robot.openGripperJawParams,
603
- robot.closeGripperJawParams,
602
+ robot.OpenGripperJawParams,
603
+ robot.CloseGripperJawParams,
604
604
  ]
605
605
 
606
606
  CommandType = Union[
@@ -698,8 +698,8 @@ CommandType = Union[
698
698
  robot.MoveAxesRelativeCommandType,
699
699
  robot.MoveAxesToCommandType,
700
700
  robot.MoveToCommandType,
701
- robot.openGripperJawCommandType,
702
- robot.closeGripperJawCommandType,
701
+ robot.OpenGripperJawCommandType,
702
+ robot.CloseGripperJawCommandType,
703
703
  ]
704
704
 
705
705
  CommandCreate = Annotated[
@@ -798,8 +798,8 @@ CommandCreate = Annotated[
798
798
  robot.MoveAxesRelativeCreate,
799
799
  robot.MoveAxesToCreate,
800
800
  robot.MoveToCreate,
801
- robot.openGripperJawCreate,
802
- robot.closeGripperJawCreate,
801
+ robot.OpenGripperJawCreate,
802
+ robot.CloseGripperJawCreate,
803
803
  ],
804
804
  Field(discriminator="commandType"),
805
805
  ]
@@ -906,8 +906,8 @@ CommandResult = Union[
906
906
  robot.MoveAxesRelativeResult,
907
907
  robot.MoveAxesToResult,
908
908
  robot.MoveToResult,
909
- robot.openGripperJawResult,
910
- robot.closeGripperJawResult,
909
+ robot.OpenGripperJawResult,
910
+ robot.CloseGripperJawResult,
911
911
  ]
912
912
 
913
913
 
@@ -11,7 +11,7 @@ from opentrons_shared_data.load import get_shared_data_root
11
11
 
12
12
  def generate_command_schema(version: str) -> str:
13
13
  """Generate a JSON Schema that all valid create commands can validate against."""
14
- schema_as_dict = CommandCreateAdapter.json_schema(mode="validation")
14
+ schema_as_dict = CommandCreateAdapter.json_schema(mode="validation", by_alias=False)
15
15
  schema_as_dict["$id"] = f"opentronsCommandSchemaV{version}"
16
16
  schema_as_dict["$schema"] = "http://json-schema.org/draft-07/schema#"
17
17
  return json.dumps(schema_as_dict, indent=2, sort_keys=True)
@@ -73,8 +73,8 @@ class GetNextTipImplementation(
73
73
  pipette_id = params.pipetteId
74
74
  starting_tip_name = params.startingTipWell
75
75
 
76
- num_tips = self._state_view.tips.get_pipette_active_channels(pipette_id)
77
- nozzle_map = self._state_view.tips.get_pipette_nozzle_map(pipette_id)
76
+ num_tips = self._state_view.pipettes.get_active_channels(pipette_id)
77
+ nozzle_map = self._state_view.pipettes.get_nozzle_configuration(pipette_id)
78
78
 
79
79
  if (
80
80
  starting_tip_name is not None
@@ -121,6 +121,12 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
121
121
  labware_id = params.labwareId
122
122
  well_name = params.wellName
123
123
 
124
+ tips_to_mark_as_used = self._state_view.tips.compute_tips_to_mark_as_used(
125
+ labware_id=labware_id,
126
+ well_name=well_name,
127
+ nozzle_map=self._state_view.pipettes.get_nozzle_configuration(pipette_id),
128
+ )
129
+
124
130
  well_location = self._state_view.geometry.convert_pick_up_tip_well_location(
125
131
  well_location=params.wellLocation
126
132
  )
@@ -152,7 +158,7 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
152
158
  )
153
159
  .set_fluid_empty(pipette_id=pipette_id, clean_tip=True)
154
160
  .mark_tips_as_used(
155
- pipette_id=pipette_id, labware_id=labware_id, well_name=well_name
161
+ labware_id=labware_id, well_names=tips_to_mark_as_used
156
162
  )
157
163
  )
158
164
  state_update = (
@@ -160,7 +166,7 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
160
166
  update_types.StateUpdate(), move_result.state_update
161
167
  )
162
168
  .mark_tips_as_used(
163
- pipette_id=pipette_id, labware_id=labware_id, well_name=well_name
169
+ labware_id=labware_id, well_names=tips_to_mark_as_used
164
170
  )
165
171
  .set_fluid_unknown(pipette_id=pipette_id)
166
172
  )
@@ -186,7 +192,7 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
186
192
  tip_geometry=tip_geometry,
187
193
  )
188
194
  .mark_tips_as_used(
189
- pipette_id=pipette_id, labware_id=labware_id, well_name=well_name
195
+ labware_id=labware_id, well_names=tips_to_mark_as_used
190
196
  )
191
197
  .set_fluid_empty(pipette_id=pipette_id, clean_tip=True)
192
198
  .set_pipette_ready_to_aspirate(
@@ -22,18 +22,18 @@ from .move_axes_relative import (
22
22
  MoveAxesRelativeCommandType,
23
23
  )
24
24
  from .open_gripper_jaw import (
25
- openGripperJaw,
26
- openGripperJawCreate,
27
- openGripperJawParams,
28
- openGripperJawResult,
29
- openGripperJawCommandType,
25
+ OpenGripperJaw,
26
+ OpenGripperJawCreate,
27
+ OpenGripperJawParams,
28
+ OpenGripperJawResult,
29
+ OpenGripperJawCommandType,
30
30
  )
31
31
  from .close_gripper_jaw import (
32
- closeGripperJaw,
33
- closeGripperJawCreate,
34
- closeGripperJawParams,
35
- closeGripperJawResult,
36
- closeGripperJawCommandType,
32
+ CloseGripperJaw,
33
+ CloseGripperJawCreate,
34
+ CloseGripperJawParams,
35
+ CloseGripperJawResult,
36
+ CloseGripperJawCommandType,
37
37
  )
38
38
 
39
39
  __all__ = [
@@ -56,15 +56,15 @@ __all__ = [
56
56
  "MoveAxesRelativeResult",
57
57
  "MoveAxesRelativeCommandType",
58
58
  # robot/openGripperJaw
59
- "openGripperJaw",
60
- "openGripperJawCreate",
61
- "openGripperJawParams",
62
- "openGripperJawResult",
63
- "openGripperJawCommandType",
59
+ "OpenGripperJaw",
60
+ "OpenGripperJawCreate",
61
+ "OpenGripperJawParams",
62
+ "OpenGripperJawResult",
63
+ "OpenGripperJawCommandType",
64
64
  # robot/closeGripperJaw
65
- "closeGripperJaw",
66
- "closeGripperJawCreate",
67
- "closeGripperJawParams",
68
- "closeGripperJawResult",
69
- "closeGripperJawCommandType",
65
+ "CloseGripperJaw",
66
+ "CloseGripperJawCreate",
67
+ "CloseGripperJawParams",
68
+ "CloseGripperJawResult",
69
+ "CloseGripperJawCommandType",
70
70
  ]
@@ -1,6 +1,7 @@
1
1
  """Command models for opening a gripper jaw."""
2
+
2
3
  from __future__ import annotations
3
- from typing import Literal, Type, Optional, Any
4
+ from typing import Literal, Type, Optional, Any, TYPE_CHECKING
4
5
 
5
6
  from pydantic import BaseModel, Field
6
7
  from pydantic.json_schema import SkipJsonSchema
@@ -16,15 +17,18 @@ from ..command import (
16
17
  )
17
18
  from opentrons.protocol_engine.errors.error_occurrence import ErrorOccurrence
18
19
 
20
+ if TYPE_CHECKING:
21
+ from ...state.state import StateView
22
+
19
23
 
20
- closeGripperJawCommandType = Literal["robot/closeGripperJaw"]
24
+ CloseGripperJawCommandType = Literal["robot/closeGripperJaw"]
21
25
 
22
26
 
23
27
  def _remove_default(s: dict[str, Any]) -> None:
24
28
  s.pop("default", None)
25
29
 
26
30
 
27
- class closeGripperJawParams(BaseModel):
31
+ class CloseGripperJawParams(BaseModel):
28
32
  """Payload required to close a gripper."""
29
33
 
30
34
  force: float | SkipJsonSchema[None] = Field(
@@ -34,53 +38,59 @@ class closeGripperJawParams(BaseModel):
34
38
  )
35
39
 
36
40
 
37
- class closeGripperJawResult(BaseModel):
38
- """Result data from the execution of a closeGripperJaw command."""
41
+ class CloseGripperJawResult(BaseModel):
42
+ """Result data from the execution of a CloseGripperJaw command."""
39
43
 
40
44
  pass
41
45
 
42
46
 
43
- class closeGripperJawImplementation(
44
- AbstractCommandImpl[closeGripperJawParams, SuccessData[closeGripperJawResult]]
47
+ class CloseGripperJawImplementation(
48
+ AbstractCommandImpl[CloseGripperJawParams, SuccessData[CloseGripperJawResult]]
45
49
  ):
46
- """closeGripperJaw command implementation."""
50
+ """CloseGripperJaw command implementation."""
47
51
 
48
52
  def __init__(
49
53
  self,
50
54
  hardware_api: HardwareControlAPI,
55
+ state_view: StateView,
51
56
  **kwargs: object,
52
57
  ) -> None:
53
58
  self._hardware_api = hardware_api
59
+ self._state_view = state_view
54
60
 
55
61
  async def execute(
56
- self, params: closeGripperJawParams
57
- ) -> SuccessData[closeGripperJawResult]:
62
+ self, params: CloseGripperJawParams
63
+ ) -> SuccessData[CloseGripperJawResult]:
58
64
  """Release the gripper."""
65
+ if self._state_view.config.use_virtual_gripper:
66
+ return SuccessData(
67
+ public=CloseGripperJawResult(),
68
+ )
59
69
  ot3_hardware_api = ensure_ot3_hardware(self._hardware_api)
60
70
  await ot3_hardware_api.grip(force_newtons=params.force)
61
71
  return SuccessData(
62
- public=closeGripperJawResult(),
72
+ public=CloseGripperJawResult(),
63
73
  )
64
74
 
65
75
 
66
- class closeGripperJaw(
67
- BaseCommand[closeGripperJawParams, closeGripperJawResult, ErrorOccurrence]
76
+ class CloseGripperJaw(
77
+ BaseCommand[CloseGripperJawParams, CloseGripperJawResult, ErrorOccurrence]
68
78
  ):
69
- """closeGripperJaw command model."""
79
+ """CloseGripperJaw command model."""
70
80
 
71
- commandType: closeGripperJawCommandType = "robot/closeGripperJaw"
72
- params: closeGripperJawParams
73
- result: Optional[closeGripperJawResult] = None
81
+ commandType: CloseGripperJawCommandType = "robot/closeGripperJaw"
82
+ params: CloseGripperJawParams
83
+ result: Optional[CloseGripperJawResult] = None
74
84
 
75
85
  _ImplementationCls: Type[
76
- closeGripperJawImplementation
77
- ] = closeGripperJawImplementation
86
+ CloseGripperJawImplementation
87
+ ] = CloseGripperJawImplementation
78
88
 
79
89
 
80
- class closeGripperJawCreate(BaseCommandCreate[closeGripperJawParams]):
81
- """closeGripperJaw command request model."""
90
+ class CloseGripperJawCreate(BaseCommandCreate[CloseGripperJawParams]):
91
+ """CloseGripperJaw command request model."""
82
92
 
83
- commandType: closeGripperJawCommandType = "robot/closeGripperJaw"
84
- params: closeGripperJawParams
93
+ commandType: CloseGripperJawCommandType = "robot/closeGripperJaw"
94
+ params: CloseGripperJawParams
85
95
 
86
- _CommandCls: Type[closeGripperJaw] = closeGripperJaw
96
+ _CommandCls: Type[CloseGripperJaw] = CloseGripperJaw