Skip to content

Conversation

@sfoster1
Copy link
Member

@sfoster1 sfoster1 commented Nov 10, 2025

This is the work-in-progress branch for the monorepo side of bumping buildroot (Opentrons/buildroot#269 ) and oe-core ( Opentrons/oe-core#237 ) to more recent versions.

The goal with this work is to only update our direct dependencies as little as possible to get the system builder updates working. Once the system builder updates are merged (ideally with little work in this repo), we can update our direct dependencies to the highest versions supported by the system builders at their new versions.

For more details on what is changing, see the system builder PRs; the biggest thing to note here is

The new python version for both Flex and OT-2 will be 3.12

To come out of draft

  • oe-core builds
  • buildroot builds
  • oe-core boots
  • buildroot boots
  • user installed packages more or less still work

To merge

  • regression test ot-2
  • regression test flex

@codecov
Copy link

codecov bot commented Nov 10, 2025

Codecov Report

❌ Patch coverage is 0% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 26.00%. Comparing base (c9f19f3) to head (0d9c8c4).
⚠️ Report is 1 commits behind head on edge.

Files with missing lines Patch % Lines
app-shell/scripts/python-install.js 0.00% 19 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             edge   #20109      +/-   ##
==========================================
+ Coverage   25.63%   26.00%   +0.37%     
==========================================
  Files        3628     3628              
  Lines      302056   301971      -85     
  Branches    42321    42369      +48     
==========================================
+ Hits        77427    78528    +1101     
+ Misses     224605   223420    -1185     
+ Partials       24       23       -1     
Flag Coverage Δ
app 2.09% <0.00%> (+1.17%) ⬆️
protocol-designer 19.35% <0.00%> (+<0.01%) ⬆️
step-generation 5.59% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...re_bindings/messages/binary_message_definitions.py 77.77% <ø> (-11.23%) ⬇️
.../firmware_bindings/messages/message_definitions.py 97.69% <ø> (-0.01%) ⬇️
...ns_hardware/firmware_bindings/messages/payloads.py 96.11% <ø> (ø)
...are/opentrons_hardware/instruments/serial_utils.py 100.00% <ø> (ø)
hardware/opentrons_hardware/scripts/load.py 0.00% <ø> (ø)
...a/python/opentrons_shared_data/data_files/types.py 0.00% <ø> (ø)
.../python/opentrons_shared_data/errors/exceptions.py 50.88% <ø> (-0.15%) ⬇️
...pentrons_shared_data/gripper/gripper_definition.py 95.12% <ø> (-0.34%) ⬇️
...pentrons_shared_data/labware/labware_definition.py 79.41% <ø> (-0.14%) ⬇️
.../python/opentrons_shared_data/pipette/dev_types.py 0.00% <ø> (ø)
... and 2 more

... and 104 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This is the version in buildroot 2025.02

We should really remove this it seems to be used to proxy a single
request forward and nothing else
This is the version buildroot 2025.02. Also remove the python version in
the pipfile we set that elsewhere
The local overrides for hatch aren't necessary anymore
We need 1.26 because 1.25 doesn't work with python packaging setups.
Fixes an issue about checking TypedDicts
We have these proxy servers, and they just hang when tearing them down
sometimes. Well, they used to; in 3.12, they hang when tearing them down
every time.

The reason is that the asyncio server code doesn't handle being shutdown
in the presence of connected clients very well. Previously, it might
hang; in 3.12, it will always hang because there's some code that
catches cancellation and tries to wait for a clean shutdown that will
never happen.

In <3.13 there's also no way to properly shut down clients in the public
api.

One workaround, which is awful, and which we're doing, is to just cancel
the server twice, waiting a little in between so that we can get the
server into that state where it's waiting a bit.

Luckily this is not really used in production code.
We heavily used `class MyStringEnum(str, Enum)` to create string
enumerators that, when put in format strings, just result in their
value. This is because the __format__ dunder of these enums was
formatting them differently than other kinds of enums. In 3.11, this
became consistent, and so we need to use the new class StrEnum - which
has the proper behavior - instead. If StrEnum doesn't exist, we'll use a
weird override.

Also we really need to use __new__ overrides for our error dataclass enum.
Papering over some more fiddly asyncio sequencing details with a sleep,
what could go wrong
Enum stuff and removing a use of distutils
@sfoster1 sfoster1 requested review from mjhuff and removed request for a team December 5, 2025 18:58
@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

A PR has been opened to address analyses snapshot changes. Please review the changes here: #20300

@sfoster1
Copy link
Member Author

sfoster1 commented Dec 5, 2025

Analysis snapshot changes are some math stuff of the kind fixed in d5ecd37 and PEP-657 traceback location improvements

strategy:
matrix:
os: ['ubuntu-24.04', 'macos-latest', 'windows-2022']
python: ['3.10', '3.11', '3.12', '3.13']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's 3.13 doing here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

figured we'd get ahead of the game a little, ease next time's pain. light preference

"labwareId": "UUID",
"pipetteId": "UUID",
"volume": 13.333333333333332,
"volume": 13.333333333333334,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol


class WellOrigin(str, Enum):

class WellOrigin(StrEnum):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

# Python 3.11 changed the string serialization of string based enums
# to always include the enumerator name; it previously did not. This
# is more consistent but also breaks our usage of string based enums.
# The replacement class StrEnum has the old behavior, but it's not
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean? Could you clarify what the behavior you want is?

If we have

class WellOrigin(StrEnum):
  TOP = "top"

Then do you want f"{WellOrigin.TOP}" to be top or TOP?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually not about whether it's top or TOP - I don't remember off the top of my head, but the code we have treats that difference correctly. The difference is this:

from enum import Enum

class MyEnum(str, Enum):
   ENTRY = 'entry'

print(MyEnum.ENTRY)
print(str(MyEnum.ENTRY))
print(f'{MyEnum.ENTRY}')
❯ python --version
Python 3.10.13
❯ python testenums.py
MyEnum.ENTRY
MyEnum.ENTRY
entry
❯ python --version
Python 3.12.12
❯ python testenums.py
MyEnum.ENTRY
MyEnum.ENTRY
MyEnum.ENTRY

Whereas with this

from enum import StrEnum

class MyEnum(StrEnum):
   ENTRY = 'entry'

print(MyEnum.ENTRY)
print(str(MyEnum.ENTRY))
print(f'{MyEnum.ENTRY}')

You get this:

❯ python --version
Python 3.12.12
❯ python testenums2.py
entry
entry
entry

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, today I learned f"{x}" isn't necessarily equal to str(x). 🫠

Copy link
Contributor

@mjhuff mjhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very exciting! Thank you! 🎉

Copy link
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thank you!

# Python 3.11 changed the string serialization of string based enums
# to always include the enumerator name; it previously did not. This
# is more consistent but also breaks our usage of string based enums.
# The replacement class StrEnum has the old behavior, but it's not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, today I learned f"{x}" isn't necessarily equal to str(x). 🫠

ncdiehl11 and others added 11 commits December 8, 2025 13:48
With the decision to treat Quick Transfer protocols more like standard
protocols, we want to show them in the desktop app's
`RecentProtocolRuns` component. This also allows us to view and download
any files from the run, which as of now would include photos taken
during any potential error recovery.

There are also a few instances in ODD where we implicitly delete QT
runs. We don't want to do this!
# Overview

Moved run status utils into `local-resources` since they are used across
platforms in the app
Replaced the majority of instances of bare `runStatus` strings with
utils

## Changelog
- moved utils from `ProtocolHeader` to `local-resources`
- fixed conditional bug that was preventing you from restarting a run
due to the robot being in idle state

## Test Plan and Hands on Testing
- smoke tested various places of app and odd

## Review requests

- Double check run status groupings aren't repeated
- Double check majority of run status bare string usage is addressed


## Risk assessment

medium - touches a lot of code but does not change functionality

Closes second half of EXEC-1478
…ls (#20197)

# Overview

Camera, concurrent modules, and dynamic liquid tracking implemented into
active ABR protocols

## Test Plan and Hands on Testing

- All protocols simulate
- `TODO:` protocols with the tc lid and dynamic liquid tracking have not
been tested on a robot yet

## Changelog
- also added a robot log script to compare duration of protocol commands

## Review requests

@ryanthecoder when implementing the dynamic pipetting, there were a
couple spots I needed to add `prepare_to_aspirate()` before a dynamic
aspirate to avoid getting this error:

```
ProtocolCommandFailedError [line 1035]: Error 4000 GENERAL_ERROR (ProtocolCommandFailedError): PipetteNotReadyToAspirateError: Pipette cannot aspirate while tracking because a previous dispense or blowout pushed the plunger beyond the bottom position. The subsequent aspirate must be from a specific well so the plunger can be reset in a known safe position.
```
Is this expected?

## Risk assessment

medium until the protocols are run on the robot
…ges (#20299)

Closes RQA-4941

Axios cannot return Blob types when in a Node.js environment (there is no native blob type in the version of Axios we use), and Electron's IPC mechanism does not properly serialize Blob objects into strings anyway.

To fix, on the node layer we can request an ArrayBuffer type instead, transform it to an Array type, and then send this data across the IPC as it becomes perfectly serializable. We can then parse this Array type back into a Blob on the browser layer.

Note that downloading images works perfectly fine - it's just an issue whenever we request the raw image files themselves.
* feat(app): add Skeleton component for second window
* fix(app): remove number from individual command
# Overview

Add non functional livestream image capture button hidden behind the
camera settings feature flag

## Test Plan and Hands on Testing

Smoke tested on ODD w/o feature flag on
<img width="491" height="430" alt="Screenshot 2025-12-04 at 2 56 59 PM"
src="https://github.com/user-attachments/assets/750a5315-4eee-4dbc-8a8d-698d8784683a"
/>

## Review requests



## Risk assessment

low

Closes EXEC-2101
…are (#20253)

# Overview

PR for touch probe proof of concept. Adds firmware, drivers, and
hardware testing scripts for the touch probe.


https://docs.google.com/document/d/151cAolVlUmFbdYdXOCe5GIgDmzycKI_iPKSS7zWbS0I/edit?tab=t.0

## Changelog

-added touch probe firmware + drivers
-added touch_probe mock scripts to hardware testing

---------

Co-authored-by: Ryan Howard <[email protected]>
Co-authored-by: Rhyann Clarke <[email protected]>
Co-authored-by: Rhyann Clarke <[email protected]>
#20311)

* fix(components): fix primarybutton and alt primarybutton styling issue
@sfoster1 sfoster1 requested a review from a team as a code owner December 8, 2025 18:48
Copy link
Collaborator

@ddcc4 ddcc4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll approve this, but I didn't quite catch what you mean by:

❯ python --version
Python 3.10.13
❯ python testenums.py
MyEnum.ENTRY
MyEnum.ENTRY
entry

vs

Whereas with this
You get this:
❯ python --version
Python 3.12.12
❯ python testenums2.py
entry
entry
entry

Isn't this going to be a change in behavior compared to Python 3.10 then?

@sfoster1
Copy link
Member Author

sfoster1 commented Dec 8, 2025

I'll approve this, but I didn't quite catch what you mean by:

❯ python --version
Python 3.10.13
❯ python testenums.py
MyEnum.ENTRY
MyEnum.ENTRY
entry

vs

Whereas with this
You get this:
❯ python --version
Python 3.12.12
❯ python testenums2.py
entry
entry
entry

Isn't this going to be a change in behavior compared to Python 3.10 then?

It is, but we pretty much only care about the format string version

Numpy 1.26.4 doesn't have a precompiled wheel for python 3.13, so when
you install it pip will build it locally. This takes a while, but also
creates a bad object on windows since numpy doesn't support mingw.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gen-analyses-snapshot-pr Generate a healing PR if the analyses snapshot test fails

Projects

None yet

Development

Successfully merging this pull request may close these issues.