Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Migrate Python projects from Pydantic v1 to v2 #14871

Open
wants to merge 140 commits into
base: edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
c2d17fb
update pydantic & fix all mypy errors
ahiuchingau Apr 4, 2024
cae6028
hardware: update pydantic & fix all mypy errors
ahiuchingau Apr 4, 2024
8779c87
hardware: fix Pipfile
ahiuchingau Apr 4, 2024
19f7110
api: update pydantic & fix mypy errors
ahiuchingau Apr 4, 2024
b5c8eab
shared-data: add Vec3f
ahiuchingau Apr 5, 2024
ac77352
shared-data: rename labware_definition to models
ahiuchingau Apr 5, 2024
ef889d4
fix api mypy test errors
ahiuchingau Apr 9, 2024
b3ea918
update api
ahiuchingau Apr 9, 2024
ea9e17e
fix protocol_engine tests
ahiuchingau Apr 9, 2024
90b7fab
fix(api): tests
ahiuchingau Apr 9, 2024
16b69eb
update command schema 8.json
ahiuchingau Apr 9, 2024
528a825
shared-data: deprecate json_encoder and use v2 serializer
ahiuchingau Apr 10, 2024
ff83a57
fix api tests
ahiuchingau Apr 10, 2024
80a7000
api(src): update deprecated code
ahiuchingau Apr 10, 2024
1291aa1
api: linter
ahiuchingau Apr 11, 2024
27bbbec
shared-data: remove deprecated code
ahiuchingau Apr 11, 2024
b646339
shared-data: mypy.ini removed commented out override
ahiuchingau Apr 11, 2024
7588a3f
robot-server & server-utils: update pipenv
ahiuchingau Apr 11, 2024
0b391da
robot-server: add pydantic_settings
ahiuchingau Apr 11, 2024
8114936
robot-server: bump-pydantic to v2
ahiuchingau Apr 11, 2024
52b5899
robot-server: fix lint errors
ahiuchingau Apr 12, 2024
9b02831
robot-server: fix one test
ahiuchingau Apr 12, 2024
2728cca
make lint
ahiuchingau Apr 12, 2024
c47cb10
add model serializer
ahiuchingau Apr 19, 2024
82d5a51
Merge remote-tracking branch 'origin/edge' into chore_update-pydantic-v2
SyntaxColoring May 22, 2024
96b4591
Post-merge code fixups.
SyntaxColoring May 22, 2024
68fa893
Re-lock performance-metrics.
SyntaxColoring May 22, 2024
86623ea
Use == version spec for robot-server, like we had before.
SyntaxColoring May 23, 2024
eac19cb
Remove outdated comment.
SyntaxColoring May 23, 2024
7e1da8d
Update g-code-testing Pipfile.
SyntaxColoring May 23, 2024
8ed4c1e
Update system-server Pipfile.
SyntaxColoring May 23, 2024
913019f
Move performance-metrics from api [dev-packages] to [packages].
SyntaxColoring May 23, 2024
2938afb
Re-lock api.
SyntaxColoring May 23, 2024
2b7d068
_TestCommand.result and ReloadLabware.result need to default to None.
SyntaxColoring May 23, 2024
ac00d02
Revert SyncClient model_validate() changes.
SyntaxColoring May 23, 2024
10aa798
Remove now-unneeded type-ignores.
SyntaxColoring May 23, 2024
fef7108
Don't instantiate BaseModel directly.
SyntaxColoring May 23, 2024
a7a69d7
Merge branch 'chore_update-pydantic-v2' of github.com:Opentrons/opent…
SyntaxColoring May 23, 2024
46b024b
Regenerate command schema.
SyntaxColoring May 23, 2024
7d73026
Delete empty log.txt.
SyntaxColoring May 23, 2024
14bc816
Update .json() calls in cli.analyze.
SyntaxColoring May 23, 2024
8dbe3d8
Run bump-pydantic on api.
SyntaxColoring May 24, 2024
d975c0e
Give up on test_command_executor.py.
SyntaxColoring May 23, 2024
e677a7e
Pin fastapi with == like we had before.
SyntaxColoring May 24, 2024
3771b91
Ensure all fastapi pins consistently use 0.100.0.
SyntaxColoring May 24, 2024
ec14dd7
Move robot-server's dependency on performance-metrics to [packages].
SyntaxColoring May 24, 2024
d3c6ce2
Install pydantic-settings in system-server.
SyntaxColoring May 24, 2024
34cae8c
Add pydantic-settings to robot-server/setup.py.
SyntaxColoring May 24, 2024
7ee2b47
Re-lock everything.
SyntaxColoring May 24, 2024
1b3b099
robot-server: Run bump-pydantic.
SyntaxColoring May 24, 2024
06e87fd
robot-server: Remove now-unneeded type-ignores.
SyntaxColoring May 24, 2024
9cdeb04
robot-server: Add a unit test for robot_server.persistence.pydantic.
SyntaxColoring May 24, 2024
5f60e97
robot-server: Post-merge fixups to robot_server.persistence.pydantic.
SyntaxColoring May 24, 2024
dd461e9
system-server: Run bump-pydantic.
SyntaxColoring May 24, 2024
3b1da95
system-server: Manual fixups.
SyntaxColoring May 24, 2024
ff3db4e
Merge remote-tracking branch 'origin/edge' into chore_update-pydantic-v2
SyntaxColoring May 28, 2024
14f5c10
g-code-testing: Run bump-pydantic [WIP]
SyntaxColoring May 24, 2024
01f0ed9
WIP: Fix some slow stuff with TypeAdapter?
SyntaxColoring May 24, 2024
de2b400
robot-server: Update error messages in tests.
SyntaxColoring May 25, 2024
d674c66
Revert BaseModel -> BaseResponseBody changes.
SyntaxColoring Jun 7, 2024
1d95e40
Merge branch 'edge' into chore_update-pydantic-v2
sfoster1 Sep 3, 2024
18a3b22
chore: format and fix lints
sfoster1 Sep 4, 2024
9417cd0
s-d: fix tests
sfoster1 Sep 4, 2024
315a370
api: fix testst
sfoster1 Sep 4, 2024
fea1fad
schema format
sfoster1 Sep 5, 2024
7fecd09
make this installable per https://github.com/pypa/setuptools/issues/4483
sfoster1 Sep 5, 2024
b0c849f
Merge branch 'edge' into chore_update-pydantic-v2
sfoster1 Sep 5, 2024
8082363
chore: pydantic 2.9.0
sfoster1 Sep 5, 2024
b3f7e04
chore: mypy 1.11.0
sfoster1 Sep 5, 2024
5a781f1
chore: py lint fixes
sfoster1 Sep 5, 2024
bab482b
chore: fix hardware-testing
sfoster1 Sep 5, 2024
aaf8f58
chore: fix api runtime type dependencies
sfoster1 Sep 6, 2024
9159f4a
fixup command schema
sfoster1 Sep 6, 2024
666b3ff
fixup some server tests
sfoster1 Sep 9, 2024
cdbf235
Merge branch 'edge' into chore_update-pydantic-v2
sfoster1 Nov 1, 2024
4809ec3
Merge branch 'edge' into chore_update-pydantic-v2
sfoster1 Dec 3, 2024
25f0c72
get lint all the way working
sfoster1 Dec 3, 2024
6ddf38b
shared-data: lint, test, warnings
sfoster1 Dec 3, 2024
f3dd85a
robot-server lint
sfoster1 Dec 3, 2024
6344995
s-d: enum handling
sfoster1 Dec 3, 2024
fce1971
all but ischema string
sfoster1 Dec 3, 2024
e3a6b90
sort the schema for better comparison later
sfoster1 Dec 3, 2024
74606e6
fix schema generation
sfoster1 Dec 3, 2024
a26b495
fix the rest of the api warnings
sfoster1 Dec 3, 2024
f3c812c
fix some r-s and s-s warnings
sfoster1 Dec 3, 2024
6332c99
more server fixes
sfoster1 Dec 4, 2024
2170735
non-integration tests fixed
sfoster1 Dec 5, 2024
dcd9257
more validation stuff
sfoster1 Dec 5, 2024
6fd9da7
Format.
SyntaxColoring Dec 9, 2024
f9dba7e
int instead of float for ge.
SyntaxColoring Dec 9, 2024
b5b28b6
Fix "global" `exclude_none=True` override.
SyntaxColoring Dec 10, 2024
6bd2223
Delete redundant BaseModel inheritance.
SyntaxColoring Dec 10, 2024
3414714
Revert `exclude_none=True, exclude_unset=True, exclude_defaults=True`…
SyntaxColoring Dec 10, 2024
b00a4ec
Revert test_response.py changes.
SyntaxColoring Dec 10, 2024
44f0f4d
Shift datetime workaround from production code to tests.
SyntaxColoring Dec 10, 2024
e065c31
Merge branch 'edge' into chore_update-pydantic-v2
SyntaxColoring Dec 10, 2024
fd76bcf
Fix robot-server docs build script.
SyntaxColoring Dec 10, 2024
f871244
Delete `no_strict_optional=True` workaround.
SyntaxColoring Dec 10, 2024
ab72323
performance-metrics: Fix systemd-python marker and re-lock.
SyntaxColoring Dec 10, 2024
4a874de
performance-metrics: Ignore missing systemd.daemon import.
SyntaxColoring Dec 10, 2024
854219d
Bump test server startup timeout from 20 to 40.
SyntaxColoring Dec 10, 2024
54eb964
Revert .construct() -> .__init__() in legacy_command_mapper.py.
SyntaxColoring Dec 10, 2024
8e14b56
Merge branch 'edge' into chore_update-pydantic-v2
SyntaxColoring Dec 10, 2024
3a7f070
Lint hardware-testing.
SyntaxColoring Dec 10, 2024
d5a707d
Revert changes to command schema 8.
SyntaxColoring Dec 10, 2024
4cefc25
Fix unused type ignore.
SyntaxColoring Dec 11, 2024
6ee8fa2
Format.
SyntaxColoring Dec 11, 2024
9768f01
Fix verify_definition() type-checking.
SyntaxColoring Dec 11, 2024
3dbe348
Add missing pydantic-settings specs to api and hardware setup.py.
SyntaxColoring Dec 11, 2024
10483bc
Experiment: Re-lock some Python projects.
SyntaxColoring Dec 11, 2024
8d7d85d
Manually complete g-code-testing migration.
SyntaxColoring Dec 12, 2024
8e81542
Merge remote-tracking branch 'origin/edge' into chore_update-pydantic-v2
SyntaxColoring Dec 12, 2024
212e876
Migrate new command annotation code.
SyntaxColoring Dec 12, 2024
a17012f
Revert use of pydantic_core.from_json() in labware def validation.
SyntaxColoring Dec 12, 2024
fe5005e
Revert vector model moves/refactors.
SyntaxColoring Dec 12, 2024
6f5cdba
Replace conint etc. with Annotated. Remove obsolete TYPE_CHECKING con…
SyntaxColoring Dec 12, 2024
f8263cb
Shore up HexColor tests for my paranoia.
SyntaxColoring Dec 12, 2024
ab27980
Fix up command schema after revert of vector refactors.
SyntaxColoring Dec 13, 2024
944b3f5
Fix incorrect construction of LabwareOffsetVectors.
SyntaxColoring Dec 13, 2024
909295d
Fix text decoding when parsing JSON from files.
SyntaxColoring Dec 13, 2024
93affa8
Update analysis snapshots for 0 changing to 0.0.
SyntaxColoring Dec 13, 2024
2b4863c
Revert jsonschema loosening.
SyntaxColoring Dec 14, 2024
2550326
Update snapshot test for protocol type coercion bug.
SyntaxColoring Dec 13, 2024
2c32dd3
Undo formatting change to mypy.ini.
SyntaxColoring Dec 14, 2024
3a29b86
Merge branch 'edge' into chore_update-pydantic-v2
SyntaxColoring Dec 16, 2024
8eac2cd
Diff minimization: Revert labware_definition->models rename.
SyntaxColoring Dec 16, 2024
33a3fc7
Revert apparently unnecessary exclude_unset etc.
SyntaxColoring Dec 16, 2024
0d7f92b
Diff minimization: Revert some trivial renames.
SyntaxColoring Dec 16, 2024
b451291
Diff minimization: Revert some small non-semantic changes (formatting…
SyntaxColoring Dec 16, 2024
7767537
limit rpds to something old enough for oe
sfoster1 Dec 16, 2024
c508888
why was it like this? it cant be like this
sfoster1 Dec 16, 2024
3686593
Re-delete ResponseList.
SyntaxColoring Dec 16, 2024
c714786
Diff minimization: .json() and .dict() overrides.
SyntaxColoring Dec 16, 2024
5bc242b
Delete now-obsolete (?) TypeAdapter overload workaround.
SyntaxColoring Dec 16, 2024
53d902d
perf: Parse RTPs through a TypeAdapter.
SyntaxColoring Dec 16, 2024
d7b1740
Delete todo comment in _up_to_3_worker.py.
SyntaxColoring Dec 16, 2024
d97002b
Merge branch 'edge' into chore_update-pydantic-v2
SyntaxColoring Dec 17, 2024
eedc0e0
Update JSONResponse docstring.
SyntaxColoring Dec 17, 2024
023276e
Handle the new startingTipWell param like other None-valued params.
SyntaxColoring Dec 17, 2024
b412650
surprise, this went through Any and wasn't caught
sfoster1 Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ name = "pypi"

[packages]
jsonschema = "==4.17.3"
pydantic = "==1.10.12"
pydantic = "==2.6.4"
pydantic-settings = "==2.2.1"
anyio = "==3.7.1"
opentrons-shared-data = { editable = true, path = "../shared-data/python" }
opentrons = { editable = true, path = "." }
Expand Down
931 changes: 513 additions & 418 deletions api/Pipfile.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions api/mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ disallow_incomplete_defs = False
disallow_untyped_defs = False
disallow_untyped_calls = False
disallow_incomplete_defs = False

# TODO: fixed in Pydantic 2.7, see https://github.com/pydantic/pydantic/pull/9008
[mypy-tests.opentrons.protocol_engine.execution.test_command_executor.*]
no_strict_optional=True
4 changes: 2 additions & 2 deletions api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ def get_version():
f"opentrons-shared-data=={VERSION}",
"aionotify==0.2.0",
"anyio>=3.6.1,<4.0.0",
"jsonschema>=3.0.1,<4.18.0",
"jsonschema>=4.0.0,<5",
"numpy>=1.20.0,<2",
"pydantic>=1.10.9,<2.0.0",
"pydantic>=2.0.0,<3",
"pyserial>=3.5",
"typing-extensions>=4.0.0,<5",
"click>=8.0.0,<9",
Expand Down
4 changes: 2 additions & 2 deletions api/src/opentrons/calibration_storage/deck_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def serialize_deck_configuration(
cutout_fixture_placements: List[CutoutFixturePlacement], last_modified: datetime
) -> bytes:
"""Serialize a deck configuration for storing on the filesystem."""
data = _DeckConfigurationModel.construct(
data = _DeckConfigurationModel.model_construct(
cutoutFixtures=[
_CutoutFixturePlacementModel.construct(
_CutoutFixturePlacementModel.model_construct(
cutoutId=e.cutout_id, cutoutFixtureId=e.cutout_fixture_id
)
for e in cutout_fixture_placements
Expand Down
4 changes: 2 additions & 2 deletions api/src/opentrons/calibration_storage/file_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def save_to_file(

def serialize_pydantic_model(data: pydantic.BaseModel) -> bytes:
"""Safely serialize data from a Pydantic model into a form suitable for storing on disk."""
return data.json(by_alias=True).encode("utf-8")
return data.model_dump_json(by_alias=True).encode("utf-8")


_ModelT = typing.TypeVar("_ModelT", bound=pydantic.BaseModel)
Expand All @@ -133,7 +133,7 @@ def deserialize_pydantic_model(
Returns `None` if the file is missing or corrupt.
"""
try:
return model.parse_raw(serialized)
return model.model_validate_json(serialized)
except json.JSONDecodeError:
_log.warning("Data is not valid JSON.", exc_info=True)
return None
Expand Down
45 changes: 16 additions & 29 deletions api/src/opentrons/calibration_storage/ot2/models/v1.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import typing

from typing_extensions import Literal
from pydantic import BaseModel, Field, validator
from pydantic import field_validator, BaseModel, Field, PlainSerializer
from datetime import datetime

from opentrons_shared_data.pipette.dev_types import LabwareUri

from opentrons.types import Point
from opentrons.calibration_storage import types

DatetimeType = typing.Annotated[
datetime,
PlainSerializer(lambda x: x.isoformat(), when_used="json"),
]

SyntaxColoring marked this conversation as resolved.
Show resolved Hide resolved

class CalibrationStatus(BaseModel):
markedBad: bool = False
source: typing.Optional[types.SourceType] = None
markedAt: typing.Optional[datetime] = None
markedAt: typing.Optional[DatetimeType] = None


# Schemas used to store the data types
Expand All @@ -22,7 +27,7 @@ class CalibrationStatus(BaseModel):
# they are currently saved in on the OT-2 to avoid a large migration.
class TipLengthModel(BaseModel):
tipLength: float = Field(..., description="Tip length data found from calibration.")
lastModified: datetime = Field(
lastModified: DatetimeType = Field(
..., description="The last time this tip length was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -40,22 +45,19 @@ class TipLengthModel(BaseModel):
..., description="The tiprack hash associated with the tip length data."
)

@validator("tipLength")
@field_validator("tipLength")
@classmethod
def ensure_tip_length_positive(cls, tipLength: float) -> float:
if tipLength < 0.0:
raise ValueError("Tip Length must be a positive number")
return tipLength

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


class DeckCalibrationModel(BaseModel):
attitude: types.AttitudeMatrix = Field(
..., description="Attitude matrix for deck found from calibration."
)
last_modified: typing.Optional[datetime] = Field(
last_modified: typing.Optional[DatetimeType] = Field(
default=None, description="The last time this deck was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -72,18 +74,14 @@ class DeckCalibrationModel(BaseModel):
description="The status of the calibration data.",
)

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


class InstrumentOffsetModel(BaseModel):
offset: Point = Field(..., description="Instrument offset found from calibration.")
tiprack: str = Field(..., description="Tiprack used to calibrate this offset")
uri: str = Field(
..., description="The URI of the labware used for instrument offset"
)
last_modified: datetime = Field(
last_modified: DatetimeType = Field(
..., description="The last time this instrument was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -94,10 +92,6 @@ class InstrumentOffsetModel(BaseModel):
description="The status of the calibration data.",
)

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


# TODO(lc 09-19-2022) We need to refactor the calibration endpoints
# so that we only need to use one data model schema. This model is a
Expand All @@ -112,7 +106,7 @@ class PipetteOffsetCalibration(BaseModel):
uri: str = Field(
..., description="The URI of the labware used for instrument offset"
)
last_modified: datetime = Field(
last_modified: DatetimeType = Field(
..., description="The last time this instrument was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -123,10 +117,6 @@ class PipetteOffsetCalibration(BaseModel):
description="The status of the calibration data.",
)

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


# TODO(lc 09-19-2022) We need to refactor the calibration endpoints
# so that we only need to use one data model schema. This model is a
Expand All @@ -137,7 +127,7 @@ class TipLengthCalibration(BaseModel):
..., description="The tiprack hash associated with this tip length data."
)
tipLength: float = Field(..., description="Tip length data found from calibration.")
lastModified: datetime = Field(
lastModified: DatetimeType = Field(
..., description="The last time this tip length was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -151,12 +141,9 @@ class TipLengthCalibration(BaseModel):
..., description="The tiprack URI associated with the tip length data."
)

@validator("tipLength")
@field_validator("tipLength")
@classmethod
def ensure_tip_length_positive(cls, tipLength: float) -> float:
if tipLength < 0.0:
raise ValueError("Tip Length must be a positive number")
return tipLength

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}
1 change: 1 addition & 0 deletions api/src/opentrons/calibration_storage/ot2/tip_length.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
def _convert_tip_length_model_to_dict(
to_dict: typing.Dict[LabwareUri, v1.TipLengthModel]
) -> typing.Dict[LabwareUri, typing.Any]:
# TODO[pydantic]: supported in Pydantic V2
# This is a workaround since pydantic doesn't have a nice way to
# add encoders when converting to a dict.
dict_of_tip_lengths = {}
Expand Down
37 changes: 14 additions & 23 deletions api/src/opentrons/calibration_storage/ot3/models/v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing_extensions import Literal
from opentrons.hardware_control.modules.types import ModuleType
from opentrons.hardware_control.types import OT3Mount
from pydantic import BaseModel, Field, validator
from pydantic import field_validator, BaseModel, Field, PlainSerializer
from datetime import datetime

from opentrons_shared_data.pipette.dev_types import LabwareUri
Expand All @@ -12,15 +12,21 @@
from opentrons.calibration_storage import types


DatetimeType = typing.Annotated[
datetime,
PlainSerializer(lambda x: x.isoformat(), when_used="json"),
]
SyntaxColoring marked this conversation as resolved.
Show resolved Hide resolved


class CalibrationStatus(BaseModel):
markedBad: bool = False
source: typing.Optional[types.SourceType] = None
markedAt: typing.Optional[datetime] = None
markedAt: typing.Optional[DatetimeType] = None


class TipLengthModel(BaseModel):
tipLength: float = Field(..., description="Tip length data found from calibration.")
lastModified: datetime = Field(
lastModified: DatetimeType = Field(
..., description="The last time this tip length was calibrated."
)
uri: typing.Union[LabwareUri, Literal[""]] = Field(
Expand All @@ -34,22 +40,19 @@ class TipLengthModel(BaseModel):
description="The status of the calibration data.",
)

@validator("tipLength")
@field_validator("tipLength")
@classmethod
def ensure_tip_length_positive(cls, tipLength: float) -> float:
if tipLength < 0.0:
raise ValueError("Tip Length must be a positive number")
return tipLength

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


class BeltCalibrationModel(BaseModel):
attitude: types.AttitudeMatrix = Field(
..., description="Attitude matrix for belts found from calibration."
)
lastModified: datetime = Field(
lastModified: DatetimeType = Field(
..., description="The last time this deck was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -63,14 +66,10 @@ class BeltCalibrationModel(BaseModel):
description="The status of the calibration data.",
)

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


class InstrumentOffsetModel(BaseModel):
offset: Point = Field(..., description="Instrument offset found from calibration.")
lastModified: datetime = Field(
lastModified: DatetimeType = Field(
..., description="The last time this instrument was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -81,10 +80,6 @@ class InstrumentOffsetModel(BaseModel):
description="The status of the calibration data.",
)

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}


class ModuleOffsetModel(BaseModel):
offset: Point = Field(..., description="Module offset found from calibration.")
Expand All @@ -99,7 +94,7 @@ class ModuleOffsetModel(BaseModel):
...,
description="The unique id of the instrument used to calibrate this module.",
)
lastModified: datetime = Field(
lastModified: DatetimeType = Field(
..., description="The last time this module was calibrated."
)
source: types.SourceType = Field(
Expand All @@ -109,7 +104,3 @@ class ModuleOffsetModel(BaseModel):
default_factory=CalibrationStatus,
description="The status of the calibration data.",
)

class Config:
json_encoders = {datetime: lambda obj: obj.isoformat()}
json_decoders = {datetime: lambda obj: datetime.fromisoformat(obj)}
11 changes: 5 additions & 6 deletions api/src/opentrons/cli/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,19 @@ async def _analyze(
robot_type=protocol_source.robot_type, protocol_config=protocol_source.config
)
analysis = await runner.run(deck_configuration=[], protocol_source=protocol_source)

if json_output:
results = AnalyzeResults.construct(
results = AnalyzeResults.model_construct(
createdAt=datetime.now(tz=timezone.utc),
files=[
ProtocolFile.construct(name=f.path.name, role=f.role)
ProtocolFile.model_construct(name=f.path.name, role=f.role)
for f in protocol_source.files
],
config=(
JsonConfig.construct(
JsonConfig.model_construct(
schemaVersion=protocol_source.config.schema_version
)
if isinstance(protocol_source.config, JsonProtocolConfig)
else PythonConfig.construct(
else PythonConfig.model_construct(
apiVersion=protocol_source.config.api_version
)
),
Expand All @@ -110,7 +109,7 @@ async def _analyze(
)

await json_output.write_text(
results.json(exclude_none=True),
results.model_dump_json(exclude_none=True),
encoding="utf-8",
)

Expand Down
6 changes: 4 additions & 2 deletions api/src/opentrons/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
Union,
)

from opentrons_shared_data.labware.labware_definition import LabwareDefinition
from opentrons_shared_data.labware.models import LabwareDefinition
from opentrons_shared_data.robot.dev_types import RobotType

from opentrons import protocol_api, __version__, should_use_ot3
Expand Down Expand Up @@ -550,7 +550,9 @@ def _create_live_context_pe(
# Non-async would use call_soon_threadsafe(), which makes the waiting harder.
async def add_all_extra_labware() -> None:
for labware_definition_dict in extra_labware.values():
labware_definition = LabwareDefinition.parse_obj(labware_definition_dict)
labware_definition = LabwareDefinition.model_validate(
labware_definition_dict
)
pe.add_labware_definition(labware_definition)

# Add extra_labware to ProtocolEngine, being careful not to modify ProtocolEngine from this
Expand Down
7 changes: 3 additions & 4 deletions api/src/opentrons/hardware_control/emulation/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from typing import List
from opentrons.hardware_control.emulation.types import ModuleType
from opentrons.hardware_control.emulation.util import TEMPERATURE_ROOM
from pydantic import BaseSettings, BaseModel
from pydantic import BaseModel
from pydantic_settings import BaseSettings, SettingsConfigDict


class PipetteSettings(BaseModel):
Expand Down Expand Up @@ -113,8 +114,6 @@ class Settings(BaseSettings):
emulator_port=9003, driver_port=9998
)
magdeck_proxy: ProxySettings = ProxySettings(emulator_port=9004, driver_port=9999)

class Config:
env_prefix = "OT_EMULATOR_"
model_config = SettingsConfigDict(env_prefix="OT_EMULATOR_")

module_server: ModuleServerSettings = ModuleServerSettings()
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from opentrons.types import Mount, Point
from opentrons.hardware_control.types import OT3Mount

from opentrons_shared_data.labware.labware_definition import LabwareDefinition
from opentrons_shared_data.labware.models import LabwareDefinition

if typing.TYPE_CHECKING:
from opentrons_shared_data.pipette.dev_types import LabwareUri
Expand Down
Loading
Loading