From 4247d54d12ba76764dd6afd4b0143a1f09777ed5 Mon Sep 17 00:00:00 2001 From: Derek Maggio Date: Tue, 25 Jun 2024 13:11:20 -0700 Subject: [PATCH] feat: configure performance-metrics to work on robot (#15316) # Overview Adds packaging scripts and configuration to enable pushing and running performance metrics on a robot. Currently running analysis and getting a cached analysis are the only things that are tracked on the robot Closes https://opentrons.atlassian.net/browse/EXEC-497 # Test Plan - Follow the steps in [README](https://github.com/Opentrons/opentrons/blob/b7274f123ee5cbdd93430a52668d07b0c90b6ae8/performance-metrics/README.md) to setup the env - Run robot analysis for 2-3 different protocols by going to the setup screen for the protocols - Repeat running analysis for each protocol - SSH into the robot and go to /data/performance_metrics_data/ - There should be 2 files - robot_context_data - robot_context_data_headers - Check their content - robot_context_data should have lines that look like this, ``` ANALYZING_PROTOCOL,1718739269730290312,14028043893 GETTING_CACHED_ANALYSIS,1718739323578647179,47381526 ... ``` - robot_context_data_headers should have a single line ``` state_name,function_start_time,duration ``` - After you are finished run `make unset-performance-metrics-ff` - Run a protocol and make sure performance metrics are no longer being recorded. Also, make sure you can still run the analysis and get a cached analysis - [x] Verify analysis and cached analysis on the OT-2 dev server - [x] Verify analysis and cached analysis on the Flex dev server - [x] Verify analysis and cached analysis on OT-2 - [x] Verify analysis and cached analysis on Flex Dev Kit - [x] Verify analysis and cached analysis on Flex @skowalski08 # Changelog ## `performance_helpers.py` - Add TrackingFunctions class which contains functions intended to be used as decorators - Generalize wrapper creation function - Make all other entities in the file private ## `performance-metrics/Makefile` - Add push targets for OT-2 and Flex - Add helper target `update-robot-version` to hack the robot into thinking it is on the same version as the app - Add `set-performance-metrics-ff` and `unset-performance-metrics-ff` - Add a get-logs target ## `performance-metrics/setup.py` Remove shared-data as a dep for performance-metrics as it does not use it ## `robot-server/Pipfile` Remove performance-metrics as a dependency as robot_server is not using it directly ## `robot-server/robot_server/protocols/protocol_analyzer.py` Wrap `analyze` and label it as `ANALYZING_PROTOCOL` ## `robot-server/robot_server/protocols/router.py` Wrap logic that gets cached_analysis and label it as `GETTING_CACHED_PROTOCOL_ANALYSIS` # Review requests - Take a look at my test plan, is there anything else that should be added to reduce the risk? - Am I installing the performance-metrics package correctly on the flex by just unpacking it in `/opt/opentrons-robot-server`? - # Risk assessment Medium? `performance-metrics` is now wrapping production code. But the package is not being built and installed on robots, it has to be pushed by a dev. Furthermore, nothing will be run without setting the feature flag --- .gitignore | 1 + api/src/opentrons/util/performance_helpers.py | 62 ++- .../util/test_performance_helpers.py | 6 +- performance-metrics/.gitignore | 1 - performance-metrics/Makefile | 87 +++- performance-metrics/README.md | 70 ++- performance-metrics/setup.cfg | 11 + performance-metrics/setup.py | 4 +- .../src/performance_metrics/data_shapes.py | 2 +- .../src/performance_metrics/types.py | 1 + robot-server/Pipfile | 2 +- robot-server/Pipfile.lock | 429 +++++++++++------- .../protocols/protocol_analyzer.py | 2 + robot-server/robot_server/protocols/router.py | 83 ++-- scripts/python_build_utils.py | 1 + 15 files changed, 534 insertions(+), 228 deletions(-) delete mode 100644 performance-metrics/.gitignore create mode 100755 performance-metrics/setup.cfg diff --git a/.gitignore b/.gitignore index 7d32575773a..319ccc32e67 100755 --- a/.gitignore +++ b/.gitignore @@ -137,6 +137,7 @@ update-server/LICENSE shared-data/python/LICENSE shared-data/LICENSE robot-server/LICENSE +performance-metrics/LICENSE # typescript incremental files *.tsbuildinfo diff --git a/api/src/opentrons/util/performance_helpers.py b/api/src/opentrons/util/performance_helpers.py index 87997484776..021fd8166ed 100644 --- a/api/src/opentrons/util/performance_helpers.py +++ b/api/src/opentrons/util/performance_helpers.py @@ -27,7 +27,7 @@ ) -class StubbedTracker: +class _StubbedTracker: """A stubbed tracker that does nothing.""" def __init__(self, storage_location: Path, should_track: bool) -> None: @@ -60,10 +60,10 @@ def store(self) -> None: pass -# Ensure that StubbedTracker implements SupportsTracking +# Ensure that _StubbedTracker implements SupportsTracking # but do not create a runtime dependency on performance_metrics if typing.TYPE_CHECKING: - _: typing.Type["SupportsTracking"] = StubbedTracker + _: typing.Type["SupportsTracking"] = _StubbedTracker def _handle_package_import() -> typing.Type["SupportsTracking"]: @@ -76,13 +76,12 @@ def _handle_package_import() -> typing.Type["SupportsTracking"]: return RobotContextTracker except ImportError: - return StubbedTracker + return _StubbedTracker -package_to_use = _handle_package_import() +_package_to_use = _handle_package_import() _robot_context_tracker: typing.Optional["SupportsTracking"] = None - # TODO: derek maggio (06-03-2024): investigate if _should_track should be # reevaluated each time _get_robot_context_tracker is called. I think this # might get stuck in a state where after the first call, _should_track is @@ -94,19 +93,30 @@ def _get_robot_context_tracker() -> "SupportsTracking": """Singleton for the robot context tracker.""" global _robot_context_tracker if _robot_context_tracker is None: - _robot_context_tracker = package_to_use( + _robot_context_tracker = _package_to_use( get_performance_metrics_data_dir(), _should_track ) return _robot_context_tracker -def track_analysis( - func: _UnderlyingFunction[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn] -) -> _UnderlyingFunction[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]: - """Track the analysis of a protocol and store each run.""" - # TODO: derek maggio (06-03-2024): generalize creating wrapper functions for tracking different states +def _track_a_function( + state_name: "RobotContextState", + func: _UnderlyingFunction[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn], +) -> typing.Callable[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]: + """Track a function. + + This function is a decorator that will track the given state for the + decorated function. + + Args: + state_name: The state to annotate the tracked function with. + func: The function to decorate. + + Returns: + The decorated function. + """ tracker: SupportsTracking = _get_robot_context_tracker() - wrapped = tracker.track(state="ANALYZING_PROTOCOL")(func) + wrapped = tracker.track(state=state_name)(func) @functools.wraps(func) def wrapper( @@ -116,6 +126,32 @@ def wrapper( try: return wrapped(*args, **kwargs) finally: + # TODO: derek maggio (06-18-2024): After investigation, it appears on startup + # that the first call to tracker.store() will not actually store the data. + # The second call stores both rows of data. + tracker.store() return wrapper + + +class TrackingFunctions: + """A class for tracking functions.""" + + @staticmethod + def track_analysis( + func: _UnderlyingFunction[ + _UnderlyingFunctionParameters, _UnderlyingFunctionReturn + ] + ) -> typing.Callable[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]: + """Track a function that runs an analysis.""" + return _track_a_function("ANALYZING_PROTOCOL", func) + + @staticmethod + def track_getting_cached_protocol_analysis( + func: _UnderlyingFunction[ + _UnderlyingFunctionParameters, _UnderlyingFunctionReturn + ] + ) -> typing.Callable[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]: + """Track a function that gets cached analysis.""" + return _track_a_function("GETTING_CACHED_ANALYSIS", func) diff --git a/api/tests/opentrons/util/test_performance_helpers.py b/api/tests/opentrons/util/test_performance_helpers.py index a8f22e48486..88181091c34 100644 --- a/api/tests/opentrons/util/test_performance_helpers.py +++ b/api/tests/opentrons/util/test_performance_helpers.py @@ -2,14 +2,14 @@ from pathlib import Path from opentrons.util.performance_helpers import ( - StubbedTracker, + _StubbedTracker, _get_robot_context_tracker, ) def test_return_function_unchanged() -> None: - """Test that the function is returned unchanged when using StubbedTracker.""" - tracker = StubbedTracker(Path("/path/to/storage"), True) + """Test that the function is returned unchanged when using _StubbedTracker.""" + tracker = _StubbedTracker(Path("/path/to/storage"), True) def func_to_track() -> None: pass diff --git a/performance-metrics/.gitignore b/performance-metrics/.gitignore deleted file mode 100644 index 8fb3d9a4ea5..00000000000 --- a/performance-metrics/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.ruff_cache/ \ No newline at end of file diff --git a/performance-metrics/Makefile b/performance-metrics/Makefile index fd4dd421ad2..993fdc37196 100644 --- a/performance-metrics/Makefile +++ b/performance-metrics/Makefile @@ -1,4 +1,38 @@ include ../scripts/python.mk +include ../scripts/push.mk + +ot_project := $(OPENTRONS_PROJECT) +project_rs_default = $(if $(ot_project),$(ot_project),robot-stack) +project_ir_default = $(if $(ot_project),$(ot_project),ot3) + +SHX := npx shx + +# Host key location for robot +ssh_key ?= $(default_ssh_key) +# Other SSH args for robot +ssh_opts ?= $(default_ssh_opts) +# Helper to safely bundle ssh options +ssh_helper = $(if $(ssh_key),-i $(ssh_key)) $(ssh_opts) + +# Defined separately than the clean target so the wheel file doesn’t have to +# depend on a PHONY target + +# Find the version of the wheel from git using a helper script. We +# use python here so we can use the same version normalization that will be +# used to create the wheel. +wheel_file = dist/$(call python_get_wheelname,performance-metrics,$(project_rs_default),performance_metrics,$(BUILD_NUMBER)) + +# Find the version of the sdist file from git using a helper script. +sdist_file = dist/$(call python_get_sdistname,performance-metrics,$(project_rs_default),performance_metrics) + +# Find the branch, sha, version that will be used to update the VERSION.json file +version_file = $(call python_get_git_version,performance-metrics,$(project_rs_default),performance_metrics) + + +clean_cmd = $(SHX) rm -rf 'build' '**/*.egg-info' '**/__pycache__' **/*.pyc '.mypy_cache' '.pytest_cache' +clean_wheel_cmd = $(clean_cmd) dist/*.whl +clean_sdist_cmd = $(clean_cmd) dist/*.tar.gz +clean_all_cmd = $(clean_cmd) dist .PHONY: lint lint: @@ -20,12 +54,61 @@ teardown: .PHONY: clean clean: - rm -rf build dist *.egg-info .mypy_cache .pytest_cache src/performance_metrics.egg-info + $(clean_all_cmd) .PHONY: wheel wheel: + $(clean_wheel_cmd) $(python) setup.py $(wheel_opts) bdist_wheel - rm -rf build + $(SHX) rm -rf build + $(SHX) ls dist + +.PHONY: sdist +sdist: export OPENTRONS_PROJECT=$(project_rs_default) +sdist: + $(clean_sdist_cmd) + $(python) setup.py sdist + $(SHX) rm -rf build + $(SHX) ls dist + +.PHONY: push-no-restart +push-no-restart: wheel + $(call push-python-package,$(host),$(ssh_key),$(ssh_opts),$(wheel_file)) + +.PHONY: push +push: push-no-restart + $(call restart-service,$(host),$(ssh_key),$(ssh_opts),"opentrons-robot-server") + +.PHONY: push-no-restart-ot3 +push-no-restart-ot3: sdist + $(call push-python-sdist,$(host),$(ssh_key),$(ssh_opts),$(sdist_file),/opt/opentrons-robot-server,performance_metrics,src,,$(version_file)) + +.PHONY: push-ot3 +push-ot3: push-no-restart-ot3 + $(call restart-service,$(host),$(ssh_key),$(ssh_opts),"opentrons-robot-server") + +.PHONY: override-robot-version +override-robot-version: + $(eval update_dict := '{"opentrons_api_version": "$(version)", "update_server_version": "$(version)", "robot_server_version": "$(version)", "server_utils_version": "$(version)", "opentrons_hardware_version": "$(version)"}') + $(call sync-version-file,$(host),$(ssh_key),$(ssh_opts),'$(update_dict)') + $(call restart-service,$(host),$(ssh_key),$(ssh_opts),"opentrons-robot-server") + + +.PHONY: set-performance-metrics-ff +set-performance-metrics-ff: + @curl \ + -H "opentrons-version: *" \ + -X POST $(host):31950/settings \ + -H "content-type: application/json" \ + -d '{"id": "enablePerformanceMetrics", "value": true}' + +.PHONY: unset-performance-metrics-ff +unset-performance-metrics-ff: + @curl \ + -H "opentrons-version: *" \ + -X POST $(host):31950/settings \ + -H "content-type: application/json" \ + -d '{"id": "enablePerformanceMetrics", "value": false}' .PHONY: test test: diff --git a/performance-metrics/README.md b/performance-metrics/README.md index 7fb20445e36..008ff0f6db2 100644 --- a/performance-metrics/README.md +++ b/performance-metrics/README.md @@ -1,3 +1,71 @@ # Performance Metrics -Project to gather various performance metrics for the Opentrons Flex. +Library to gather various performance metrics for the Opentrons Flex. + +Currently being imported inside of `opentrons.util.performance_helpers` which defines +helper function used inside other projects + +## Setup + +It is assumed that you already have the other projects in the monorepo setup correctly. + +```bash +make -C performance-metrics setup +``` + +### Testing against OT-2 Dev Server + +```bash +make -C robot-server dev-ot2 +``` + +### Testing against real OT-2 + +To push development packages to OT-2 run the following commands from the root directory of this repo: + +```bash +make -C performance-metrics push-no-restart host= +make -C api push-no-restart host= +make -C robot-server push host= +``` + +### Testing against Flex Dev Server + +```bash +make -C robot-server dev-flex +``` + +### Testing against real Flex + +```bash +make -C performance-metrics push-no-restart-ot3 host= +make -C api push-no-restart-ot3 host= +make -C robot-server push-ot3 host= +``` + +### Extra step when running against real robots + +Once this is done you might need to hack getting your robot and app to think they are on the same version. +Go to your app -> Settings -> General and find your app version + +Then run + +```bash +make -C performance-metrics override-robot-version version= host= +``` + +this will make the app think that the robot is on the same version + +### Enabling performance-metrics feature flag + +Performance metrics usage is hidden behind a feature flag. To enable it run the following command: + +```bash +make set-performance-metrics-ff host= +``` + +To disable it run: + +```bash +make unset-performance-metrics-ff host= +``` diff --git a/performance-metrics/setup.cfg b/performance-metrics/setup.cfg new file mode 100755 index 00000000000..5f426ffc147 --- /dev/null +++ b/performance-metrics/setup.cfg @@ -0,0 +1,11 @@ +[bdist_wheel] +universal = 1 + +[metadata] +license_files = ../LICENSE + +[pep8] +ignore = E221,E222 + +[aliases] +test=pytest diff --git a/performance-metrics/setup.py b/performance-metrics/setup.py index eced9a55ab9..a0261bd7fdc 100755 --- a/performance-metrics/setup.py +++ b/performance-metrics/setup.py @@ -53,9 +53,7 @@ def get_version(): KEYWORDS = ["robots", "protocols", "synbio", "pcr", "automation", "lab"] DESCRIPTION = "Library for working with performance metrics on the Opentrons robots" PACKAGES = find_packages(where="src", exclude=["tests.*", "tests"]) -INSTALL_REQUIRES = [ - f"opentrons-shared-data=={VERSION}", -] +INSTALL_REQUIRES = [] def read(*parts): diff --git a/performance-metrics/src/performance_metrics/data_shapes.py b/performance-metrics/src/performance_metrics/data_shapes.py index 70323a7dc4d..b9a39a2fcea 100644 --- a/performance-metrics/src/performance_metrics/data_shapes.py +++ b/performance-metrics/src/performance_metrics/data_shapes.py @@ -25,7 +25,7 @@ class RawContextData(SupportsCSVStorage): @classmethod def headers(self) -> typing.Tuple[str, str, str]: """Returns the headers for the raw context data.""" - return ("state_id", "function_start_time", "duration") + return ("state_name", "function_start_time", "duration") def csv_row(self) -> typing.Tuple[str, int, int]: """Returns the raw context data as a string.""" diff --git a/performance-metrics/src/performance_metrics/types.py b/performance-metrics/src/performance_metrics/types.py index 735ba8c8a5e..5fb2eebd5c5 100644 --- a/performance-metrics/src/performance_metrics/types.py +++ b/performance-metrics/src/performance_metrics/types.py @@ -11,6 +11,7 @@ RobotContextState = typing.Literal[ "ANALYZING_PROTOCOL", + "GETTING_CACHED_ANALYSIS", "RUNNING_PROTOCOL", "CALIBRATING", "ROBOT_STARTING_UP", diff --git a/robot-server/Pipfile b/robot-server/Pipfile index 0b70739eac3..c66f132ecd4 100755 --- a/robot-server/Pipfile +++ b/robot-server/Pipfile @@ -36,8 +36,8 @@ sqlalchemy2-stubs = "==0.0.2a21" # limited by tavern python-box = "==6.1.0" types-paho-mqtt = "==1.6.0.20240106" -performance-metrics = {file = "../performance-metrics", editable = true} pyusb = "==1.2.1" +performance-metrics = {file = "../performance-metrics", editable = true} [packages] anyio = "==3.7.1" diff --git a/robot-server/Pipfile.lock b/robot-server/Pipfile.lock index af344b810f6..a771c9eab95 100644 --- a/robot-server/Pipfile.lock +++ b/robot-server/Pipfile.lock @@ -252,6 +252,70 @@ "markers": "python_version >= '3.8'", "version": "==1.4.1" }, + "greenlet": { + "hashes": [ + "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67", + "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6", + "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257", + "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4", + "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676", + "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61", + "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc", + "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca", + "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7", + "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728", + "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305", + "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6", + "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379", + "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414", + "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04", + "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a", + "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf", + "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491", + "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559", + "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e", + "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274", + "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb", + "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b", + "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9", + "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b", + "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be", + "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506", + "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405", + "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113", + "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f", + "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5", + "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230", + "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d", + "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f", + "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a", + "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e", + "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61", + "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6", + "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d", + "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71", + "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22", + "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2", + "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3", + "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067", + "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc", + "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881", + "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3", + "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e", + "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac", + "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53", + "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0", + "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b", + "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83", + "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41", + "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c", + "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf", + "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da", + "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33" + ], + "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", + "version": "==3.0.3" + }, "h11": { "hashes": [ "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", @@ -481,11 +545,11 @@ }, "packaging": { "hashes": [ - "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==24.0" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "paho-mqtt": { "hashes": [ @@ -617,11 +681,11 @@ }, "setuptools": { "hashes": [ - "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987", - "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32" + "sha256:937a48c7cdb7a21eb53cd7f9b59e525503aa8abaf3584c730dc5f7a5bec3a650", + "sha256:a58a8fde0541dab0419750bcc521fbdf8585f6e5cb41909df3a472ef7b81ca95" ], "markers": "python_version >= '3.8'", - "version": "==69.5.1" + "version": "==70.1.1" }, "sniffio": { "hashes": [ @@ -701,12 +765,12 @@ }, "typing-extensions": { "hashes": [ - "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", - "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==4.11.0" + "version": "==4.12.2" }, "uvicorn": { "hashes": [ @@ -966,11 +1030,11 @@ }, "certifi": { "hashes": [ - "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", - "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" + "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", + "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" ], "markers": "python_version >= '3.6'", - "version": "==2024.2.2" + "version": "==2024.6.2" }, "charset-normalizer": { "hashes": [ @@ -1002,61 +1066,61 @@ "toml" ], "hashes": [ - "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de", - "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661", - "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26", - "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41", - "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d", - "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981", - "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2", - "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34", - "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f", - "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a", - "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35", - "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223", - "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1", - "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746", - "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90", - "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c", - "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca", - "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8", - "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596", - "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e", - "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd", - "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e", - "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3", - "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e", - "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312", - "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7", - "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572", - "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428", - "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f", - "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07", - "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e", - "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4", - "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136", - "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5", - "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8", - "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d", - "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228", - "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206", - "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa", - "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e", - "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be", - "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5", - "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668", - "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601", - "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057", - "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146", - "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f", - "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8", - "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7", - "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987", - "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19", - "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece" + "sha256:018a12985185038a5b2bcafab04ab833a9a0f2c59995b3cec07e10074c78635f", + "sha256:02ff6e898197cc1e9fa375581382b72498eb2e6d5fc0b53f03e496cfee3fac6d", + "sha256:042183de01f8b6d531e10c197f7f0315a61e8d805ab29c5f7b51a01d62782747", + "sha256:1014fbf665fef86cdfd6cb5b7371496ce35e4d2a00cda501cf9f5b9e6fced69f", + "sha256:1137f46adb28e3813dec8c01fefadcb8c614f33576f672962e323b5128d9a68d", + "sha256:16852febd96acd953b0d55fc842ce2dac1710f26729b31c80b940b9afcd9896f", + "sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47", + "sha256:2214ee920787d85db1b6a0bd9da5f8503ccc8fcd5814d90796c2f2493a2f4d2e", + "sha256:3257fdd8e574805f27bb5342b77bc65578e98cbc004a92232106344053f319ba", + "sha256:3684bc2ff328f935981847082ba4fdc950d58906a40eafa93510d1b54c08a66c", + "sha256:3a6612c99081d8d6134005b1354191e103ec9705d7ba2754e848211ac8cacc6b", + "sha256:3d7564cc09dd91b5a6001754a5b3c6ecc4aba6323baf33a12bd751036c998be4", + "sha256:44da56a2589b684813f86d07597fdf8a9c6ce77f58976727329272f5a01f99f7", + "sha256:5013ed890dc917cef2c9f765c4c6a8ae9df983cd60dbb635df8ed9f4ebc9f555", + "sha256:54317c2b806354cbb2dc7ac27e2b93f97096912cc16b18289c5d4e44fc663233", + "sha256:56b4eafa21c6c175b3ede004ca12c653a88b6f922494b023aeb1e836df953ace", + "sha256:581ea96f92bf71a5ec0974001f900db495488434a6928a2ca7f01eee20c23805", + "sha256:5cd64adedf3be66f8ccee418473c2916492d53cbafbfcff851cbec5a8454b136", + "sha256:5df54843b88901fdc2f598ac06737f03d71168fd1175728054c8f5a2739ac3e4", + "sha256:65e528e2e921ba8fd67d9055e6b9f9e34b21ebd6768ae1c1723f4ea6ace1234d", + "sha256:6aae5cce399a0f065da65c7bb1e8abd5c7a3043da9dceb429ebe1b289bc07806", + "sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99", + "sha256:7076b4b3a5f6d2b5d7f1185fde25b1e54eb66e647a1dfef0e2c2bfaf9b4c88c8", + "sha256:73ca8fbc5bc622e54627314c1a6f1dfdd8db69788f3443e752c215f29fa87a0b", + "sha256:79b356f3dd5b26f3ad23b35c75dbdaf1f9e2450b6bcefc6d0825ea0aa3f86ca5", + "sha256:7a892be37ca35eb5019ec85402c3371b0f7cda5ab5056023a7f13da0961e60da", + "sha256:8192794d120167e2a64721d88dbd688584675e86e15d0569599257566dec9bf0", + "sha256:820bc841faa502e727a48311948e0461132a9c8baa42f6b2b84a29ced24cc078", + "sha256:8f894208794b164e6bd4bba61fc98bf6b06be4d390cf2daacfa6eca0a6d2bb4f", + "sha256:a04e990a2a41740b02d6182b498ee9796cf60eefe40cf859b016650147908029", + "sha256:a44963520b069e12789d0faea4e9fdb1e410cdc4aab89d94f7f55cbb7fef0353", + "sha256:a6bb74ed465d5fb204b2ec41d79bcd28afccf817de721e8a807d5141c3426638", + "sha256:ab73b35e8d109bffbda9a3e91c64e29fe26e03e49addf5b43d85fc426dde11f9", + "sha256:aea072a941b033813f5e4814541fc265a5c12ed9720daef11ca516aeacd3bd7f", + "sha256:b1ccf5e728ccf83acd313c89f07c22d70d6c375a9c6f339233dcf792094bcbf7", + "sha256:b385d49609f8e9efc885790a5a0e89f2e3ae042cdf12958b6034cc442de428d3", + "sha256:b3d45ff86efb129c599a3b287ae2e44c1e281ae0f9a9bad0edc202179bcc3a2e", + "sha256:b4a474f799456e0eb46d78ab07303286a84a3140e9700b9e154cfebc8f527016", + "sha256:b95c3a8cb0463ba9f77383d0fa8c9194cf91f64445a63fc26fb2327e1e1eb088", + "sha256:c5986ee7ea0795a4095ac4d113cbb3448601efca7f158ec7f7087a6c705304e4", + "sha256:cdd31315fc20868c194130de9ee6bfd99755cc9565edff98ecc12585b90be882", + "sha256:cef4649ec906ea7ea5e9e796e68b987f83fa9a718514fe147f538cfeda76d7a7", + "sha256:d05c16cf4b4c2fc880cb12ba4c9b526e9e5d5bb1d81313d4d732a5b9fe2b9d53", + "sha256:d2e344d6adc8ef81c5a233d3a57b3c7d5181f40e79e05e1c143da143ccb6377d", + "sha256:d45d3cbd94159c468b9b8c5a556e3f6b81a8d1af2a92b77320e887c3e7a5d080", + "sha256:db14f552ac38f10758ad14dd7b983dbab424e731588d300c7db25b6f89e335b5", + "sha256:dbc5958cb471e5a5af41b0ddaea96a37e74ed289535e8deca404811f6cb0bc3d", + "sha256:ddbd2f9713a79e8e7242d7c51f1929611e991d855f414ca9996c20e44a895f7c", + "sha256:e16f3d6b491c48c5ae726308e6ab1e18ee830b4cdd6913f2d7f77354b33f91c8", + "sha256:e2afe743289273209c992075a5a4913e8d007d569a406ffed0bd080ea02b0633", + "sha256:e564c2cf45d2f44a9da56f4e3a26b2236504a496eb4cb0ca7221cd4cc7a9aca9", + "sha256:ed550e7442f278af76d9d65af48069f1fb84c9f745ae249c1a183c1e9d1b025c" ], "markers": "python_version >= '3.8'", - "version": "==7.5.1" + "version": "==7.5.4" }, "decoy": { "hashes": [ @@ -1192,6 +1256,14 @@ "markers": "python_version >= '3.7'", "version": "==4.17.3" }, + "jsonschema-specifications": { + "hashes": [ + "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", + "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.12.1" + }, "mccabe": { "hashes": [ "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", @@ -1251,18 +1323,13 @@ "markers": "python_version >= '3.5'", "version": "==1.0.0" }, - "opentrons-shared-data": { - "editable": true, - "markers": "python_version >= '3.10'", - "path": "../shared-data/python" - }, "packaging": { "hashes": [ - "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==24.0" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "paho-mqtt": { "hashes": [ @@ -1322,49 +1389,6 @@ "markers": "python_version >= '3.8'", "version": "==2.11.1" }, - "pydantic": { - "hashes": [ - "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303", - "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe", - "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47", - "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494", - "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33", - "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86", - "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d", - "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c", - "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a", - "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565", - "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb", - "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62", - "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62", - "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0", - "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523", - "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d", - "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405", - "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f", - "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b", - "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718", - "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed", - "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb", - "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5", - "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc", - "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942", - "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe", - "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246", - "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350", - "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303", - "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09", - "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33", - "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8", - "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a", - "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1", - "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6", - "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.10.12" - }, "pydocstyle": { "hashes": [ "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019", @@ -1396,44 +1420,6 @@ ], "version": "==1.8.0" }, - "pyrsistent": { - "hashes": [ - "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f", - "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e", - "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958", - "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34", - "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca", - "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d", - "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d", - "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4", - "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714", - "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf", - "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee", - "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8", - "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224", - "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d", - "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054", - "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656", - "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7", - "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423", - "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce", - "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e", - "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3", - "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0", - "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f", - "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b", - "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce", - "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a", - "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174", - "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86", - "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f", - "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b", - "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98", - "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022" - ], - "markers": "python_version >= '3.8'", - "version": "==0.20.0" - }, "pytest": { "hashes": [ "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e", @@ -1445,12 +1431,12 @@ }, "pytest-asyncio": { "hashes": [ - "sha256:68516fdd1018ac57b846c9846b954f0393b26f094764a28c955eabb0536a4e8a", - "sha256:ffe523a89c1c222598c76856e76852b787504ddb72dd5d9b6617ffa8aa2cde5f" + "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b", + "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==0.23.6" + "version": "==0.23.7" }, "pytest-cov": { "hashes": [ @@ -1584,6 +1570,14 @@ "markers": "python_version >= '3.6'", "version": "==6.0.1" }, + "referencing": { + "hashes": [ + "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", + "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de" + ], + "markers": "python_version >= '3.8'", + "version": "==0.35.1" + }, "requests": { "hashes": [ "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", @@ -1593,6 +1587,111 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==2.27.1" }, + "rpds-py": { + "hashes": [ + "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee", + "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc", + "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc", + "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944", + "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20", + "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7", + "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4", + "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6", + "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6", + "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93", + "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633", + "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0", + "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360", + "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8", + "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139", + "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7", + "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a", + "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9", + "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26", + "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724", + "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72", + "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b", + "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09", + "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100", + "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3", + "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261", + "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3", + "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9", + "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b", + "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3", + "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de", + "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d", + "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e", + "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8", + "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff", + "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5", + "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c", + "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e", + "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e", + "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4", + "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8", + "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922", + "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338", + "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d", + "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8", + "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2", + "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72", + "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80", + "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644", + "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae", + "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163", + "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104", + "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d", + "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60", + "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a", + "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d", + "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07", + "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49", + "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10", + "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f", + "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2", + "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8", + "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7", + "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88", + "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65", + "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0", + "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909", + "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8", + "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c", + "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184", + "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397", + "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a", + "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346", + "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590", + "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333", + "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb", + "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74", + "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e", + "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d", + "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa", + "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f", + "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53", + "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1", + "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac", + "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0", + "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd", + "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611", + "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f", + "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c", + "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5", + "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab", + "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc", + "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43", + "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da", + "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac", + "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843", + "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e", + "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89", + "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64" + ], + "markers": "python_version >= '3.8'", + "version": "==0.18.1" + }, "ruamel.yaml": { "hashes": [ "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636", @@ -1749,20 +1848,20 @@ }, "typing-extensions": { "hashes": [ - "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", - "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==4.11.0" + "version": "==4.12.2" }, "urllib3": { "hashes": [ - "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07", - "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0" + "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3", + "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.18" + "version": "==1.26.19" } } } diff --git a/robot-server/robot_server/protocols/protocol_analyzer.py b/robot-server/robot_server/protocols/protocol_analyzer.py index 5e1f4bf765d..8cf32c630f1 100644 --- a/robot-server/robot_server/protocols/protocol_analyzer.py +++ b/robot-server/robot_server/protocols/protocol_analyzer.py @@ -6,6 +6,7 @@ from opentrons import protocol_runner from opentrons.protocol_engine.errors import ErrorOccurrence +from opentrons.util.performance_helpers import TrackingFunctions from opentrons.protocol_engine.types import RunTimeParamValuesType, RunTimeParameter import opentrons.util.helpers as datetime_helper from opentrons.protocol_runner import AbstractRunner, PythonAndLegacyRunner, JsonRunner @@ -55,6 +56,7 @@ async def load_runner( return runner + @TrackingFunctions.track_analysis async def analyze( self, runner: AbstractRunner, diff --git a/robot-server/robot_server/protocols/router.py b/robot-server/robot_server/protocols/router.py index 044117d1f2c..6ff6f9e97c5 100644 --- a/robot-server/robot_server/protocols/router.py +++ b/robot-server/robot_server/protocols/router.py @@ -9,6 +9,7 @@ from opentrons.protocol_engine.types import RunTimeParamValuesType from opentrons_shared_data.robot import user_facing_robot_type +from opentrons.util.performance_helpers import TrackingFunctions from typing_extensions import Literal from fastapi import ( @@ -273,48 +274,54 @@ async def create_protocol( # noqa: C901 cached_protocol_id = protocol_store.get_id_by_hash(content_hash) if cached_protocol_id is not None: - resource = protocol_store.get(protocol_id=cached_protocol_id) - try: - analysis_summaries, _ = await _start_new_analysis_if_necessary( - protocol_id=cached_protocol_id, - analysis_id=analysis_id, - rtp_values=parsed_rtp, - force_reanalyze=False, - protocol_store=protocol_store, - analysis_store=analysis_store, - analyses_manager=analyses_manager, + @TrackingFunctions.track_getting_cached_protocol_analysis + async def _get_cached_protocol_analysis() -> PydanticResponse[ + SimpleBody[Protocol] + ]: + resource = protocol_store.get(protocol_id=cached_protocol_id) + try: + analysis_summaries, _ = await _start_new_analysis_if_necessary( + protocol_id=cached_protocol_id, + analysis_id=analysis_id, + rtp_values=parsed_rtp, + force_reanalyze=False, + protocol_store=protocol_store, + analysis_store=analysis_store, + analyses_manager=analyses_manager, + ) + except AnalysisIsPendingError as error: + raise LastAnalysisPending(detail=str(error)).as_error( + status.HTTP_503_SERVICE_UNAVAILABLE + ) from error + + data = Protocol.construct( + id=cached_protocol_id, + createdAt=resource.created_at, + protocolKind=ProtocolKind.from_string(resource.protocol_kind), + protocolType=resource.source.config.protocol_type, + robotType=resource.source.robot_type, + metadata=Metadata.parse_obj(resource.source.metadata), + analysisSummaries=analysis_summaries, + key=resource.protocol_key, + files=[ + ProtocolFile(name=f.path.name, role=f.role) + for f in resource.source.files + ], ) - except AnalysisIsPendingError as error: - raise LastAnalysisPending(detail=str(error)).as_error( - status.HTTP_503_SERVICE_UNAVAILABLE - ) from error - - data = Protocol.construct( - id=cached_protocol_id, - createdAt=resource.created_at, - protocolKind=ProtocolKind.from_string(resource.protocol_kind), - protocolType=resource.source.config.protocol_type, - robotType=resource.source.robot_type, - metadata=Metadata.parse_obj(resource.source.metadata), - analysisSummaries=analysis_summaries, - key=resource.protocol_key, - files=[ - ProtocolFile(name=f.path.name, role=f.role) - for f in resource.source.files - ], - ) - log.info( - f'Protocol with id "{cached_protocol_id}" with same contents already exists.' - f" Returning existing protocol data in response payload." - ) + log.info( + f'Protocol with id "{cached_protocol_id}" with same contents already exists.' + f" Returning existing protocol data in response payload." + ) - return await PydanticResponse.create( - content=SimpleBody.construct(data=data), - # not returning a 201 because we're not actually creating a new resource - status_code=status.HTTP_200_OK, - ) + return await PydanticResponse.create( + content=SimpleBody.construct(data=data), + # not returning a 201 because we're not actually creating a new resource + status_code=status.HTTP_200_OK, + ) + + return await _get_cached_protocol_analysis() try: source = await protocol_reader.save( diff --git a/scripts/python_build_utils.py b/scripts/python_build_utils.py index a0daeabc8b9..317775cd2f2 100644 --- a/scripts/python_build_utils.py +++ b/scripts/python_build_utils.py @@ -33,6 +33,7 @@ 'usb-bridge': PackageEntry('usb_bridge'), 'system-server': PackageEntry('system_server'), 'server-utils': PackageEntry('server_utils'), + 'performance-metrics': PackageEntry('performance_metrics'), } project_entries = {