-
Notifications
You must be signed in to change notification settings - Fork 178
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 v4 JSON executor #5221
Conversation
…3-executor-test branch)
Codecov Report
@@ Coverage Diff @@
## edge #5221 +/- ##
=======================================
Coverage 62.14% 62.14%
=======================================
Files 1054 1054
Lines 30225 30225
=======================================
Hits 18784 18784
Misses 11441 11441 Continue to review full report at Codecov.
|
) * create system/wifi module and move some functions from server/endpoints/networking there. * more refactoring * code clean up and restructuring. * move eap option validation from network endpoints to wifi. rewrote test_key_lifecycle to test the key api. not the http api. * reworked test_networking_endpoints to only test the http interaction with the key functions. Not the underlying file system. That belongs in the test_wifi module. * test_network_status added to nmcli. this didn't belong in the server endpoint tests as it is really testing our ability to communicate with nmcli. * remove deprecated comment * start robot_server networking endpoints * progress * keys is a reserved word. use an alias. * list keys tests pass * networking tests pass minus the disconnect * disconnect tests * tests for wificonfiguration model validation * add todo note regarding wifi disconnect * fix lint errors * cannot import log_control.MAX_RECORDS due to syslog import failure. * clean up the instances of multiple response types. * rename V1ErrorResponse to V1BasicResponse. It isn't always used for errors. Name was misleading. * fix bad test * fix lint error * fix bugs that were revealed when running on PI. Configure didn't work because we weren't testing how the nmcli.configure call was made. get wifi/keys failed due to validation errors on pydantic model due to attribute named keys. also, someone (me) didn't port the aiohttp unit tests properly. closes #5143
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.
Preliminary change requests to make this a bit more idiomatic python and support cancel
return modules_by_id | ||
|
||
|
||
def _engage_magnet(modules, params) -> None: |
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.
We should type the args here. It may be a good idea to make a LoadedModules
type variable so we don't have to have Dict[str, ModuleContext]
or whatever there all the time
# while holding, because the temperature delta will be exceeded. | ||
# when this flicker happens, this function would sleep for a moment longer | ||
|
||
if status == 'heating': |
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.
We should push this logic down all the way to the hardware_control.modules.TemperatureModule
, so cancelling works here.
The way cancel is currently implemented is in the execution manager in hardware control with an asyncio condition wrapping a state that can be running, paused, or cancelling. When you call a hardware control function that checks the condition (or one of the whitelisted ones for cancellation), you can be cancelled.
As this code stands, the cancellation won't actually happen here - you could be awaiting for a very long time, especially if there's an error in the tempdeck communications.
Making a tempdeck.await_temperature(target: float)
function will fix this. We can register it as cancellable with the execution manager, which means it will get cancelled when a cancel happens; or we can implement some more complex logic that pairs monitoring the condition with awaiting the temperature.
The other open question is, what's supposed to happen to the protocol state when this is running? How does it interact with pause? This is as much a UX question as a technical question (@howisthisnamenottakenyet ).
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.
Eek, forgot about cancel. I'm fine with moving this down to the module level, that means we're exposing another "hidden" thing to the module context though. But I guess there isn't really another option.
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.
it's really of equal status to the other one though - they come as a pair.
Honestly it's reasonable at this point to unhide it - we wanted to keep it hidden because you could set the temperature, but waiting for it wasn't exposed. If properly waiting for it is exposed, we might as well have it be part of the python api. What do you think @pantslakz and @howisthisnamenottakenyet
asyncio.sleep(0.2) | ||
|
||
|
||
dispatcher_map: Dict[Any, Any] = { |
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.
This map and the code in dispatch_json
looks like it will work, but I'd prefer to avoid magic strings in favor of enums - it's a bit easier to type systematically, since we don't have literal types (yet) in mypy. In addition, python enums can have arbitrary objects as values, so you could have something like
class JsonCommandHandler(NamedTuple): # could also be a typed generic passed down to the handler element (see above re: C++ brain)
name: str
handler: Callable[] # appropriately type
class JsonCommand:
"delay": JsonCommandHandler(...)
'Valid names (ignoring case): ' | ||
'"' + '", "'.join(alias_map.keys()) + '"') | ||
'Valid names (ignoring case): ''"' + '", "' | ||
.join(model_map.keys()) + '", "' + '", "' |
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.
This is intended to be a literate error for python protocols; it may be better to avoid mentioning the model_map
at all, or to explicitly mention it as a lesser alternative, something like:
"Valid names (ignoring case): {alias_map.keys()}
You can also refer to modules by their exact model: {model_map.keys()}"
@@ -232,6 +232,16 @@ def target(self): | |||
""" Current target temperature in C""" | |||
return self._module.target | |||
|
|||
@property # type: ignore | |||
@requires_version(2, 0) |
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.
This should require version 2.3, since it will be new in 2.3. Also, changes or additions to api-exposed methods should be accompanied with a change note in the version docs
Closes #5117 * refactor add/select step selectors for mocking, and add tests
|
||
t = self._loop.create_task(_await_temperature(awaiting_temperature)) | ||
await self.make_cancellable(t) | ||
return await t |
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.
what does this return? if it's nothing, we don't need to return
; if it's something, we should annotate the return type in both the inner closure and the wrapper
status = self.status | ||
|
||
if status == 'heating': | ||
while (self.temperature < awaiting_temperature): |
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.
unnecessary parens
asyncio.sleep(0.2) | ||
|
||
elif status == 'cooling': | ||
while (self.temperature > awaiting_temperature): |
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.
unnecessary parens
Clear out engageHeight from MAGNET steps when magnetic module model is edited. Closes #5225
…api (#5252) * robot endpoint progress: home, light, and position implemented with unittests. * add test for mount with z too low to aiohttp * move api implemented and unit tested. moved camera into its own router. * lint issues fixed * move ThreadAsyncLock into hardware_control package. * rename to threaded_async_lock and at it to hardware_control export * use ThreadedAsyncLock in home and move handlers. * fix lint errors * add model validator tests. more clean up. closes #5191
This commit make a new function _do_plunger_home which homes a plunger on a mount, if it exists, and then moves that plunger to its configured bottom. This is now used both by API.home_plunger (which was where this behavior was before) but also by a call to API.home() that involves pipettes, ensuring that plungers are always moved to the bottom after they are homed. Closes #5164
This reverts commit 9cb4940.
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.
LGTM once qa approves. In the future we probably shouldn't merge edge back into longstanding branches though, it really makes a mess of the diff.
Yeah that's my bad. I saw there was a conflict in the versioning notes so I thought I would merge and fix, but it really just made the tree unintelligible |
overview
This PR closes #4868 by adding the v4 JSON executor to the api
changelog
review requests
start_set_temperature
andawait_temperature
commands.Regression test that protocols that do not use modules still behave as expectedNevermind if you export a protocol without modules it will export as a v3 protocol, and therefore use the v3 executor