diff --git a/compute_sdk/globus_compute_sdk/errors/error_types.py b/compute_sdk/globus_compute_sdk/errors/error_types.py index 47c5d35f8..a4ce95aa6 100644 --- a/compute_sdk/globus_compute_sdk/errors/error_types.py +++ b/compute_sdk/globus_compute_sdk/errors/error_types.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re import textwrap import time @@ -70,11 +71,31 @@ def __str__(self) -> str: ) +SERDE_TASK_EXECUTION_FAILED_HELP_MESSAGE = """ + +This appears to be an error with serialization. If it is, using a different +serialization strategy from globus_compute_sdk.serialize might resolve the issue. For +example, to use globus_compute_sdk.serialize.CombinedCode: + + from globus_compute_sdk import Client, Executor + from globus_compute_sdk.serialize import CombinedCode + + gcc = Client(code_serialization_strategy=CombinedCode()) + with Executor('', client=gcc) as gcx: + # do something with gcx + +For more information, see: + https://globus-compute.readthedocs.io/en/latest/sdk.html#specifying-a-serialization-strategy +""" + + class TaskExecutionFailed(Exception): """ Error result from the remote end, wrapped as an exception object """ + SERDE_REGEX = re.compile("dill|pickle|serializ", re.IGNORECASE) + def __init__( self, remote_data: str, @@ -87,4 +108,8 @@ def __init__( self.completion_t = completion_t or str(time.time()) def __str__(self) -> str: - return "\n" + textwrap.indent(self.remote_data, " ") + remote_data = textwrap.indent(self.remote_data, " ") + message = "\n" + remote_data + if re.search(TaskExecutionFailed.SERDE_REGEX, remote_data): + message += SERDE_TASK_EXECUTION_FAILED_HELP_MESSAGE + return message diff --git a/compute_sdk/tests/unit/test_error_types.py b/compute_sdk/tests/unit/test_error_types.py new file mode 100644 index 000000000..59e6575bc --- /dev/null +++ b/compute_sdk/tests/unit/test_error_types.py @@ -0,0 +1,27 @@ +import traceback +from functools import lru_cache + +import pytest +from globus_compute_sdk.errors import TaskExecutionFailed +from globus_compute_sdk.serialize import DillCodeSource + + +@lru_cache(maxsize=None) +def annotated_function(): + return "data" + + +def test_task_execution_failed_serialization_help_msg(): + try: + DillCodeSource().serialize(annotated_function) + except OSError: + tb = traceback.format_exc() + else: + pytest.fail("Expected DillCodeSource to fail to serialize annotated functions") + + tef = TaskExecutionFailed(tb) + assert "This appears to be an error with serialization." in str(tef) + assert ( + "https://globus-compute.readthedocs.io/en/latest/sdk.html" + "#specifying-a-serialization-strategy" in str(tef) + )