-
Notifications
You must be signed in to change notification settings - Fork 179
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
feat(api): add InstrumentContext.load_name and update LiquidClass.get_for() #17289
base: edge
Are you sure you want to change the base?
Conversation
Don't we already consistently call it |
"""Get liquid class transfer properties for the specified pipette and tip.""" | ||
from . import InstrumentContext, Labware |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we just import this at the top of the file (and get rid of the if TYPE_CHECKING
bit)?
You are clearly using the symbols InstrumentContext
and Labware
in your implementation (versus only importing it for the typechecker), so why not treat it as a normal import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding to this, I can see limited use of getting liquid class properties without having to provide the names, but I'd almost rather that be it's own function which would allow us to remove this internal import. That or we could always flip around the isinstance
to check for str instead of InstrumentContext
or Labware
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we just import this at the top of the file (and get rid of the if TYPE_CHECKING bit)?
Because it results in a circular import for InstrumentContext
. InstrumentContext
already imports from _liquid
.
I can see limited use of getting liquid class properties without having to provide the names, but I'd almost rather that be it's own function
Not sure I understand. Can you elaborate?
That or we could always flip around the isinstance to check for str instead of InstrumentContext or Labware
If we want to verify that the args are not of some third, unsupported type then we will have to check if isinstance
of InstrumentContext
and Labware
. Sure we can maybe check that if it's not a string and if there's an error doing pipette.load_name
or tiprack.uri
, the args are wrong. But it's not as foolproof as doing isinstance
checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TY! Looks good except for a possible GEN1/GEN2 cross-compatibility thing.
@@ -64,18 +67,42 @@ def name(self) -> str: | |||
def display_name(self) -> str: | |||
return self._display_name | |||
|
|||
def get_for(self, pipette: str, tiprack: str) -> TransferProperties: | |||
def get_for( | |||
self, pipette: Union[str, InstrumentContext], tiprack: Union[str, Labware] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: "tip rack" is two words, so can we name the argument tip_rack
instead of tiprack
?
def get_load_name(self) -> str: | ||
"""Get the pipette's requested API load name. | ||
|
||
For OT-2 pipettes, this is the same as pipette name. | ||
""" | ||
return self.get_hardware_state()["name"] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For OT-2 pipettes, this is the same as pipette name.
Not always, I don't think. What about GEN1/GEN2 cross-compatibility? If a protocol requests p300_single
but gets a p300_single_gen2
, I'd expect load_name
to return p300_single
. I think this get_hardware_state()
-based implementation will return p300_single_gen2
.
I don't have a robot in front of me to test this, so feel free to dismiss this change request if I'm wrong about this.
@abstractmethod | ||
def get_load_name(self) -> str: | ||
"""Get the pipette's requested API load name. | ||
|
||
This is the load name that is specified in the `ProtocolContext.load_instrument()` | ||
method. This name might differ from the engine-specific pipette name. | ||
""" | ||
... | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your call, but I wonder if this is easier to implement directly in InstrumentContext
instead of in the InstrumentCore
s.
MAX_SUPPORTED_VERSION = APIVersion(2, 22) | ||
MAX_SUPPORTED_VERSION = APIVersion(2, 23) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making sure you mean to have this in this PR?
Closes AUTH-1295, AUTH-1299
Overview
InstrumentContext.load_name
to fetch the python API load name of a pipetteLiquidClass.get_for()
to accept the a loaded instrument object and loaded tiprack object forpipette
andtiprack
args respectively.Test Plan and Hands on Testing
Added unit and integration tests
Review requests
LiquidClass.get_for()
method will still accept the pipette name and tiprack URI as arguments. This is to allow fetching liquid class properties without needing to load pipettes and tipracks. Let me know if this is not a good ideaInstrumentContext.load_name
? I want to avoid any confusion with the existingname
property and this new propertyRisk assessment
None