-
Notifications
You must be signed in to change notification settings - Fork 31
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
Detect and display non-zero returncode from scripts #474
Conversation
This pull request has been mentioned on Image.sc Forum. There might be relevant details there: |
omeroweb/webclient/views.py
Outdated
if cb.returncode != 0: | ||
# This 'error' shows failure icon | ||
kwargs["error"] = 1 | ||
kwargs["Message"] = "Script failed with Exception" |
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.
Should this not just be kwargs["error"] = ...
Also, I could see adding the return code into the message unobstruvisely, e.g.:
f"Script exited with failure. (rc={{ cb.returnCode }})"
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 is kwargs["error"] = ...
?
Do you mean kwargs["error"] = cb.returncode
?
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
Interesting thread which incidentally raises the question: what the recommendation should be for handling and communicating failures in OMERO.scripts? At the moment, the primary relevant place I found in the reference documentation suggests failures may be handled via client output message - see https://omero.readthedocs.io/en/stable/developers/scripts/style-guide.html#script-outputs Using the official
|
@sbesson Thanks for the review. I guess we can't currently have the script raise an Exception (to get the I would prefer not to add another convention (on top of the "Message" convention) for errors, so I think that raising an Exception should be the best way to indicate "Failure". |
omeroweb/webclient/views.py
Outdated
# check if we get something back from the handle... | ||
if cb.block(0): # ms. | ||
cb.close() | ||
try: | ||
# we can only retrieve this ONCE - must save results | ||
results = proc.getResults(0, conn.SERVICE_OPTS) | ||
update_callback(request, cbString, status="finished") | ||
kwargs = { | ||
"status": ("finished" if cb.returncode == 0 else "failed"), |
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.
I initially thought that this key was reflecting the process termination state i.e. the enums defined in https://github.com/ome/omero-py/blob/d5ca72f930d85ee1f147f9f8e3cfd1c95c8089ae/src/omero/callbacks.py#L62-L64 but looking at the code, we seem to have additional state e.g. in-progress, failed etc
Do we have a list of all supported statuses with their meaning?
In that case, I suspect finished
must be interpreted as finished with a zero return code
. Note this is a more restrictive interpretation than https://docs.openmicroscopy.org/omero-blitz/5.6.2/slice2html/omero/grid/ProcessCallback.html#processFinished.
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.
From testing in omero-figure, that app is using the "finished"
status to know when the figure export script is done. Without it, the spinner keeps on spinning and the stderr isn't displayed.
So, best not to change this if we can help it.
omeroweb/webclient/views.py
Outdated
} | ||
if cb.returncode != 0: | ||
# This 'error' shows failure icon | ||
kwargs["error"] = 1 |
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.
Reading the code, if return code is non-zero, there are currently three keys which have updated values (failure
, status
and error
). Are these all necessary?
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.
failure
isn't used anywhere so I'll remove it.
The error
flag is a boolean, so we could remove it and add set status = "error"
for scripts.
kwargs["Message"] = ( | ||
f"Script exited with failure." | ||
f" (returncode={ cb.returncode })" | ||
) |
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 would happen if a script first set a message output via client.setOutput
and then terminate with a non-zero return code?
Should we handle this use case and respect the message sent by the script and use this as the default error is unset?
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.
@sbesson Just returning to this... In my testing, if the script does client.setOutput(....)
then generates some un-caught exception and terminates, the output is not passed on to the server. I don't see it in the code at
omero-web/omeroweb/webclient/views.py
Line 3822 in d5e4f84
for key, value in results.items(): |
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.
Apologies - made a mistake in my client.setOutput("Message"...)
. That is actually handled OK and is displayed in place of the error message:
However, most scripts don't try to return a "Message" until the end, so it's likely that if a script fails with some uncaught exception then the "Message" won't have been set.
@will-moore following up on the questions from #474 (comment), would it be possible to either update the description of this PR or add a comment with the different types of scenarios that should be tested and the expected outcome of the |
@sbesson I've updated the PR description. Hope that contains everything you need? |
Thanks @will-moore for adjusting the description. As per the previous discussion, I am still questioning the added value of the new Also re #474 (comment), has the proposal of storing the value of the return code in |
OK - yes, apologies. I'll do that... |
@sbesson Use key |
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.
Tested with a minimal script
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import omero.scripts as scripts
from omero.gateway import BlitzGateway
from omero.rtypes import rstring
def run_script():
client = scripts.client(
'test_failure.py',
"""Test""",
scripts.Bool(
"Fail", optional=False, grouping="1", default="False"),
scripts.String(
"Message", optional=True, grouping="2",
description="The message to be sent to the client."),
)
try:
conn = BlitzGateway(client_obj=client)
script_params = client.getInputs(unwrap=True)
if "Message" in script_params:
client.setOutput("Message", rstring(script_params["Message"]))
if script_params["Fail"]:
raise Exception("This should fail the script")
finally:
client.closeSession()
if __name__ == "__main__":
run_script()
After running the script with various conditions of failures/messages
The underlying changes should remain backwards-compatible for existing apps which would rely on the context and make the return code available.
Overall, communicating a non-zero return code is definitely useful and I think this change is safe for inclusion in the next minor release of OMERO.web.
This uses the
returncode
returned from running scripts to show the Error icon in Activities dialog:Feature requested at https://forum.image.sc/t/omero-scripts-fail-icon/81495
To test:
client.setOutput("Message", rstring("OK so far..."))
returncode
from the failure.The
context
used to render the html page in the example above looks like this: