opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0__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.
Files changed (238) hide show
  1. opentrons/cli/analyze.py +71 -7
  2. opentrons/config/__init__.py +9 -0
  3. opentrons/config/advanced_settings.py +22 -0
  4. opentrons/config/defaults_ot3.py +14 -36
  5. opentrons/config/feature_flags.py +4 -0
  6. opentrons/config/types.py +6 -17
  7. opentrons/drivers/absorbance_reader/abstract.py +27 -3
  8. opentrons/drivers/absorbance_reader/async_byonoy.py +208 -154
  9. opentrons/drivers/absorbance_reader/driver.py +24 -15
  10. opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
  11. opentrons/drivers/absorbance_reader/simulator.py +32 -6
  12. opentrons/drivers/types.py +23 -1
  13. opentrons/execute.py +2 -2
  14. opentrons/hardware_control/api.py +18 -10
  15. opentrons/hardware_control/backends/controller.py +3 -2
  16. opentrons/hardware_control/backends/flex_protocol.py +11 -5
  17. opentrons/hardware_control/backends/ot3controller.py +18 -50
  18. opentrons/hardware_control/backends/ot3simulator.py +7 -6
  19. opentrons/hardware_control/backends/ot3utils.py +1 -0
  20. opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
  21. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
  22. opentrons/hardware_control/module_control.py +43 -2
  23. opentrons/hardware_control/modules/__init__.py +7 -1
  24. opentrons/hardware_control/modules/absorbance_reader.py +232 -83
  25. opentrons/hardware_control/modules/errors.py +7 -0
  26. opentrons/hardware_control/modules/heater_shaker.py +8 -3
  27. opentrons/hardware_control/modules/magdeck.py +12 -3
  28. opentrons/hardware_control/modules/mod_abc.py +27 -2
  29. opentrons/hardware_control/modules/tempdeck.py +15 -7
  30. opentrons/hardware_control/modules/thermocycler.py +69 -3
  31. opentrons/hardware_control/modules/types.py +11 -5
  32. opentrons/hardware_control/modules/update.py +11 -5
  33. opentrons/hardware_control/modules/utils.py +3 -1
  34. opentrons/hardware_control/ot3_calibration.py +6 -6
  35. opentrons/hardware_control/ot3api.py +131 -94
  36. opentrons/hardware_control/poller.py +15 -11
  37. opentrons/hardware_control/protocols/__init__.py +1 -7
  38. opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
  39. opentrons/hardware_control/protocols/liquid_handler.py +5 -0
  40. opentrons/hardware_control/protocols/position_estimator.py +3 -1
  41. opentrons/hardware_control/types.py +2 -0
  42. opentrons/legacy_commands/helpers.py +8 -2
  43. opentrons/motion_planning/__init__.py +2 -0
  44. opentrons/motion_planning/waypoints.py +32 -0
  45. opentrons/protocol_api/__init__.py +2 -1
  46. opentrons/protocol_api/_liquid.py +87 -1
  47. opentrons/protocol_api/_parameter_context.py +10 -1
  48. opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
  49. opentrons/protocol_api/core/engine/instrument.py +29 -25
  50. opentrons/protocol_api/core/engine/labware.py +20 -4
  51. opentrons/protocol_api/core/engine/module_core.py +166 -17
  52. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +362 -0
  53. opentrons/protocol_api/core/engine/protocol.py +30 -2
  54. opentrons/protocol_api/core/instrument.py +2 -0
  55. opentrons/protocol_api/core/labware.py +4 -0
  56. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
  57. opentrons/protocol_api/core/legacy/legacy_labware_core.py +5 -0
  58. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +6 -2
  59. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
  60. opentrons/protocol_api/core/module.py +22 -4
  61. opentrons/protocol_api/core/protocol.py +6 -2
  62. opentrons/protocol_api/instrument_context.py +52 -20
  63. opentrons/protocol_api/labware.py +13 -1
  64. opentrons/protocol_api/module_contexts.py +115 -17
  65. opentrons/protocol_api/protocol_context.py +49 -5
  66. opentrons/protocol_api/validation.py +5 -3
  67. opentrons/protocol_engine/__init__.py +10 -9
  68. opentrons/protocol_engine/actions/__init__.py +3 -0
  69. opentrons/protocol_engine/actions/actions.py +30 -25
  70. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  71. opentrons/protocol_engine/clients/sync_client.py +1 -1
  72. opentrons/protocol_engine/clients/transports.py +1 -1
  73. opentrons/protocol_engine/commands/__init__.py +0 -4
  74. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
  75. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +148 -0
  76. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +65 -9
  77. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +148 -0
  78. opentrons/protocol_engine/commands/absorbance_reader/read.py +200 -0
  79. opentrons/protocol_engine/commands/aspirate.py +29 -16
  80. opentrons/protocol_engine/commands/aspirate_in_place.py +33 -16
  81. opentrons/protocol_engine/commands/blow_out.py +63 -14
  82. opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
  83. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
  84. opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
  85. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
  86. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
  87. opentrons/protocol_engine/commands/command.py +31 -18
  88. opentrons/protocol_engine/commands/command_unions.py +37 -24
  89. opentrons/protocol_engine/commands/comment.py +5 -3
  90. opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
  91. opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
  92. opentrons/protocol_engine/commands/custom.py +5 -3
  93. opentrons/protocol_engine/commands/dispense.py +42 -20
  94. opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
  95. opentrons/protocol_engine/commands/drop_tip.py +70 -16
  96. opentrons/protocol_engine/commands/drop_tip_in_place.py +59 -13
  97. opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
  98. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
  99. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
  100. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
  101. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
  102. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
  103. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
  104. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
  105. opentrons/protocol_engine/commands/home.py +11 -5
  106. opentrons/protocol_engine/commands/liquid_probe.py +146 -88
  107. opentrons/protocol_engine/commands/load_labware.py +28 -5
  108. opentrons/protocol_engine/commands/load_liquid.py +18 -7
  109. opentrons/protocol_engine/commands/load_module.py +4 -6
  110. opentrons/protocol_engine/commands/load_pipette.py +18 -17
  111. opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
  112. opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
  113. opentrons/protocol_engine/commands/move_labware.py +155 -23
  114. opentrons/protocol_engine/commands/move_relative.py +15 -3
  115. opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
  116. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
  117. opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
  118. opentrons/protocol_engine/commands/move_to_well.py +37 -10
  119. opentrons/protocol_engine/commands/pick_up_tip.py +51 -30
  120. opentrons/protocol_engine/commands/pipetting_common.py +47 -16
  121. opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
  122. opentrons/protocol_engine/commands/reload_labware.py +13 -4
  123. opentrons/protocol_engine/commands/retract_axis.py +6 -3
  124. opentrons/protocol_engine/commands/save_position.py +2 -3
  125. opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
  126. opentrons/protocol_engine/commands/set_status_bar.py +5 -3
  127. opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
  128. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
  129. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
  130. opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
  131. opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
  132. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
  133. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
  134. opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
  135. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
  136. opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
  137. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
  138. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
  139. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
  140. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
  141. opentrons/protocol_engine/commands/touch_tip.py +19 -7
  142. opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
  143. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
  144. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
  145. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
  146. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  147. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  148. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +10 -4
  149. opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
  150. opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
  151. opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
  152. opentrons/protocol_engine/create_protocol_engine.py +60 -10
  153. opentrons/protocol_engine/engine_support.py +2 -1
  154. opentrons/protocol_engine/error_recovery_policy.py +14 -3
  155. opentrons/protocol_engine/errors/__init__.py +20 -0
  156. opentrons/protocol_engine/errors/error_occurrence.py +8 -3
  157. opentrons/protocol_engine/errors/exceptions.py +127 -2
  158. opentrons/protocol_engine/execution/__init__.py +2 -0
  159. opentrons/protocol_engine/execution/command_executor.py +22 -13
  160. opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
  161. opentrons/protocol_engine/execution/door_watcher.py +1 -1
  162. opentrons/protocol_engine/execution/equipment.py +2 -1
  163. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  164. opentrons/protocol_engine/execution/gantry_mover.py +4 -2
  165. opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
  166. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
  167. opentrons/protocol_engine/execution/labware_movement.py +73 -22
  168. opentrons/protocol_engine/execution/movement.py +17 -7
  169. opentrons/protocol_engine/execution/pipetting.py +7 -4
  170. opentrons/protocol_engine/execution/queue_worker.py +6 -2
  171. opentrons/protocol_engine/execution/run_control.py +1 -1
  172. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
  173. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
  174. opentrons/protocol_engine/execution/tip_handler.py +77 -43
  175. opentrons/protocol_engine/notes/__init__.py +14 -2
  176. opentrons/protocol_engine/notes/notes.py +18 -1
  177. opentrons/protocol_engine/plugins.py +1 -1
  178. opentrons/protocol_engine/protocol_engine.py +47 -31
  179. opentrons/protocol_engine/resources/__init__.py +2 -0
  180. opentrons/protocol_engine/resources/deck_data_provider.py +19 -5
  181. opentrons/protocol_engine/resources/file_provider.py +161 -0
  182. opentrons/protocol_engine/resources/fixture_validation.py +11 -1
  183. opentrons/protocol_engine/resources/labware_validation.py +10 -0
  184. opentrons/protocol_engine/state/__init__.py +0 -70
  185. opentrons/protocol_engine/state/addressable_areas.py +1 -1
  186. opentrons/protocol_engine/state/command_history.py +21 -2
  187. opentrons/protocol_engine/state/commands.py +110 -31
  188. opentrons/protocol_engine/state/files.py +59 -0
  189. opentrons/protocol_engine/state/frustum_helpers.py +440 -0
  190. opentrons/protocol_engine/state/geometry.py +445 -59
  191. opentrons/protocol_engine/state/labware.py +264 -84
  192. opentrons/protocol_engine/state/liquids.py +1 -1
  193. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +21 -3
  194. opentrons/protocol_engine/state/modules.py +145 -90
  195. opentrons/protocol_engine/state/motion.py +33 -14
  196. opentrons/protocol_engine/state/pipettes.py +157 -317
  197. opentrons/protocol_engine/state/state.py +30 -1
  198. opentrons/protocol_engine/state/state_summary.py +3 -0
  199. opentrons/protocol_engine/state/tips.py +69 -114
  200. opentrons/protocol_engine/state/update_types.py +424 -0
  201. opentrons/protocol_engine/state/wells.py +236 -0
  202. opentrons/protocol_engine/types.py +90 -0
  203. opentrons/protocol_reader/file_format_validator.py +83 -15
  204. opentrons/protocol_runner/json_translator.py +21 -5
  205. opentrons/protocol_runner/legacy_command_mapper.py +27 -6
  206. opentrons/protocol_runner/legacy_context_plugin.py +27 -71
  207. opentrons/protocol_runner/protocol_runner.py +6 -3
  208. opentrons/protocol_runner/run_orchestrator.py +41 -6
  209. opentrons/protocols/advanced_control/mix.py +3 -5
  210. opentrons/protocols/advanced_control/transfers.py +125 -56
  211. opentrons/protocols/api_support/constants.py +1 -1
  212. opentrons/protocols/api_support/definitions.py +1 -1
  213. opentrons/protocols/api_support/labware_like.py +4 -4
  214. opentrons/protocols/api_support/tip_tracker.py +2 -2
  215. opentrons/protocols/api_support/types.py +15 -2
  216. opentrons/protocols/api_support/util.py +30 -42
  217. opentrons/protocols/duration/errors.py +1 -1
  218. opentrons/protocols/duration/estimator.py +50 -29
  219. opentrons/protocols/execution/dev_types.py +2 -2
  220. opentrons/protocols/execution/execute_json_v4.py +15 -10
  221. opentrons/protocols/execution/execute_python.py +8 -3
  222. opentrons/protocols/geometry/planning.py +12 -12
  223. opentrons/protocols/labware.py +17 -33
  224. opentrons/protocols/parameters/csv_parameter_interface.py +3 -1
  225. opentrons/simulate.py +3 -3
  226. opentrons/types.py +30 -3
  227. opentrons/util/logging_config.py +34 -0
  228. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/METADATA +5 -4
  229. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/RECORD +235 -223
  230. opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
  231. opentrons/protocol_engine/commands/configuring_common.py +0 -26
  232. opentrons/protocol_runner/thread_async_queue.py +0 -174
  233. /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
  234. /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
  235. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/LICENSE +0 -0
  236. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/WHEEL +0 -0
  237. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/entry_points.txt +0 -0
  238. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/top_level.txt +0 -0
@@ -1,94 +0,0 @@
1
- """Command models to measure absorbance."""
2
- from __future__ import annotations
3
- from typing import List, Optional, TYPE_CHECKING
4
- from typing_extensions import Literal, Type
5
-
6
- from pydantic import BaseModel, Field
7
-
8
- from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
9
- from ...errors.error_occurrence import ErrorOccurrence
10
-
11
- if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
13
- from opentrons.protocol_engine.execution import EquipmentHandler
14
-
15
-
16
- MeasureAbsorbanceCommandType = Literal["absorbanceReader/measure"]
17
-
18
-
19
- class MeasureAbsorbanceParams(BaseModel):
20
- """Input parameters for a single absorbance reading."""
21
-
22
- moduleId: str = Field(..., description="Unique ID of the Absorbance Reader.")
23
- sampleWavelength: int = Field(..., description="Sample wavelength in nm.")
24
-
25
-
26
- class MeasureAbsorbanceResult(BaseModel):
27
- """Result data from running an aborbance reading."""
28
-
29
- # TODO: Transform this into a more complex model, such as a map with well names.
30
- data: Optional[List[float]] = Field(
31
- ..., min_items=96, max_items=96, description="Absorbance data points."
32
- )
33
-
34
-
35
- class MeasureAbsorbanceImpl(
36
- AbstractCommandImpl[
37
- MeasureAbsorbanceParams, SuccessData[MeasureAbsorbanceResult, None]
38
- ]
39
- ):
40
- """Execution implementation of an Absorbance Reader measurement."""
41
-
42
- def __init__(
43
- self,
44
- state_view: StateView,
45
- equipment: EquipmentHandler,
46
- **unused_dependencies: object,
47
- ) -> None:
48
- self._state_view = state_view
49
- self._equipment = equipment
50
-
51
- async def execute(
52
- self, params: MeasureAbsorbanceParams
53
- ) -> SuccessData[MeasureAbsorbanceResult, None]:
54
- """Initiate a single absorbance measurement."""
55
- abs_reader_substate = self._state_view.modules.get_absorbance_reader_substate(
56
- module_id=params.moduleId
57
- )
58
- # Allow propagation of ModuleNotAttachedError.
59
- abs_reader = self._equipment.get_module_hardware_api(
60
- abs_reader_substate.module_id
61
- )
62
-
63
- if abs_reader is not None:
64
- result = await abs_reader.start_measure(wavelength=params.sampleWavelength)
65
- return SuccessData(
66
- public=MeasureAbsorbanceResult(data=result),
67
- private=None,
68
- )
69
-
70
- return SuccessData(
71
- public=MeasureAbsorbanceResult(data=None),
72
- private=None,
73
- )
74
-
75
-
76
- class MeasureAbsorbance(
77
- BaseCommand[MeasureAbsorbanceParams, MeasureAbsorbanceResult, ErrorOccurrence]
78
- ):
79
- """A command to execute an Absorbance Reader measurement."""
80
-
81
- commandType: MeasureAbsorbanceCommandType = "absorbanceReader/measure"
82
- params: MeasureAbsorbanceParams
83
- result: Optional[MeasureAbsorbanceResult]
84
-
85
- _ImplementationCls: Type[MeasureAbsorbanceImpl] = MeasureAbsorbanceImpl
86
-
87
-
88
- class MeasureAbsorbanceCreate(BaseCommandCreate[MeasureAbsorbanceParams]):
89
- """A request to execute an Absorbance Reader measurement."""
90
-
91
- commandType: MeasureAbsorbanceCommandType = "absorbanceReader/measure"
92
- params: MeasureAbsorbanceParams
93
-
94
- _CommandCls: Type[MeasureAbsorbance] = MeasureAbsorbance
@@ -1,26 +0,0 @@
1
- """Common configuration command base models."""
2
-
3
- from dataclasses import dataclass
4
- from opentrons.hardware_control.nozzle_manager import (
5
- NozzleMap,
6
- )
7
- from ..resources import pipette_data_provider
8
-
9
-
10
- @dataclass
11
- class PipetteConfigUpdateResultMixin:
12
- """A mixin-suitable model for adding pipette config to private results."""
13
-
14
- pipette_id: str
15
- serial_number: str
16
- config: pipette_data_provider.LoadedStaticPipetteData
17
-
18
-
19
- @dataclass
20
- class PipetteNozzleLayoutResultMixin:
21
- """A nozzle layout result for updating the pipette state."""
22
-
23
- pipette_id: str
24
-
25
- nozzle_map: NozzleMap
26
- """A dataclass object holding information about the current nozzle configuration."""
@@ -1,174 +0,0 @@
1
- """Safely pass values between threads and async tasks."""
2
-
3
-
4
- from __future__ import annotations
5
-
6
- from collections import deque
7
- from threading import Condition
8
- from typing import AsyncIterable, Deque, Generic, Iterable, TypeVar
9
-
10
- from anyio.to_thread import run_sync
11
-
12
-
13
- _T = TypeVar("_T")
14
-
15
-
16
- class ThreadAsyncQueue(Generic[_T]):
17
- """A queue to safely pass values of type `_T` between threads and async tasks.
18
-
19
- All methods are safe to call concurrently from any thread or task.
20
-
21
- Compared to queue.Queue:
22
-
23
- * This class lets you close the queue to signal that no more values will be added,
24
- which makes common producer/consumer patterns easier.
25
- (This is like Golang channels and AnyIO memory object streams.)
26
- * This class has built-in support for async consumers.
27
-
28
- Compared to asyncio.Queue and AnyIO memory object streams:
29
-
30
- * You can use this class to communicate between async tasks and threads
31
- without the threads having to wait for the event loop to be free
32
- every time they access the queue.
33
- """
34
-
35
- def __init__(self) -> None:
36
- """Initialize the queue."""
37
- self._is_closed = False
38
- self._deque: Deque[_T] = deque()
39
- self._condition = Condition()
40
-
41
- def put(self, value: _T) -> None:
42
- """Add a value to the back of the queue.
43
-
44
- Returns immediately, without blocking. The queue can grow without bound.
45
-
46
- Raises:
47
- QueueClosed: If the queue is already closed.
48
- """
49
- with self._condition:
50
- if self._is_closed:
51
- raise QueueClosed("Can't add more values when queue is already closed.")
52
- else:
53
- self._deque.append(value)
54
- self._condition.notify()
55
-
56
- def get(self) -> _T:
57
- """Remove and return the value at the front of the queue.
58
-
59
- If the queue is empty, this blocks until a new value is available.
60
- If you're calling from an async task, use one of the async methods instead
61
- to avoid blocking the event loop.
62
-
63
- Raises:
64
- QueueClosed: If all values have been consumed
65
- and the queue has been closed with `done_putting()`.
66
- """
67
- with self._condition:
68
- while True:
69
- if len(self._deque) > 0:
70
- return self._deque.popleft()
71
- elif self._is_closed:
72
- raise QueueClosed("Queue closed; no more items to get.")
73
- else:
74
- # We don't have anything to return.
75
- # Wait for something to change, then check again.
76
- self._condition.wait()
77
-
78
- def get_until_closed(self) -> Iterable[_T]:
79
- """Remove and return values from the front of the queue until it's closed.
80
-
81
- Example:
82
- for value in queue.get_until_closed():
83
- print(value)
84
- """
85
- while True:
86
- try:
87
- yield self.get()
88
- except QueueClosed:
89
- break
90
-
91
- async def get_async(self) -> _T:
92
- """Like `get()`, except yield to the event loop while waiting.
93
-
94
- Warning:
95
- A waiting `get_async()` won't be interrupted by an async cancellation.
96
- The proper way to interrupt a waiting `get_async()`
97
- is to close the queue, just like you have to do with `get()`.
98
- """
99
- return await run_sync(
100
- self.get,
101
- # We keep `cancellable` False so we don't leak this helper thread.
102
- # If we made it True, an async cancellation here would detach us
103
- # from the helper thread and allow the thread to "run to completion"--
104
- # but if no more values are ever enqueued, and the queue is never closed,
105
- # completion would never happen and it would hang around forever.
106
- cancellable=False,
107
- )
108
-
109
- async def get_async_until_closed(self) -> AsyncIterable[_T]:
110
- """Like `get_until_closed()`, except yield to the event loop while waiting.
111
-
112
- Example:
113
- async for value in queue.get_async_until_closed():
114
- print(value)
115
-
116
- Warning:
117
- While the ``async for`` is waiting for a new value,
118
- it won't be interrupted by an async cancellation.
119
- The proper way to interrupt a waiting `get_async_until_closed()`
120
- is to close the queue, just like you have to do with `get()`.
121
- """
122
- while True:
123
- try:
124
- yield await self.get_async()
125
- except QueueClosed:
126
- break
127
-
128
- def done_putting(self) -> None:
129
- """Close the queue, i.e. signal that no more values will be `put()`.
130
-
131
- You normally *must* close the queue eventually
132
- to inform consumers that they can stop waiting for new values.
133
- Forgetting to do this can leave them waiting forever,
134
- leaking tasks or threads or causing deadlocks.
135
-
136
- Consider using a ``with`` block instead. See `__enter__()`.
137
-
138
- Raises:
139
- QueueClosed: If the queue is already closed.
140
- """
141
- with self._condition:
142
- if self._is_closed:
143
- raise QueueClosed("Can't close when queue is already closed.")
144
- else:
145
- self._is_closed = True
146
- self._condition.notify_all()
147
-
148
- def __enter__(self) -> ThreadAsyncQueue[_T]:
149
- """Use the queue as a context manager, closing the queue upon exit.
150
-
151
- Example:
152
- This:
153
-
154
- with queue:
155
- do_stuff()
156
-
157
- Is equivalent to:
158
-
159
- try:
160
- do_stuff()
161
- finally:
162
- queue.done_putting()
163
- """
164
- return self
165
-
166
- def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None:
167
- """See `__enter__()`."""
168
- self.done_putting()
169
-
170
-
171
- class QueueClosed(Exception):
172
- """See `ThreadAsyncQueue.done_putting()`."""
173
-
174
- pass