opentrons 8.2.0a2__py2.py3-none-any.whl → 8.2.0a4__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 (24) hide show
  1. opentrons/drivers/absorbance_reader/async_byonoy.py +5 -4
  2. opentrons/hardware_control/backends/ot3utils.py +1 -0
  3. opentrons/hardware_control/modules/absorbance_reader.py +2 -0
  4. opentrons/hardware_control/types.py +2 -0
  5. opentrons/protocol_api/module_contexts.py +56 -26
  6. opentrons/protocol_engine/commands/absorbance_reader/read.py +4 -0
  7. opentrons/protocol_engine/commands/aspirate_in_place.py +3 -3
  8. opentrons/protocol_engine/commands/command.py +3 -1
  9. opentrons/protocol_engine/commands/dispense_in_place.py +1 -1
  10. opentrons/protocol_engine/commands/drop_tip.py +2 -1
  11. opentrons/protocol_engine/commands/drop_tip_in_place.py +7 -2
  12. opentrons/protocol_engine/commands/pick_up_tip.py +1 -1
  13. opentrons/protocol_engine/commands/pipetting_common.py +8 -1
  14. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +3 -1
  15. opentrons/protocol_engine/errors/error_occurrence.py +8 -3
  16. opentrons/protocol_engine/state/modules.py +4 -1
  17. opentrons/protocol_runner/run_orchestrator.py +15 -0
  18. opentrons/protocols/parameters/csv_parameter_interface.py +3 -1
  19. {opentrons-8.2.0a2.dist-info → opentrons-8.2.0a4.dist-info}/METADATA +4 -4
  20. {opentrons-8.2.0a2.dist-info → opentrons-8.2.0a4.dist-info}/RECORD +24 -24
  21. {opentrons-8.2.0a2.dist-info → opentrons-8.2.0a4.dist-info}/LICENSE +0 -0
  22. {opentrons-8.2.0a2.dist-info → opentrons-8.2.0a4.dist-info}/WHEEL +0 -0
  23. {opentrons-8.2.0a2.dist-info → opentrons-8.2.0a4.dist-info}/entry_points.txt +0 -0
  24. {opentrons-8.2.0a2.dist-info → opentrons-8.2.0a4.dist-info}/top_level.txt +0 -0
@@ -23,7 +23,8 @@ from opentrons.hardware_control.modules.errors import AbsorbanceReaderDisconnect
23
23
 
24
24
 
25
25
  SN_PARSER = re.compile(r'ATTRS{serial}=="(?P<serial>.+?)"')
26
- VERSION_PARSER = re.compile(r"Absorbance (?P<version>V\d+\.\d+\.\d+)")
26
+ # match semver V0.0.0 (old format) or one integer (latest format)
27
+ VERSION_PARSER = re.compile(r"(?P<version>(V\d+\.\d+\.\d+|^\d+$))")
27
28
  SERIAL_PARSER = re.compile(r"(?P<serial>(OPT|BYO)[A-Z]{3}[0-9]+)")
28
29
 
29
30
 
@@ -156,10 +157,10 @@ class AsyncByonoy:
156
157
  func=partial(self._interface.get_device_information, handle),
157
158
  )
158
159
  self._raise_if_error(err.name, f"Error getting device information: {err}")
159
- serial_match = SERIAL_PARSER.fullmatch(device_info.sn)
160
- version_match = VERSION_PARSER.match(device_info.version)
160
+ serial_match = SERIAL_PARSER.match(device_info.sn)
161
+ version_match = VERSION_PARSER.search(device_info.version)
161
162
  serial = serial_match["serial"].strip() if serial_match else "OPTMAA00000"
162
- version = version_match["version"].lower() if version_match else "v0.0.0"
163
+ version = version_match["version"].lower() if version_match else "v0"
163
164
  info = {
164
165
  "serial": serial,
165
166
  "version": version,
@@ -652,6 +652,7 @@ _gripper_jaw_state_lookup: Dict[FirmwareGripperjawState, GripperJawState] = {
652
652
  FirmwareGripperjawState.force_controlling_home: GripperJawState.HOMED_READY,
653
653
  FirmwareGripperjawState.force_controlling: GripperJawState.GRIPPING,
654
654
  FirmwareGripperjawState.position_controlling: GripperJawState.HOLDING,
655
+ FirmwareGripperjawState.stopped: GripperJawState.STOPPED,
655
656
  }
656
657
 
657
658
 
@@ -312,6 +312,8 @@ class AbsorbanceReader(mod_abc.AbstractModule):
312
312
  log.debug(f"Updating {self.name}: {self.port} with {firmware_file_path}")
313
313
  self._updating = True
314
314
  success, res = await self._driver.update_firmware(firmware_file_path)
315
+ # it takes time for the plate reader to re-init after an update.
316
+ await asyncio.sleep(10)
315
317
  self._device_info = await self._driver.get_device_info()
316
318
  await self._poller.start()
317
319
  self._updating = False
@@ -625,6 +625,8 @@ class GripperJawState(enum.Enum):
625
625
  #: the gripper is actively force-control gripping something
626
626
  HOLDING = enum.auto()
627
627
  #: the gripper is in position-control mode
628
+ STOPPED = enum.auto()
629
+ #: the gripper has been homed before but is stopped now
628
630
 
629
631
 
630
632
  class InstrumentProbeType(enum.Enum):
@@ -581,7 +581,7 @@ class ThermocyclerContext(ModuleContext):
581
581
  individual well of the loaded labware, in µL.
582
582
  If not specified, the default is 25 µL.
583
583
 
584
- .. note:
584
+ .. note::
585
585
 
586
586
  If ``hold_time_minutes`` and ``hold_time_seconds`` are not
587
587
  specified, the Thermocycler will proceed to the next command
@@ -605,7 +605,7 @@ class ThermocyclerContext(ModuleContext):
605
605
  :param temperature: A value between 37 and 110, representing the target
606
606
  temperature in °C.
607
607
 
608
- .. note:
608
+ .. note::
609
609
 
610
610
  The Thermocycler will proceed to the next command immediately after
611
611
  ``temperature`` has been reached.
@@ -635,13 +635,13 @@ class ThermocyclerContext(ModuleContext):
635
635
  individual well of the loaded labware, in µL.
636
636
  If not specified, the default is 25 µL.
637
637
 
638
- .. note:
638
+ .. note::
639
639
 
640
640
  Unlike with :py:meth:`set_block_temperature`, either or both of
641
641
  ``hold_time_minutes`` and ``hold_time_seconds`` must be defined
642
642
  and for each step.
643
643
 
644
- .. note:
644
+ .. note::
645
645
 
646
646
  Before API Version 2.21, Thermocycler profiles run with this command
647
647
  would be listed in the app as having a number of repetitions equal to
@@ -991,7 +991,7 @@ class MagneticBlockContext(ModuleContext):
991
991
 
992
992
 
993
993
  class AbsorbanceReaderContext(ModuleContext):
994
- """An object representing a connected Absorbance Reader Module.
994
+ """An object representing a connected Absorbance Plate Reader Module.
995
995
 
996
996
  It should not be instantiated directly; instead, it should be
997
997
  created through :py:meth:`.ProtocolContext.load_module`.
@@ -1009,17 +1009,21 @@ class AbsorbanceReaderContext(ModuleContext):
1009
1009
 
1010
1010
  @requires_version(2, 21)
1011
1011
  def close_lid(self) -> None:
1012
- """Close the lid of the Absorbance Reader."""
1012
+ """Use the Flex Gripper to close the lid of the Absorbance Plate Reader.
1013
+
1014
+ You must call this method before initializing the reader, even if the reader was
1015
+ in the closed position at the start of the protocol.
1016
+ """
1013
1017
  self._core.close_lid()
1014
1018
 
1015
1019
  @requires_version(2, 21)
1016
1020
  def open_lid(self) -> None:
1017
- """Open the lid of the Absorbance Reader."""
1021
+ """Use the Flex Gripper to open the lid of the Absorbance Plate Reader."""
1018
1022
  self._core.open_lid()
1019
1023
 
1020
1024
  @requires_version(2, 21)
1021
1025
  def is_lid_on(self) -> bool:
1022
- """Return ``True`` if the Absorbance Reader's lid is currently closed."""
1026
+ """Return ``True`` if the Absorbance Plate Reader's lid is currently closed."""
1023
1027
  return self._core.is_lid_on()
1024
1028
 
1025
1029
  @requires_version(2, 21)
@@ -1029,19 +1033,28 @@ class AbsorbanceReaderContext(ModuleContext):
1029
1033
  wavelengths: List[int],
1030
1034
  reference_wavelength: Optional[int] = None,
1031
1035
  ) -> None:
1032
- """Take a zero reading on the Absorbance Plate Reader Module.
1036
+ """Prepare the Absorbance Plate Reader to read a plate.
1037
+
1038
+ See :ref:`absorbance-initialization` for examples.
1033
1039
 
1034
1040
  :param mode: Either ``"single"`` or ``"multi"``.
1035
1041
 
1036
- - In single measurement mode, :py:meth:`.AbsorbanceReaderContext.read` uses
1037
- one sample wavelength and an optional reference wavelength.
1038
- - In multiple measurement mode, :py:meth:`.AbsorbanceReaderContext.read` uses
1039
- a list of up to six sample wavelengths.
1040
- :param wavelengths: A list of wavelengths, in mm, to measure.
1041
- - Must contain only one item when initializing a single measurement.
1042
- - Must contain one to six items when initializing a multiple measurement.
1043
- :param reference_wavelength: An optional reference wavelength, in mm. Cannot be
1044
- used with multiple measurements.
1042
+ - In single measurement mode, :py:meth:`.AbsorbanceReaderContext.read` uses
1043
+ one sample wavelength and an optional reference wavelength.
1044
+ - In multiple measurement mode, :py:meth:`.AbsorbanceReaderContext.read` uses
1045
+ a list of up to six sample wavelengths.
1046
+ :param wavelengths: A list of wavelengths, in nm, to measure.
1047
+
1048
+ - In the default hardware configuration, each wavelength must be one of
1049
+ ``450`` (blue), ``562`` (green), ``600`` (orange), or ``650`` (red). In
1050
+ custom hardware configurations, the module may accept other integers
1051
+ between 350 and 1000.
1052
+ - The list must contain only one item when initializing a single measurement.
1053
+ - The list can contain one to six items when initializing a multiple measurement.
1054
+ :param reference_wavelength: An optional reference wavelength, in nm. If provided,
1055
+ :py:meth:`.AbsorbanceReaderContext.read` will read at the reference
1056
+ wavelength and then subtract the reference wavelength values from the
1057
+ measurement wavelength values. Can only be used with single measurements.
1045
1058
  """
1046
1059
  self._core.initialize(
1047
1060
  mode, wavelengths, reference_wavelength=reference_wavelength
@@ -1051,16 +1064,33 @@ class AbsorbanceReaderContext(ModuleContext):
1051
1064
  def read(
1052
1065
  self, export_filename: Optional[str] = None
1053
1066
  ) -> Dict[int, Dict[str, float]]:
1054
- """Initiate read on the Absorbance Reader.
1067
+ """Read a plate on the Absorbance Plate Reader.
1068
+
1069
+ This method always returns a dictionary of measurement data. It optionally will
1070
+ save a CSV file of the results to the Flex filesystem, which you can access from
1071
+ the Recent Protocol Runs screen in the Opentrons App. These files are `only` saved
1072
+ if you specify ``export_filename``.
1073
+
1074
+ In simulation, the values for each well key in the dictionary are set to zero, and
1075
+ no files are written.
1076
+
1077
+ .. note::
1078
+
1079
+ Avoid divide-by-zero errors when simulating and using the results of this
1080
+ method later in the protocol. If you divide by any of the measurement
1081
+ values, use :py:meth:`.ProtocolContext.is_simulating` to use alternate dummy
1082
+ data or skip the division step.
1055
1083
 
1056
- Returns a dictionary of wavelengths to dictionary of values ordered by well name.
1084
+ :param export_filename: An optional file basename. If provided, this method
1085
+ will write a CSV file for each measurement in the read operation. File
1086
+ names will use the value of this parameter, the measurement wavelength
1087
+ supplied in :py:meth:`~.AbsorbanceReaderContext.initialize`, and a
1088
+ ``.csv`` extension. For example, when reading at wavelengths 450 and 562
1089
+ with ``export_filename="my_data"``, there will be two output files:
1090
+ ``my_data_450.csv`` and ``my_data_562.csv``.
1057
1091
 
1058
- :param export_filename: Optional, if a filename is provided a CSV file will be saved
1059
- as a result of the read action containing measurement data. The filename will
1060
- be modified to include the wavelength used during measurement. If multiple
1061
- measurements are taken, then a file will be generated for each wavelength provided.
1092
+ See :ref:`absorbance-csv` for information on working with these CSV files.
1062
1093
 
1063
- Example: If `export_filename="my_data"` and wavelengths 450 and 531 are used during
1064
- measurement, the output files will be "my_data_450.csv" and "my_data_531.csv".
1094
+ :returns: A dictionary of wavelengths to dictionary of values ordered by well name.
1065
1095
  """
1066
1096
  return self._core.read(filename=export_filename)
@@ -80,6 +80,10 @@ class ReadAbsorbanceImpl(
80
80
  raise CannotPerformModuleAction(
81
81
  "Cannot perform Read action on Absorbance Reader without calling `.initialize(...)` first."
82
82
  )
83
+ if abs_reader_substate.is_lid_on is False:
84
+ raise CannotPerformModuleAction(
85
+ "Absorbance Plate Reader can't read a plate with the lid open. Call `close_lid()` first."
86
+ )
83
87
 
84
88
  # TODO: we need to return a file ID and increase the file count even when a moduel is not attached
85
89
  if (
@@ -83,10 +83,11 @@ class AspirateInPlaceImplementation(
83
83
  TipNotAttachedError: if no tip is attached to the pipette.
84
84
  PipetteNotReadyToAspirateError: pipette plunger is not ready.
85
85
  """
86
+ state_update = StateUpdate()
87
+
86
88
  ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
87
89
  pipette_id=params.pipetteId,
88
90
  )
89
-
90
91
  if not ready_to_aspirate:
91
92
  raise PipetteNotReadyToAspirateError(
92
93
  "Pipette cannot aspirate in place because of a previous blow out."
@@ -94,11 +95,10 @@ class AspirateInPlaceImplementation(
94
95
  " so the plunger can be reset in a known safe position."
95
96
  )
96
97
 
97
- state_update = StateUpdate()
98
98
  current_location = self._state_view.pipettes.get_current_location()
99
+ current_position = await self._gantry_mover.get_position(params.pipetteId)
99
100
 
100
101
  try:
101
- current_position = await self._gantry_mover.get_position(params.pipetteId)
102
102
  volume = await self._pipetting.aspirate_in_place(
103
103
  pipette_id=params.pipetteId,
104
104
  volume=params.volume,
@@ -185,7 +185,9 @@ class BaseCommand(
185
185
  )
186
186
  error: Union[
187
187
  _ErrorT,
188
- # ErrorOccurrence here is for undefined errors not captured by _ErrorT.
188
+ # ErrorOccurrence here is a catch-all for undefined errors not captured by
189
+ # _ErrorT, or defined errors that don't parse into _ErrorT because, for example,
190
+ # they are from an older software version that was missing some fields.
189
191
  ErrorOccurrence,
190
192
  None,
191
193
  ] = Field(
@@ -76,8 +76,8 @@ class DispenseInPlaceImplementation(
76
76
  """Dispense without moving the pipette."""
77
77
  state_update = StateUpdate()
78
78
  current_location = self._state_view.pipettes.get_current_location()
79
+ current_position = await self._gantry_mover.get_position(params.pipetteId)
79
80
  try:
80
- current_position = await self._gantry_mover.get_position(params.pipetteId)
81
81
  volume = await self._pipetting.dispense_in_place(
82
82
  pipette_id=params.pipetteId,
83
83
  volume=params.volume,
@@ -145,6 +145,7 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
145
145
  error=exception,
146
146
  )
147
147
  ],
148
+ errorInfo={"retryLocation": position},
148
149
  )
149
150
  state_update_if_false_positive = update_types.StateUpdate()
150
151
  state_update_if_false_positive.update_pipette_tip_state(
@@ -165,7 +166,7 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
165
166
  )
166
167
 
167
168
 
168
- class DropTip(BaseCommand[DropTipParams, DropTipResult, ErrorOccurrence]):
169
+ class DropTip(BaseCommand[DropTipParams, DropTipResult, TipPhysicallyAttachedError]):
169
170
  """Drop tip command model."""
170
171
 
171
172
  commandType: DropTipCommandType = "dropTip"
@@ -18,7 +18,7 @@ from ..resources.model_utils import ModelUtils
18
18
  from ..state import update_types
19
19
 
20
20
  if TYPE_CHECKING:
21
- from ..execution import TipHandler
21
+ from ..execution import TipHandler, GantryMover
22
22
 
23
23
 
24
24
  DropTipInPlaceCommandType = Literal["dropTipInPlace"]
@@ -57,15 +57,19 @@ class DropTipInPlaceImplementation(
57
57
  self,
58
58
  tip_handler: TipHandler,
59
59
  model_utils: ModelUtils,
60
+ gantry_mover: GantryMover,
60
61
  **kwargs: object,
61
62
  ) -> None:
62
63
  self._tip_handler = tip_handler
63
64
  self._model_utils = model_utils
65
+ self._gantry_mover = gantry_mover
64
66
 
65
67
  async def execute(self, params: DropTipInPlaceParams) -> _ExecuteReturn:
66
68
  """Drop a tip using the requested pipette."""
67
69
  state_update = update_types.StateUpdate()
68
70
 
71
+ retry_location = await self._gantry_mover.get_position(params.pipetteId)
72
+
69
73
  try:
70
74
  await self._tip_handler.drop_tip(
71
75
  pipette_id=params.pipetteId, home_after=params.homeAfter
@@ -85,6 +89,7 @@ class DropTipInPlaceImplementation(
85
89
  error=exception,
86
90
  )
87
91
  ],
92
+ errorInfo={"retryLocation": retry_location},
88
93
  )
89
94
  return DefinedErrorData(
90
95
  public=error,
@@ -99,7 +104,7 @@ class DropTipInPlaceImplementation(
99
104
 
100
105
 
101
106
  class DropTipInPlace(
102
- BaseCommand[DropTipInPlaceParams, DropTipInPlaceResult, ErrorOccurrence]
107
+ BaseCommand[DropTipInPlaceParams, DropTipInPlaceResult, TipPhysicallyAttachedError]
103
108
  ):
104
109
  """Drop tip in place command model."""
105
110
 
@@ -82,7 +82,7 @@ class TipPhysicallyMissingError(ErrorOccurrence):
82
82
  isDefined: bool = True
83
83
  errorType: Literal["tipPhysicallyMissing"] = "tipPhysicallyMissing"
84
84
  errorCode: str = ErrorCodes.TIP_PICKUP_FAILED.value.code
85
- detail: str = "No tip detected."
85
+ detail: str = "No Tip Detected"
86
86
 
87
87
 
88
88
  _ExecuteReturn = Union[
@@ -148,7 +148,12 @@ class DestinationPositionResult(BaseModel):
148
148
 
149
149
 
150
150
  class ErrorLocationInfo(TypedDict):
151
- """Holds a retry location for in-place error recovery."""
151
+ """Holds a retry location for in-place error recovery.
152
+
153
+ This is appropriate to pass to a `moveToCoordinates` command,
154
+ assuming the pipette has not been configured with a different nozzle layout
155
+ in the meantime.
156
+ """
152
157
 
153
158
  retryLocation: Tuple[float, float, float]
154
159
 
@@ -201,3 +206,5 @@ class TipPhysicallyAttachedError(ErrorOccurrence):
201
206
 
202
207
  errorCode: str = ErrorCodes.TIP_DROP_FAILED.value.code
203
208
  detail: str = ErrorCodes.TIP_DROP_FAILED.value.detail
209
+
210
+ errorInfo: ErrorLocationInfo
@@ -1,6 +1,8 @@
1
1
  """Ungrip labware payload, result, and implementaiton."""
2
2
 
3
3
  from __future__ import annotations
4
+
5
+ from opentrons.hardware_control.types import Axis
4
6
  from opentrons.protocol_engine.errors.exceptions import GripperNotAttachedError
5
7
  from pydantic import BaseModel
6
8
  from typing import Optional, Type
@@ -46,7 +48,7 @@ class UnsafeUngripLabwareImplementation(
46
48
  ot3_hardware_api = ensure_ot3_hardware(self._hardware_api)
47
49
  if not ot3_hardware_api.has_gripper():
48
50
  raise GripperNotAttachedError("No gripper found to perform ungrip.")
49
- await ot3_hardware_api.ungrip()
51
+ await ot3_hardware_api.home([Axis.G])
50
52
  return SuccessData(
51
53
  public=UnsafeUngripLabwareResult(),
52
54
  )
@@ -12,8 +12,6 @@ from opentrons_shared_data.errors.exceptions import EnumeratedError
12
12
  log = getLogger(__name__)
13
13
 
14
14
 
15
- # TODO(mc, 2021-11-12): flesh this model out with structured error data
16
- # for each error type so client may produce better error messages
17
15
  class ErrorOccurrence(BaseModel):
18
16
  """An occurrence of a specific error during protocol execution."""
19
17
 
@@ -44,8 +42,15 @@ class ErrorOccurrence(BaseModel):
44
42
  id: str = Field(..., description="Unique identifier of this error occurrence.")
45
43
  createdAt: datetime = Field(..., description="When the error occurred.")
46
44
 
45
+ # Our Python should probably always set this to False--if we want it to be True,
46
+ # we should probably be using a more specific subclass of ErrorOccurrence anyway.
47
+ # However, we can't make this Literal[False], because we want this class to be able
48
+ # to act as a catch-all for parsing defined errors that might be missing some
49
+ # `errorInfo` fields because they were serialized by older software.
47
50
  isDefined: bool = Field(
48
- default=False, # default=False for database backwards compatibility.
51
+ # default=False for database backwards compatibility, so we can parse objects
52
+ # serialized before isDefined existed.
53
+ default=False,
49
54
  description=dedent(
50
55
  """\
51
56
  Whether this error is *defined.*
@@ -1268,7 +1268,10 @@ class ModuleView(HasState[ModuleState]):
1268
1268
  row = chr(ord("A") + i // 12) # Convert index to row (A-H)
1269
1269
  col = (i % 12) + 1 # Convert index to column (1-12)
1270
1270
  well_key = f"{row}{col}"
1271
- well_map[well_key] = value
1271
+ truncated_value = float(
1272
+ "{:.5}".format(str(value))
1273
+ ) # Truncate the returned value to the third decimal place
1274
+ well_map[well_key] = truncated_value
1272
1275
  return well_map
1273
1276
  else:
1274
1277
  raise ValueError(
@@ -418,6 +418,21 @@ class RunOrchestrator:
418
418
  """Get current nozzle maps keyed by pipette id."""
419
419
  return self._protocol_engine.state_view.tips.get_pipette_nozzle_maps()
420
420
 
421
+ def get_tip_attached(self) -> Dict[str, bool]:
422
+ """Get current tip state keyed by pipette id."""
423
+
424
+ def has_tip_attached(pipette_id: str) -> bool:
425
+ return (
426
+ self._protocol_engine.state_view.pipettes.get_attached_tip(pipette_id)
427
+ is not None
428
+ )
429
+
430
+ pipette_ids = (
431
+ pipette.id
432
+ for pipette in self._protocol_engine.state_view.pipettes.get_all()
433
+ )
434
+ return {pipette_id: has_tip_attached(pipette_id) for pipette_id in pipette_ids}
435
+
421
436
  def set_error_recovery_policy(self, policy: ErrorRecoveryPolicy) -> None:
422
437
  """Create error recovery policy for the run."""
423
438
  self._protocol_engine.set_error_recovery_policy(policy)
@@ -60,7 +60,9 @@ class CSVParameter:
60
60
  as appropriate.
61
61
 
62
62
  :param detect_dialect: If ``True``, examine the file and try to assign it a
63
- :py:class:`csv.Dialect` to improve parsing behavior.
63
+ :py:class:`csv.Dialect` to improve parsing behavior. Set this to ``False``
64
+ when using the file output of :py:meth:`.AbsorbanceReaderContext.read` as
65
+ a runtime parameter.
64
66
  :param kwargs: For advanced CSV handling, you can pass any of the
65
67
  `formatting parameters <https://docs.python.org/3/library/csv.html#csv-fmt-params>`_
66
68
  accepted by :py:func:`csv.reader` from the Python standard library.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opentrons
3
- Version: 8.2.0a2
3
+ Version: 8.2.0a4
4
4
  Summary: The Opentrons API is a simple framework designed to make writing automated biology lab protocols easy.
5
5
  Author: Opentrons
6
6
  Author-email: engineering@opentrons.com
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Topic :: Scientific/Engineering
22
22
  Requires-Python: >=3.10
23
23
  License-File: ../LICENSE
24
- Requires-Dist: opentrons-shared-data ==8.2.0a2
24
+ Requires-Dist: opentrons-shared-data ==8.2.0a4
25
25
  Requires-Dist: aionotify ==0.3.1
26
26
  Requires-Dist: anyio <4.0.0,>=3.6.1
27
27
  Requires-Dist: jsonschema <4.18.0,>=3.0.1
@@ -34,9 +34,9 @@ Requires-Dist: pyusb ==1.2.1
34
34
  Requires-Dist: packaging >=21.0
35
35
  Requires-Dist: importlib-metadata >=1.0 ; python_version < "3.8"
36
36
  Provides-Extra: flex-hardware
37
- Requires-Dist: opentrons-hardware[flex] ==8.2.0a2 ; extra == 'flex-hardware'
37
+ Requires-Dist: opentrons-hardware[flex] ==8.2.0a4 ; extra == 'flex-hardware'
38
38
  Provides-Extra: ot2-hardware
39
- Requires-Dist: opentrons-hardware ==8.2.0a2 ; extra == 'ot2-hardware'
39
+ Requires-Dist: opentrons-hardware ==8.2.0a4 ; extra == 'ot2-hardware'
40
40
 
41
41
  .. _Full API Documentation: http://docs.opentrons.com
42
42
 
@@ -47,7 +47,7 @@ opentrons/drivers/types.py,sha256=muQKlqOMYcL6iglT9a3iEJ5EnqcBDCkgHz2KyePsm6I,22
47
47
  opentrons/drivers/utils.py,sha256=QmSTP07PPXq3_Qth1Idagn7lixWFjpkOzR8LFSpcw-g,7362
48
48
  opentrons/drivers/absorbance_reader/__init__.py,sha256=d9_-VJ_MKOyRy9C5Ioeg4CWsC1WIVgQlxGqBvgpoBRc,322
49
49
  opentrons/drivers/absorbance_reader/abstract.py,sha256=Egc7RKKXscEXFC0bPVx_r1vKe2-Df9PJyDpH0OFOIiw,2005
50
- opentrons/drivers/absorbance_reader/async_byonoy.py,sha256=pp4lvODBd3ydKwac28RANQgWs_X5Ml2NdFw0ZHgpXPA,13502
50
+ opentrons/drivers/absorbance_reader/async_byonoy.py,sha256=zmRC1nTHDx1X_paN7mSPYdHMtKtKpmrs0KnEUDHdD58,13558
51
51
  opentrons/drivers/absorbance_reader/driver.py,sha256=V8hLjNRVzlRPtVW04XEWrXytn06ZRBxG9LqL4ETj21g,2791
52
52
  opentrons/drivers/absorbance_reader/hid_protocol.py,sha256=OM6Ogkl1Lw3d501rfHcRI3lPZITAVKdxCR6JkHdKMCQ,3836
53
53
  opentrons/drivers/absorbance_reader/simulator.py,sha256=MiFQgnVNq2R35T3u59idcKlrj6SEFllt8tdupfH5jKQ,2419
@@ -107,7 +107,7 @@ opentrons/hardware_control/robot_calibration.py,sha256=HiCQNmdp59SbkzXpDGtPsN8rS
107
107
  opentrons/hardware_control/simulator_setup.py,sha256=3gelKslgMDobLpIlhVHmAqmZ5wXe1hZcK4RwKRMy3aM,9277
108
108
  opentrons/hardware_control/thread_manager.py,sha256=3-PrzUzJFSjUVtrgTUEF5GIStsDufvaSbp51B2x-yJY,17253
109
109
  opentrons/hardware_control/threaded_async_lock.py,sha256=qMaIrJ4KSMzvKm0hWt4o74Joah-sc404LlhMjCJue2g,3316
110
- opentrons/hardware_control/types.py,sha256=1A0-2eWLXRWsbTJKSjm_OGyqLZiX5z9aaKN_AvOJE5o,20691
110
+ opentrons/hardware_control/types.py,sha256=Df4FGgsoPeTiX5EQes4MGW4O1hoJxLI0SU3Fo-whsPs,20777
111
111
  opentrons/hardware_control/util.py,sha256=RSlfjzrmhtntSexamNpPn3-qrnbrdhuzEjOnxv8v7lA,8650
112
112
  opentrons/hardware_control/backends/__init__.py,sha256=u5Dg3AFZuvDV7hFqJ8I4F9D1dLDt6e-TsFJReyBYe4E,212
113
113
  opentrons/hardware_control/backends/controller.py,sha256=MOVMq9s1rY_jHhajHB1hQ1MgXXyY54-gMrrvAuMsOFg,14622
@@ -116,7 +116,7 @@ opentrons/hardware_control/backends/estop_state.py,sha256=_GYjI6OaD3CZNduWV2_RVe
116
116
  opentrons/hardware_control/backends/flex_protocol.py,sha256=PlGUMXTRISFl9c-ZxU2TdPDursLAprPw6ZLqtGMngIE,12030
117
117
  opentrons/hardware_control/backends/ot3controller.py,sha256=3y18NJbFDKMkfLk4X8ApIcZ9n3EMtZqCqag5hTUS74g,61020
118
118
  opentrons/hardware_control/backends/ot3simulator.py,sha256=N63d7Qf1DHg_-sVxsRZsKoJIZtTRJIRVNZL2V_EE5Os,29502
119
- opentrons/hardware_control/backends/ot3utils.py,sha256=3y3jb0NdveIXd06X7wllfkx2hkc5NYtxwRrr8OxW1Vs,21893
119
+ opentrons/hardware_control/backends/ot3utils.py,sha256=Y0V26XqPxKzZmMhc0pBdfibC_En9pWmU77kyD7tDHOg,21955
120
120
  opentrons/hardware_control/backends/simulator.py,sha256=q_9PQlBdOyCa9sj2gLqYWZ-fG9v4mddDAiScL-yHCXY,17549
121
121
  opentrons/hardware_control/backends/status_bar_state.py,sha256=ftNn2ouBhPZiFbUm79I4z6ndup7XDmcNowhb-KREspE,8529
122
122
  opentrons/hardware_control/backends/subsystem_manager.py,sha256=lv2ON2pZ7PY2tg3-qxpAlLYIg1SJxX3erHJvcfy5UGs,16484
@@ -160,7 +160,7 @@ opentrons/hardware_control/instruments/ot3/instrument_calibration.py,sha256=9ERA
160
160
  opentrons/hardware_control/instruments/ot3/pipette.py,sha256=rrbN1Du1pTL8-pZ19K38ns_w5SMDMHcUG3Wh5nuxdWo,32493
161
161
  opentrons/hardware_control/instruments/ot3/pipette_handler.py,sha256=G6cL5qjwgi4hXKUNwvnJDEaeX0u2xp-U-dEHLRo_5pc,36704
162
162
  opentrons/hardware_control/modules/__init__.py,sha256=YLYJShv7FDI_QHboB2lQkSxoILoW9ms6Opu45ZeMMBU,1306
163
- opentrons/hardware_control/modules/absorbance_reader.py,sha256=dCbOyHvQdN3KXh2EUnLuD1C6Wpe-ft-dmcfX4H39KY8,13468
163
+ opentrons/hardware_control/modules/absorbance_reader.py,sha256=Z6ikQiySpDi4tP1VxT-Q0WCNLUqfyzJ-iw7B7t-CUNI,13573
164
164
  opentrons/hardware_control/modules/errors.py,sha256=cREqoMc6nwGxQbLvZYDfIlq1mCv0alN42J7qxNBNiOY,165
165
165
  opentrons/hardware_control/modules/heater_shaker.py,sha256=tp-j8jbkY1oRrvHkXwmMRng-tX4ARPPrEJsS1mSQFCo,15026
166
166
  opentrons/hardware_control/modules/lid_temp_status.py,sha256=XKlr41I41g8aFxrrqGZxecHWgtBceG9ZrOSkyqq1khE,1201
@@ -222,7 +222,7 @@ opentrons/protocol_api/deck.py,sha256=94vFceg1SC1bAGd7TvC1ZpYwnJR-VlzurEZ6jkacYe
222
222
  opentrons/protocol_api/disposal_locations.py,sha256=NRiSGmDR0LnbyEkWSOM-o64uR2fUoB1NWJG7Y7SsJSs,7920
223
223
  opentrons/protocol_api/instrument_context.py,sha256=EnOs4BAmpIabaWMFKCqhwIJcrWpP-iEv32kmdV2t9Uo,97275
224
224
  opentrons/protocol_api/labware.py,sha256=qwjAO1Au9Ujx5jyGNQ0-HLDBOXUygnXNSuv5696tGCw,48177
225
- opentrons/protocol_api/module_contexts.py,sha256=TZiswcxFRSFP_t_OoE03BSnOkZo9XQjoayHiUlVeqwA,40455
225
+ opentrons/protocol_api/module_contexts.py,sha256=qubmR4LrLwP8e-ONKQYBlLTRQ5gpB-H25fE3SV70sKI,42104
226
226
  opentrons/protocol_api/module_validation_and_errors.py,sha256=XL_m72P8rcvGO2fynY7UzXLcpGuI6X4s0V6Xf735Iyc,1464
227
227
  opentrons/protocol_api/protocol_context.py,sha256=3nVIYxTpFp2Ho6kdW65hG8LhDaTRvlFuGbuy9LsQg5s,55459
228
228
  opentrons/protocol_api/robot_context.py,sha256=vph_ZqfdmREOwLwpjSkXiSZSpI1HO0HuilhqjhgT7Rw,2660
@@ -281,19 +281,19 @@ opentrons/protocol_engine/clients/sync_client.py,sha256=f65mhTO3zwTph1LtCl7Td6z3
281
281
  opentrons/protocol_engine/clients/transports.py,sha256=QejmtG5TjgOLUXpNhOzor_q-7MFI1qNfsguwkzY6Rxc,7177
282
282
  opentrons/protocol_engine/commands/__init__.py,sha256=FKOX8Uq3g2_syxMQN0A70qEtpJrsJDlJfPhAxS4ZAII,14006
283
283
  opentrons/protocol_engine/commands/aspirate.py,sha256=zOh7wqqFlAdkQCUC1-pp0-Zi-6QEpg3ntXDTpzlgc4Y,6137
284
- opentrons/protocol_engine/commands/aspirate_in_place.py,sha256=0m3V2IMZm4PgekIPHkF9f7v52j3ngDNJuoppmF0p4xU,6003
284
+ opentrons/protocol_engine/commands/aspirate_in_place.py,sha256=pWU3Rfgi3i1vHG8_cKFmkot1sYKAYSxR-iQJlMpjTo4,5999
285
285
  opentrons/protocol_engine/commands/blow_out.py,sha256=qCxq_wa5spsr7kARCR1lRIODF4WQDCsZFJ4rhtJ4FXw,4191
286
286
  opentrons/protocol_engine/commands/blow_out_in_place.py,sha256=uJ6x8cXM1WcIKk6771FlVRLnO9-p5C8_FBCq0aGralk,3809
287
- opentrons/protocol_engine/commands/command.py,sha256=xBJBC2N40Ljkyp7hh5riXAu_2BWrgajU95uRVNvA3GI,9780
287
+ opentrons/protocol_engine/commands/command.py,sha256=LmZQAGRw_QnB77QNo242nonefqk1chg9A-MQ75F6GPs,9952
288
288
  opentrons/protocol_engine/commands/command_unions.py,sha256=30mrXVFxikW24rs3MeVBhpCevEbxs8NZ7EygLfi7O1M,20402
289
289
  opentrons/protocol_engine/commands/comment.py,sha256=yo2MpBEkILZ0R501eBW0-UACi15daH4COmghdDPz_FQ,1631
290
290
  opentrons/protocol_engine/commands/configure_for_volume.py,sha256=ZAZMWpFDU8C4GNRO-AEuMk1J2um11U5-iY3s3AaNi_M,3293
291
291
  opentrons/protocol_engine/commands/configure_nozzle_layout.py,sha256=86cYz78pVPtIiZu71TegHBIH9Gzz3Rz3LxI5-9bUJ5w,3802
292
292
  opentrons/protocol_engine/commands/custom.py,sha256=Gdhg8QrQ-PKphW1j8j3O2JEeCTQSQldldtNE-3YIdLU,2187
293
293
  opentrons/protocol_engine/commands/dispense.py,sha256=LcOjG9kzf0yUcnCBLGV6OmTur1Y_6B6ydUUvo3LFFok,5033
294
- opentrons/protocol_engine/commands/dispense_in_place.py,sha256=uJP947lhql7OrJtfcZUhiSN7nKnJsTGtDVkGp4aCpSI,5187
295
- opentrons/protocol_engine/commands/drop_tip.py,sha256=DdRPYbafoahQLkrgBG7X9GvzDxuyuz7oLbUeLcBC-Ko,6272
296
- opentrons/protocol_engine/commands/drop_tip_in_place.py,sha256=_FUBZ-FcmOoK57zZLrjCl_FSRk0RzUY_M1mGL2Js9vU,3914
294
+ opentrons/protocol_engine/commands/dispense_in_place.py,sha256=oiek-Xu3TvGv2tQY6BHcp4r1LW4bu1mAB58Nyr3FKWI,5183
295
+ opentrons/protocol_engine/commands/drop_tip.py,sha256=rjR7lAf20OvaFSRVgl78fFq_9dUW6U7-N7eHsq3hoK0,6338
296
+ opentrons/protocol_engine/commands/drop_tip_in_place.py,sha256=qTPwqXWkMW4rIQznxi3anRjCBH2UQE_WlcIHCPXypvc,4158
297
297
  opentrons/protocol_engine/commands/generate_command_schema.py,sha256=w5RsTJV4HtFpS58-xfVQ2O52h1R0zVTJkpLapN4uo9Y,1352
298
298
  opentrons/protocol_engine/commands/get_tip_presence.py,sha256=igvMiKJWzdetWBXlIaYp4Tfk57gfACon34CWzUWynno,2536
299
299
  opentrons/protocol_engine/commands/hash_command_params.py,sha256=obWy4TbVH97SyhNqrSD6iP1wgZ20JoaH1rilZCjXxIs,1530
@@ -309,8 +309,8 @@ opentrons/protocol_engine/commands/move_to_addressable_area.py,sha256=cJRXXRLkaw
309
309
  opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py,sha256=5BAisk0npPcesI6bMQxKH2Xxz641uyR6RbtU9RiD5NM,7134
310
310
  opentrons/protocol_engine/commands/move_to_coordinates.py,sha256=FQ1wQ9V3OcM4nSn-hWYWrxefcLMLZOw8WW6yARiRqDg,3051
311
311
  opentrons/protocol_engine/commands/move_to_well.py,sha256=0w5TsY51m5rmp-H7bd9EKWjTzJiz3ztyW647N5NxdHI,3292
312
- opentrons/protocol_engine/commands/pick_up_tip.py,sha256=Qd7ZZEKNT1cwlNZUZgZqtjnwJ7Iqgpf4dhIcbuf_0W0,6875
313
- opentrons/protocol_engine/commands/pipetting_common.py,sha256=Ds5FsMpBIxq2Y-2_ntGTsjC0eFZReXDSmVdk37LJOSI,6672
312
+ opentrons/protocol_engine/commands/pick_up_tip.py,sha256=1yzOenpKUDIQh_xrkea5hhD_0kxd00DmXpoIrvr6kuo,6874
313
+ opentrons/protocol_engine/commands/pipetting_common.py,sha256=JW_QzmBhwOXq_xONiSNyeHdLzFn2r--H6pDu05JNSJE,6879
314
314
  opentrons/protocol_engine/commands/prepare_to_aspirate.py,sha256=061KttjjIM4u5WejUViLwnIqrj97mr8V-4UjkbTbitU,3710
315
315
  opentrons/protocol_engine/commands/reload_labware.py,sha256=XPSQ1AHykiChI1CotwE73eF7FbULUqDQ1pUpOtEwrXc,3408
316
316
  opentrons/protocol_engine/commands/retract_axis.py,sha256=bMPJxQSYK9VsxraNl_SErXH9Dj4pBqrbx2gtTIg0MMw,2882
@@ -325,7 +325,7 @@ opentrons/protocol_engine/commands/absorbance_reader/__init__.py,sha256=umS98Llk
325
325
  opentrons/protocol_engine/commands/absorbance_reader/close_lid.py,sha256=i6kggql8hJgTxpUbc5dmdMdHDsYWiczfMvZNA72FmvI,5540
326
326
  opentrons/protocol_engine/commands/absorbance_reader/initialize.py,sha256=bbs7FwfpGVNAa5UT_rMV7ImrRnmREN9kRhmG8xJsAaU,5373
327
327
  opentrons/protocol_engine/commands/absorbance_reader/open_lid.py,sha256=Ef5coWs4GGOzmZbrAFZXTKq8hZCC7rJc2DVCOU2PFJg,5531
328
- opentrons/protocol_engine/commands/absorbance_reader/read.py,sha256=xu5KijW_sSEtjdhNIEctYkQBZC8Baj650W6s8nXfTKw,8187
328
+ opentrons/protocol_engine/commands/absorbance_reader/read.py,sha256=QZ8zjjlKQPXprekxsEjgFxmvLns4Q0NpnZ6hbFAoq6k,8403
329
329
  opentrons/protocol_engine/commands/calibration/__init__.py,sha256=JjNnULLBM3j8VtpfHOvH51em9jVLR_ezyrUJUWqxuYI,1611
330
330
  opentrons/protocol_engine/commands/calibration/calibrate_gripper.py,sha256=1HgEsH-0ycGD-OlxdmCTIuBeSCzVTc1vepSjVirai-g,5570
331
331
  opentrons/protocol_engine/commands/calibration/calibrate_module.py,sha256=zjkgPgHHn5CM-ztvbcKcTaAMvj9zsMLNyykynwec0j0,4172
@@ -363,10 +363,10 @@ opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py,sha256=K1i
363
363
  opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py,sha256=v5h1sLxx_NMAhVCLbmECd7sD0PsecB4Dj-oaBEe0YBs,3635
364
364
  opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py,sha256=hCRqFeBInC9Mxz9LqUgIrjTTAjuMEq5MJxCqqXwi3N4,2552
365
365
  opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py,sha256=etNdLxj0TtmBA5fTLR-OSfbnRNbXKDzE__aKRAkvWMM,7866
366
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py,sha256=MSYftVeLHqnIyX0n9IJLq6XOb7P835EQg7KR3n3PU6c,2397
366
+ opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py,sha256=408KbcJgroOA7Qhs-qih-ce-2n-ixGKu6mhv33TplJ0,2454
367
367
  opentrons/protocol_engine/commands/unsafe/update_position_estimators.py,sha256=Jgds_cwEHBiiDyJVK6wL34VTWZikrSVYJSRUohnsod8,3044
368
368
  opentrons/protocol_engine/errors/__init__.py,sha256=4CEG_WmrdSmESVkSkwfLlbNwW_r8TlMbD_fEXzcn5qg,5232
369
- opentrons/protocol_engine/errors/error_occurrence.py,sha256=PM_bxIxLYKtsRl_cGMiCtXVVMEb88hkLFEWcafwqLf8,7542
369
+ opentrons/protocol_engine/errors/error_occurrence.py,sha256=Uoa0tqJ4C-oosDUwk-XXf0NxgWVnVnnhTFOqJAT1J_o,7896
370
370
  opentrons/protocol_engine/errors/exceptions.py,sha256=yHLqtkKQbJev80zZYvZz8gjw8luXxWRrcJe3TEcIj88,40604
371
371
  opentrons/protocol_engine/execution/__init__.py,sha256=X8qTYYOc1v84JIDM1xYpIo3VG_BPnsrfl2jm9UUQGwQ,1384
372
372
  opentrons/protocol_engine/execution/command_executor.py,sha256=F1V7H_Y7mqc4hJMfs79aNZ7qG0NFh-xj2BHt4fSUK-4,8202
@@ -412,7 +412,7 @@ opentrons/protocol_engine/state/frustum_helpers.py,sha256=OMa7_3INieaNhkFb6wVC6l
412
412
  opentrons/protocol_engine/state/geometry.py,sha256=-yEsGHPfjUVNgVWJKeBiJyzl65wAzSvjS7W-kOxukCQ,67902
413
413
  opentrons/protocol_engine/state/labware.py,sha256=Ns_GoUKxL55P6J2YEch5GZCVvTbQZS0h4CbZwCr7Frc,44758
414
414
  opentrons/protocol_engine/state/liquids.py,sha256=TwchzB7xNt7CAd3wX3BA_5DXrQhGwj_uFQsv0FWOXXk,1886
415
- opentrons/protocol_engine/state/modules.py,sha256=8d5YOPhGs8jnw5mDQiGSrhtvozZkCtcRQd49YesVmds,53936
415
+ opentrons/protocol_engine/state/modules.py,sha256=NCx6s9WhFnv-XXIcnfnJ_rqLelI7pzqIv8v5ACrG2xE,54110
416
416
  opentrons/protocol_engine/state/motion.py,sha256=1KEm1HXdkuFKNe2lElZnNfJedml4afMFnmcDvG-3fLA,14937
417
417
  opentrons/protocol_engine/state/pipettes.py,sha256=jXhPGLHT1Ypc_tt8UkWZz51sCZ9ld4umr7AyuhlvxoU,30861
418
418
  opentrons/protocol_engine/state/state.py,sha256=HbkGfTLYNPlb9yu2sCi4UOJQrgXedi3w8xbYc0QCn-w,14550
@@ -446,7 +446,7 @@ opentrons/protocol_runner/legacy_command_mapper.py,sha256=N6Ubuz8VHHh0Ga3JgHVhBx
446
446
  opentrons/protocol_runner/legacy_context_plugin.py,sha256=G_qpeyaLvsCjb72_n96Luy8CPSfgPZpt0QKVzKc6LKY,4730
447
447
  opentrons/protocol_runner/protocol_runner.py,sha256=VtgqbcrcKhvWwGyl-LeX-0LjcQw3_frvwyi3d3UlzR8,20732
448
448
  opentrons/protocol_runner/python_protocol_wrappers.py,sha256=2eIGAlKCLfVSUjO5hhd_UKCEBQX_nS4Y9E5wXm2WvhY,6505
449
- opentrons/protocol_runner/run_orchestrator.py,sha256=H_1oryOKooKVmDaKukP9htm0JmgDTJJ6iRs-uEp8jxc,18324
449
+ opentrons/protocol_runner/run_orchestrator.py,sha256=d--Ezeo2M8hEk0Vjp2tZMvJFqaNKFkrQNB24F03DACo,18864
450
450
  opentrons/protocol_runner/task_queue.py,sha256=YH8_lvuLBYjfzXAOJU8DYXizQcbaxGmUiAPmd7kHERw,2581
451
451
  opentrons/protocols/__init__.py,sha256=cOUxilkIvdlqGvN4nYJQYr0TGdIWnzxBaTfoz3svmw8,245
452
452
  opentrons/protocols/bundle.py,sha256=QW_2kwnxgdG_nNPl2e110A5ehOH9Ej63-9TBx-F9Yvw,3666
@@ -485,7 +485,7 @@ opentrons/protocols/models/__init__.py,sha256=KePRAkkKzFoc0lAz8y89cWnxru8ofe3mow
485
485
  opentrons/protocols/models/json_protocol.py,sha256=lteWlIBXgRM86k-wO1dKsx02G2_4kustSDeSoyc5N5U,20128
486
486
  opentrons/protocols/parameters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
487
487
  opentrons/protocols/parameters/csv_parameter_definition.py,sha256=xZhGtdfH2vXSWFK-aGET07_L0LODvHWkfNxf7pQoOmo,2762
488
- opentrons/protocols/parameters/csv_parameter_interface.py,sha256=S7fdY39TxXqXO-jnaTZFLFI62n0HGc_XjYScWGB44VY,3945
488
+ opentrons/protocols/parameters/csv_parameter_interface.py,sha256=lcELoVQi3PRIDFd4Dw7bi4wODi1tjGuMb2F5X4c4m6Y,4086
489
489
  opentrons/protocols/parameters/exceptions.py,sha256=vQUeyy8Yk_fzP4bvT0r_zu3s7Aty3LM7PzTV6k2iXu0,1092
490
490
  opentrons/protocols/parameters/parameter_definition.py,sha256=OMtUCPKyFx5ZH3Jfcw05aF8pptWQ7XYzYttGMuSPu9k,9529
491
491
  opentrons/protocols/parameters/types.py,sha256=h7vaNmKbDHc1q_FzbZoIgoSVo0mvS64FeiLZDnv7xnQ,489
@@ -512,9 +512,9 @@ opentrons/util/helpers.py,sha256=3hr801bWGbxEcOFAS7f-iOhmnUhoK5qahbB8SIvaCfY,165
512
512
  opentrons/util/linal.py,sha256=IlKAP9HkNBBgULeSf4YVwSKHdx9jnCjSr7nvDvlRALg,5753
513
513
  opentrons/util/logging_config.py,sha256=t3xRxQ5zfXQsU8S4gl6yvrtqx6dxOGyBwIM43CGRyjE,6887
514
514
  opentrons/util/performance_helpers.py,sha256=ew7H8XD20iS6-2TJAzbQeyzStZkkE6PzHt_Adx3wbZQ,5172
515
- opentrons-8.2.0a2.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
516
- opentrons-8.2.0a2.dist-info/METADATA,sha256=bvd0sP2Rm1bKi07Fc_-G1cXPrnnrdfybMiiHbJRcWI4,5019
517
- opentrons-8.2.0a2.dist-info/WHEEL,sha256=_4XEmVmaBFWtekSGrbfOGNjC2I5lUr0lZSRblBllIFA,109
518
- opentrons-8.2.0a2.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
519
- opentrons-8.2.0a2.dist-info/top_level.txt,sha256=wk6whpbMZdBQpcK0Fg0YVfUGrAgVOFON7oQAhOMGMW8,10
520
- opentrons-8.2.0a2.dist-info/RECORD,,
515
+ opentrons-8.2.0a4.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
516
+ opentrons-8.2.0a4.dist-info/METADATA,sha256=SFV-QYAri_wgUI2MTAXq9EWhvkbu-8XHkJvUCJ3Wfks,5019
517
+ opentrons-8.2.0a4.dist-info/WHEEL,sha256=_4XEmVmaBFWtekSGrbfOGNjC2I5lUr0lZSRblBllIFA,109
518
+ opentrons-8.2.0a4.dist-info/entry_points.txt,sha256=fTa6eGCYkvOtv0ov-KVE8LLGetgb35LQLF9x85OWPVw,106
519
+ opentrons-8.2.0a4.dist-info/top_level.txt,sha256=wk6whpbMZdBQpcK0Fg0YVfUGrAgVOFON7oQAhOMGMW8,10
520
+ opentrons-8.2.0a4.dist-info/RECORD,,