From ccfe3999128cfaa9b776b1d4a53a20890c25d045 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Mon, 5 Aug 2024 16:10:25 -0400 Subject: [PATCH 1/7] Leaky docstrings. --- api/src/opentrons/simulate.py | 59 ++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/api/src/opentrons/simulate.py b/api/src/opentrons/simulate.py index 01a1484c6b5..46475af2db8 100644 --- a/api/src/opentrons/simulate.py +++ b/api/src/opentrons/simulate.py @@ -242,28 +242,31 @@ def get_protocol_api( >>> instr.home() :param version: The API version to use. This must be lower than - ``opentrons.protocol_api.MAX_SUPPORTED_VERSION``. - It may be specified either as a string (``'2.0'``) or - as a ``protocols.types.APIVersion`` - (``APIVersion(2, 0)``). + ``opentrons.protocol_api.MAX_SUPPORTED_VERSION``. + It may be specified either as a string (``'2.0'``) or + as a ``protocols.types.APIVersion`` + (``APIVersion(2, 0)``). :param bundled_labware: If specified, a mapping from labware names to - labware definitions for labware to consider in the - protocol. Note that if you specify this, _only_ - labware in this argument will be allowed in the - protocol. This is preparation for a beta feature - and is best not used. + labware definitions for labware to consider in the + protocol. Note that if you specify this, _only_ + labware in this argument will be allowed in the + protocol. This is preparation for a beta feature + and is best not used. :param bundled_data: If specified, a mapping from filenames to contents - for data to be available in the protocol from - :py:obj:`opentrons.protocol_api.ProtocolContext.bundled_data`. + for data to be available in the protocol from + :py:obj:`opentrons.protocol_api.ProtocolContext.bundled_data`. :param extra_labware: A mapping from labware load names to custom labware definitions. - If this is ``None`` (the default), and this function is called on a robot, - it will look for labware in the ``labware`` subdirectory of the Jupyter - data directory. - :param hardware_simulator: If specified, a hardware simulator instance. + If this is ``None`` (the default), and this function is called on a robot, + it will look for labware in the ``labware`` subdirectory of the Jupyter + data directory. + :param hardware_simulator: This is only for internal use by Opentrons. If specified, + it's a hardware simulator instance to reuse instead of creating a fresh one. :param robot_type: The type of robot to simulate: either ``"Flex"`` or ``"OT-2"``. - If you're running this function on a robot, the default is the type of that - robot. Otherwise, the default is ``"OT-2"``, for backwards compatibility. - :param use_virtual_hardware: If true, use the protocol engines virtual hardware, if false use the lower level hardware simulator. + If you're running this function on a robot, the default is the type of that + robot. Otherwise, the default is ``"OT-2"``, for backwards compatibility. + :param use_virtual_hardware: This is only for internal use by Opentrons. + If ``True``, use the Protocol Engine's virtual hardware. If ``False``, use the + lower level hardware simulator. :return: The protocol context. """ if isinstance(version, str): @@ -321,7 +324,7 @@ def get_protocol_api( hardware_api=checked_hardware, bundled_data=bundled_data, extra_labware=extra_labware, - use_virtual_hardware=use_virtual_hardware, + use_pe_virtual_hardware=use_virtual_hardware, ) # Intentional difference from execute.get_protocol_api(): @@ -794,7 +797,7 @@ def _create_live_context_pe( deck_type: str, extra_labware: Dict[str, "LabwareDefinitionDict"], bundled_data: Optional[Dict[str, bytes]], - use_virtual_hardware: bool = True, + use_pe_virtual_hardware: bool = True, ) -> ProtocolContext: """Return a live ProtocolContext that controls the robot through ProtocolEngine.""" assert api_version >= ENGINE_CORE_API_VERSION @@ -804,7 +807,7 @@ def _create_live_context_pe( create_protocol_engine_in_thread( hardware_api=hardware_api_wrapped, config=_get_protocol_engine_config( - robot_type, virtual=use_virtual_hardware + robot_type, use_pe_virtual_hardware=use_pe_virtual_hardware ), error_recovery_policy=error_recovery_policy.never_recover, drop_tips_after_run=False, @@ -910,7 +913,9 @@ async def run(protocol_source: ProtocolSource) -> _SimulateResult: hardware_api_wrapped = hardware_api.wrapped() protocol_engine = await create_protocol_engine( hardware_api=hardware_api_wrapped, - config=_get_protocol_engine_config(robot_type, virtual=True), + config=_get_protocol_engine_config( + robot_type, use_pe_virtual_hardware=True + ), error_recovery_policy=error_recovery_policy.never_recover, load_fixed_trash=should_load_fixed_trash(protocol_source.config), ) @@ -961,15 +966,17 @@ async def run(protocol_source: ProtocolSource) -> _SimulateResult: return asyncio.run(run(protocol_source)) -def _get_protocol_engine_config(robot_type: RobotType, virtual: bool) -> Config: +def _get_protocol_engine_config( + robot_type: RobotType, use_pe_virtual_hardware: bool +) -> Config: """Return a Protocol Engine config to execute protocols on this device.""" return Config( robot_type=robot_type, deck_type=DeckType(deck_type_for_simulation(robot_type)), ignore_pause=True, - use_virtual_pipettes=virtual, - use_virtual_modules=virtual, - use_virtual_gripper=virtual, + use_virtual_pipettes=use_pe_virtual_hardware, + use_virtual_modules=use_pe_virtual_hardware, + use_virtual_gripper=use_pe_virtual_hardware, use_simulated_deck_config=True, ) From 85a30d9a29e41e1cd7209662656138a14aed7c29 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Mon, 5 Aug 2024 16:19:58 -0400 Subject: [PATCH 2/7] Indentation. --- api/src/opentrons/execute.py | 74 +++++++++++++++++------------------ api/src/opentrons/simulate.py | 51 ++++++++++++------------ 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/api/src/opentrons/execute.py b/api/src/opentrons/execute.py index e4109d5d390..e3e2ebe4514 100644 --- a/api/src/opentrons/execute.py +++ b/api/src/opentrons/execute.py @@ -142,23 +142,23 @@ def get_protocol_api( When this function is called, modules and instruments will be recached. :param version: The API version to use. This must be lower than - ``opentrons.protocol_api.MAX_SUPPORTED_VERSION``. - It may be specified either as a string (``'2.0'``) or - as a ``protocols.types.APIVersion`` - (``APIVersion(2, 0)``). + ``opentrons.protocol_api.MAX_SUPPORTED_VERSION``. + It may be specified either as a string (``'2.0'``) or + as a ``protocols.types.APIVersion`` + (``APIVersion(2, 0)``). :param bundled_labware: If specified, a mapping from labware names to - labware definitions for labware to consider in the - protocol. Note that if you specify this, _only_ - labware in this argument will be allowed in the - protocol. This is preparation for a beta feature - and is best not used. + labware definitions for labware to consider in the + protocol. Note that if you specify this, _only_ + labware in this argument will be allowed in the + protocol. This is preparation for a beta feature + and is best not used. :param bundled_data: If specified, a mapping from filenames to contents - for data to be available in the protocol from - :py:obj:`opentrons.protocol_api.ProtocolContext.bundled_data`. + for data to be available in the protocol from + :py:obj:`opentrons.protocol_api.ProtocolContext.bundled_data`. :param extra_labware: A mapping from labware load names to custom labware definitions. - If this is ``None`` (the default), and this function is called on a robot, - it will look for labware in the ``labware`` subdirectory of the Jupyter - data directory. + If this is ``None`` (the default), and this function is called on a robot, + it will look for labware in the ``labware`` subdirectory of the Jupyter + data directory. :return: The protocol context. """ if isinstance(version, str): @@ -313,18 +313,18 @@ def execute( :param protocol_file: The protocol file to execute :param protocol_name: The name of the protocol file. This is required - internally, but it may not be a thing we can get - from the protocol_file argument. + internally, but it may not be a thing we can get + from the protocol_file argument. :param propagate_logs: Whether this function should allow logs from the - Opentrons stack to propagate up to the root handler. - This can be useful if you're integrating this - function in a larger application, but most logs that - occur during protocol simulation are best associated - with the actions in the protocol that cause them. - Default: ``False`` + Opentrons stack to propagate up to the root handler. + This can be useful if you're integrating this + function in a larger application, but most logs that + occur during protocol simulation are best associated + with the actions in the protocol that cause them. + Default: ``False`` :param log_level: The level of logs to emit on the command line: - ``"debug"``, ``"info"``, ``"warning"``, or ``"error"``. - Defaults to ``"warning"``. + ``"debug"``, ``"info"``, ``"warning"``, or ``"error"``. + Defaults to ``"warning"``. :param emit_runlog: A callback for printing the run log. If specified, this will be called whenever a command adds an entry to the run log, which can be used for display and progress @@ -353,17 +353,17 @@ def execute( ``KeyError``. :param custom_labware_paths: A list of directories to search for custom labware. - Loads valid labware from these paths and makes them available - to the protocol context. If this is ``None`` (the default), and - this function is called on a robot, it will look in the ``labware`` - subdirectory of the Jupyter data directory. + Loads valid labware from these paths and makes them available + to the protocol context. If this is ``None`` (the default), and + this function is called on a robot, it will look in the ``labware`` + subdirectory of the Jupyter data directory. :param custom_data_paths: A list of directories or files to load custom - data files from. Ignored if the apiv2 feature - flag if not set. Entries may be either files or - directories. Specified files and the - non-recursive contents of specified directories - are presented by the protocol context in - ``ProtocolContext.bundled_data``. + data files from. Ignored if the apiv2 feature + flag if not set. Entries may be either files or + directories. Specified files and the + non-recursive contents of specified directories + are presented by the protocol context in + ``ProtocolContext.bundled_data``. """ stack_logger = logging.getLogger("opentrons") stack_logger.propagate = propagate_logs @@ -457,10 +457,10 @@ def main() -> int: """Handler for command line invocation to run a protocol. :param argv: The arguments the program was invoked with; this is usually - :py:obj:`sys.argv` but if you want to override that you can. + :py:obj:`sys.argv` but if you want to override that you can. :returns int: A success or failure value suitable for use as a shell - return code passed to :py:obj:`sys.exit` (0 means success, - anything else is a kind of failure). + return code passed to :py:obj:`sys.exit` (0 means success, + anything else is a kind of failure). """ parser = argparse.ArgumentParser( prog="opentrons_execute", description="Run an OT-2 protocol" diff --git a/api/src/opentrons/simulate.py b/api/src/opentrons/simulate.py index 46475af2db8..8b0840baa2a 100644 --- a/api/src/opentrons/simulate.py +++ b/api/src/opentrons/simulate.py @@ -477,36 +477,36 @@ def simulate( :param protocol_file: The protocol file to simulate. :param file_name: The name of the file :param custom_labware_paths: A list of directories to search for custom labware. - Loads valid labware from these paths and makes them available - to the protocol context. If this is ``None`` (the default), and - this function is called on a robot, it will look in the ``labware`` - subdirectory of the Jupyter data directory. + Loads valid labware from these paths and makes them available + to the protocol context. If this is ``None`` (the default), and + this function is called on a robot, it will look in the ``labware`` + subdirectory of the Jupyter data directory. :param custom_data_paths: A list of directories or files to load custom - data files from. Ignored if the apiv2 feature - flag if not set. Entries may be either files or - directories. Specified files and the - non-recursive contents of specified directories - are presented by the protocol context in - ``protocol_api.ProtocolContext.bundled_data``. + data files from. Ignored if the apiv2 feature + flag if not set. Entries may be either files or + directories. Specified files and the + non-recursive contents of specified directories + are presented by the protocol context in + ``protocol_api.ProtocolContext.bundled_data``. :param hardware_simulator_file_path: A path to a JSON file defining a - hardware simulator. + hardware simulator. :param duration_estimator: For internal use only. - Optional duration estimator object. + Optional duration estimator object. :param propagate_logs: Whether this function should allow logs from the - Opentrons stack to propagate up to the root handler. - This can be useful if you're integrating this - function in a larger application, but most logs that - occur during protocol simulation are best associated - with the actions in the protocol that cause them. - Default: ``False`` + Opentrons stack to propagate up to the root handler. + This can be useful if you're integrating this + function in a larger application, but most logs that + occur during protocol simulation are best associated + with the actions in the protocol that cause them. + Default: ``False`` :param log_level: The level of logs to capture in the run log: - ``"debug"``, ``"info"``, ``"warning"``, or ``"error"``. - Defaults to ``"warning"``. + ``"debug"``, ``"info"``, ``"warning"``, or ``"error"``. + Defaults to ``"warning"``. :returns: A tuple of a run log for user output, and possibly the required - data to write to a bundle to bundle this protocol. The bundle is - only emitted if bundling is allowed - and this is an unbundled Protocol API - v2 python protocol. In other cases it is None. + data to write to a bundle to bundle this protocol. The bundle is + only emitted if bundling is allowed + and this is an unbundled Protocol API + v2 python protocol. In other cases it is None. """ stack_logger = logging.getLogger("opentrons") stack_logger.propagate = propagate_logs @@ -639,8 +639,7 @@ def get_arguments(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: Useful if you want to use this module as a component of another CLI program and want to add its arguments. - :param parser: A parser to add arguments to. If not specified, one will be - created. + :param parser: A parser to add arguments to. If not specified, one will be created. :returns argparse.ArgumentParser: The parser with arguments added. """ parser.add_argument( From 4bd40f17ee9dc032e6ef57a64ba671b06316bee1 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Mon, 5 Aug 2024 17:21:14 -0400 Subject: [PATCH 3/7] More docstring tweaks. --- api/src/opentrons/simulate.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/api/src/opentrons/simulate.py b/api/src/opentrons/simulate.py index 8b0840baa2a..e16ff00d183 100644 --- a/api/src/opentrons/simulate.py +++ b/api/src/opentrons/simulate.py @@ -228,10 +228,9 @@ def get_protocol_api( use_virtual_hardware: bool = True, ) -> protocol_api.ProtocolContext: """ - Build and return a ``protocol_api.ProtocolContext`` - connected to Virtual Smoothie. + Build and return a ``protocol_api.ProtocolContext`` that simulates robot control. - This can be used to run protocols from interactive Python sessions + This can be used to simulate protocols from interactive Python sessions such as Jupyter or an interpreter on the command line: .. code-block:: python @@ -438,15 +437,15 @@ def simulate( """ Simulate the protocol itself. - This is a one-stop function to simulate a protocol, whether python or json, - no matter the api version, from external (i.e. not bound up in other + This is a one-stop function to simulate a protocol, whether Python or JSON, + no matter the API version, from external (i.e. not bound up in other internal server infrastructure) sources. - To simulate an opentrons protocol from other places, pass in a file like - object as protocol_file; this function either returns (if the simulation + To simulate an opentrons protocol from other places, pass in a file-like + object as ``protocol_file``; this function either returns (if the simulation has no problems) or raises an exception. - To call from the command line use either the autogenerated entrypoint + To call from the command line, use either the autogenerated entrypoint ``opentrons_simulate`` (``opentrons_simulate.exe``, on windows) or ``python -m opentrons.simulate``. @@ -488,8 +487,9 @@ def simulate( non-recursive contents of specified directories are presented by the protocol context in ``protocol_api.ProtocolContext.bundled_data``. - :param hardware_simulator_file_path: A path to a JSON file defining a - hardware simulator. + :param hardware_simulator_file_path: A path to a JSON file defining the simulated + hardware. This is mainly for internal use by Opentrons, and is not necessary + to simulate protocols. :param duration_estimator: For internal use only. Optional duration estimator object. :param propagate_logs: Whether this function should allow logs from the From db101c373e3bc77c3b2a5397a4bee2085d18ea9c Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Mon, 5 Aug 2024 17:25:24 -0400 Subject: [PATCH 4/7] Delete apparently outdated comment. --- api/src/opentrons/simulate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/opentrons/simulate.py b/api/src/opentrons/simulate.py index e16ff00d183..69b27775882 100644 --- a/api/src/opentrons/simulate.py +++ b/api/src/opentrons/simulate.py @@ -998,7 +998,6 @@ def main() -> int: parser = get_arguments(parser) args = parser.parse_args() - # Try to migrate api v1 containers if needed # TODO(mm, 2022-12-01): Configure the DurationEstimator with the correct deck type. duration_estimator = DurationEstimator() if args.estimate_duration else None # type: ignore[no-untyped-call] From 4ae758b1dd88d462bcf9b433fb877fc8804d43af Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Tue, 6 Aug 2024 15:24:15 -0400 Subject: [PATCH 5/7] Asterisk emphasis. Co-authored-by: Ed Cormany --- api/src/opentrons/execute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/opentrons/execute.py b/api/src/opentrons/execute.py index e3e2ebe4514..83e8af7690e 100644 --- a/api/src/opentrons/execute.py +++ b/api/src/opentrons/execute.py @@ -148,7 +148,7 @@ def get_protocol_api( (``APIVersion(2, 0)``). :param bundled_labware: If specified, a mapping from labware names to labware definitions for labware to consider in the - protocol. Note that if you specify this, _only_ + protocol. Note that if you specify this, *only* labware in this argument will be allowed in the protocol. This is preparation for a beta feature and is best not used. From 0cee6bfa97cb18a06d6ffdd23238186751186d75 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Tue, 6 Aug 2024 15:24:33 -0400 Subject: [PATCH 6/7] Backticks around argument. Co-authored-by: Ed Cormany --- api/src/opentrons/execute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/opentrons/execute.py b/api/src/opentrons/execute.py index 83e8af7690e..2e6a5870f7d 100644 --- a/api/src/opentrons/execute.py +++ b/api/src/opentrons/execute.py @@ -314,7 +314,7 @@ def execute( :param protocol_file: The protocol file to execute :param protocol_name: The name of the protocol file. This is required internally, but it may not be a thing we can get - from the protocol_file argument. + from the ``protocol_file`` argument. :param propagate_logs: Whether this function should allow logs from the Opentrons stack to propagate up to the root handler. This can be useful if you're integrating this From 1fa24866cd424fc96449d518614b40e2490f9609 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Tue, 6 Aug 2024 15:26:55 -0400 Subject: [PATCH 7/7] Asterisks for one and all. --- api/src/opentrons/simulate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/opentrons/simulate.py b/api/src/opentrons/simulate.py index 69b27775882..c2b41fbf649 100644 --- a/api/src/opentrons/simulate.py +++ b/api/src/opentrons/simulate.py @@ -247,7 +247,7 @@ def get_protocol_api( (``APIVersion(2, 0)``). :param bundled_labware: If specified, a mapping from labware names to labware definitions for labware to consider in the - protocol. Note that if you specify this, _only_ + protocol. Note that if you specify this, *only* labware in this argument will be allowed in the protocol. This is preparation for a beta feature and is best not used.