From 9b8eafc442abffb1cce857fecb1a5cdf1e878205 Mon Sep 17 00:00:00 2001 From: Shlok Amin Date: Thu, 27 Jun 2024 13:34:54 -0400 Subject: [PATCH] fix(api): Parse all RTP fields strictly to fix flakiness (#15187) (#15536) closes https://opentrons.atlassian.net/browse/RESC-287 --------- Co-authored-by: Max Marrone Co-authored-by: Edward Cormany Co-authored-by: Sanniti Pimpley --- api/release-notes.md | 3 ++ api/src/opentrons/protocol_engine/types.py | 44 ++++++++++++++-------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/api/release-notes.md b/api/release-notes.md index 5c433e6cba8..dbfbfc5bad4 100644 --- a/api/release-notes.md +++ b/api/release-notes.md @@ -12,6 +12,9 @@ Welcome to the v7.4.0 release of the Opentrons robot software! This release adds support for the [Opentrons Flex HEPA/UV Module](https://opentrons.com/products/opentrons-flex-hepa-uv-module). +### Bug Fixes + +- Fixed certain string runtime parameter values being misinterpreted as an incorrect type. --- ## Opentrons Robot Software Changes in 7.3.1 diff --git a/api/src/opentrons/protocol_engine/types.py b/api/src/opentrons/protocol_engine/types.py index 13e9515e447..77ab6231b71 100644 --- a/api/src/opentrons/protocol_engine/types.py +++ b/api/src/opentrons/protocol_engine/types.py @@ -4,7 +4,15 @@ from datetime import datetime from enum import Enum from dataclasses import dataclass -from pydantic import BaseModel, Field, validator +from pydantic import ( + BaseModel, + Field, + StrictBool, + StrictFloat, + StrictInt, + StrictStr, + validator, +) from typing import Optional, Union, List, Dict, Any, NamedTuple, Tuple, FrozenSet from typing_extensions import Literal, TypeGuard @@ -877,12 +885,14 @@ def from_hw_state(cls, state: HwTipStateType) -> "TipPresenceStatus": class RTPBase(BaseModel): """Parameters defined in a protocol.""" - displayName: str = Field(..., description="Display string for the parameter.") - variableName: str = Field(..., description="Python variable name of the parameter.") - description: Optional[str] = Field( + displayName: StrictStr = Field(..., description="Display string for the parameter.") + variableName: StrictStr = Field( + ..., description="Python variable name of the parameter." + ) + description: Optional[StrictStr] = Field( None, description="Detailed description of the parameter." ) - suffix: Optional[str] = Field( + suffix: Optional[StrictStr] = Field( None, description="Units (like mL, mm/sec, etc) or a custom suffix for the parameter.", ) @@ -894,17 +904,17 @@ class NumberParameter(RTPBase): type: Literal["int", "float"] = Field( ..., description="String specifying whether the number is an int or float type." ) - min: float = Field( + min: Union[StrictInt, StrictFloat] = Field( ..., description="Minimum value that the number param is allowed to have." ) - max: float = Field( + max: Union[StrictInt, StrictFloat] = Field( ..., description="Maximum value that the number param is allowed to have." ) - value: float = Field( + value: Union[StrictInt, StrictFloat] = Field( ..., description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.", ) - default: float = Field( + default: Union[StrictInt, StrictFloat] = Field( ..., description="Default value of the parameter, to be used when there is no client-specified value.", ) @@ -916,11 +926,11 @@ class BooleanParameter(RTPBase): type: Literal["bool"] = Field( default="bool", description="String specifying the type of this parameter" ) - value: bool = Field( + value: StrictBool = Field( ..., description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.", ) - default: bool = Field( + default: StrictBool = Field( ..., description="Default value of the parameter, to be used when there is no client-specified value.", ) @@ -929,8 +939,10 @@ class BooleanParameter(RTPBase): class EnumChoice(BaseModel): """Components of choices used in RTP Enum Parameters.""" - displayName: str = Field(..., description="Display string for the param's choice.") - value: Union[float, str] = Field( + displayName: StrictStr = Field( + ..., description="Display string for the param's choice." + ) + value: Union[StrictInt, StrictFloat, StrictStr] = Field( ..., description="Enum value of the param's choice." ) @@ -945,11 +957,11 @@ class EnumParameter(RTPBase): choices: List[EnumChoice] = Field( ..., description="List of valid choices for this parameter." ) - value: Union[float, str] = Field( + value: Union[StrictInt, StrictFloat, StrictStr] = Field( ..., description="The value assigned to the parameter; if not supplied by the client, will be assigned the default value.", ) - default: Union[float, str] = Field( + default: Union[StrictInt, StrictFloat, StrictStr] = Field( ..., description="Default value of the parameter, to be used when there is no client-specified value.", ) @@ -958,5 +970,5 @@ class EnumParameter(RTPBase): RunTimeParameter = Union[NumberParameter, EnumParameter, BooleanParameter] RunTimeParamValuesType = Dict[ - str, Union[float, bool, str] + StrictStr, Union[StrictInt, StrictFloat, StrictBool, StrictStr] ] # update value types as more RTP types are added