Repository: Parsl/parsl

Issue:
Clarify AppBadFormatting error
As reported by @madduri.

The error message raised on badly formatted bash apps is not clear. This is slightly better for threads than IPP, but both are not as helpful as they should be. We need to make sure the error message the user sees is actually formatted with the info we want to provide. Also, we should add more info: all of the args, kwargs, template, etc.

With IPP:
```
Traceback (most recent call last):
  File "/Users/awoodard/ci/parsl/parsl/dataflow/dflow.py", line 187, in handle_update
    res = future.result()
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/_base.py", line 398, in result
    return self.__get_result()
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/_base.py", line 357, in __get_result
    raise self._exception
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/site-packages/ipyparallel/client/asyncresult.py", line 224, in _resolve_result
    raise r
ipyparallel.error.RemoteError: AppBadFormatting()
```

With threads:
```
Traceback (most recent call last):
  File "/Users/awoodard/ci/parsl/parsl/app/bash.py", line 34, in remote_side_bash_executor
    executable = partial_cmdline.format(*args, **kwargs)
IndexError: tuple index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test_bash_apps/test_error_codes.py", line 184, in <module>
    test_bash_formatting()
  File "test_bash_apps/test_error_codes.py", line 76, in test_bash_formatting
    f.result()
  File "/Users/awoodard/ci/parsl/parsl/dataflow/futures.py", line 117, in result
    res = self.parent.result(timeout=timeout)
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/_base.py", line 405, in result
    return self.__get_result()
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/_base.py", line 357, in __get_result
    raise self._exception
  File "/Users/awoodard/ci/parsl/parsl/dataflow/dflow.py", line 187, in handle_update
    res = future.result()
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/_base.py", line 398, in result
    return self.__get_result()
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/_base.py", line 357, in __get_result
    raise self._exception
  File "/Users/awoodard/software/anaconda3/envs/parsl_py36/lib/python3.6/concurrent/futures/thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/Users/awoodard/ci/parsl/parsl/app/bash.py", line 43, in remote_side_bash_executor
    raise pe.AppBadFormatting("[{}] App formatting failed during cmd_line resolution: {}".format(func_name, e), None)
parsl.app.errors.AppBadFormatting
```


Discussion:

Resolving patch:
diff --git a/parsl/app/bash.py b/parsl/app/bash.py
--- a/parsl/app/bash.py
+++ b/parsl/app/bash.py
@@ -35,14 +35,14 @@ def remote_side_bash_executor(func, *args, **kwargs):
 
     except AttributeError as e:
         if partial_cmdline:
-            raise pe.AppBadFormatting("[{}] App formatting failed during cmd_line resolution: {}".format(func_name, e), None)
+            raise pe.AppBadFormatting("App formatting failed for app '{}' with AttributeError: {}".format(func_name, e), None)
         else:
-            raise pe.BashAppNoReturn("[{}] Bash App returned NoneType, must return str object".format(func_name), None)
+            raise pe.BashAppNoReturn("Bash app '{}' returned NoneType, must return string object".format(func_name), None)
 
     except IndexError as e:
-        raise pe.AppBadFormatting("[{}] App formatting failed during cmd_line resolution: {}".format(func_name, e), None)
+        raise pe.AppBadFormatting("App formatting failed for app '{}' with IndexError: {}".format(func_name, e), None)
     except Exception as e:
-        logging.error("[{}] Caught exception during cmd_line resolution: {}".format(func_name, e))
+        logging.error("Caught exception during formatting of app '{}': {}".format(func_name, e))
         raise e
 
     logging.debug("Executable: %s", executable)
diff --git a/parsl/app/errors.py b/parsl/app/errors.py
--- a/parsl/app/errors.py
+++ b/parsl/app/errors.py
@@ -41,7 +41,7 @@ class AppBadFormatting(ParslError):
     """
 
     def __init__(self, reason, exitcode, retries=None):
-        super().__init__()
+        super().__init__(reason)
         self.reason = reason
         self.exitcode = exitcode
         self.retries = retries
@@ -58,7 +58,7 @@ class AppFailure(AppException):
     """
 
     def __init__(self, reason, exitcode, retries=None):
-        super().__init__()
+        super().__init__(reason)
         self.reason = reason
         self.exitcode = exitcode
         self.retries = retries
@@ -74,7 +74,7 @@ class AppTimeout(AppException):
     """
 
     def __init__(self, reason, exitcode, retries=None):
-        super().__init__()
+        super().__init__(reason)
         self.reason = reason
         self.exitcode = -55
         self.retries = retries
@@ -90,7 +90,7 @@ class BashAppNoReturn(AppException):
     """
 
     def __init__(self, reason, exitcode, retries=None):
-        super().__init__()
+        super().__init__(reason)
         self.reason = reason
         self.exitcode = -21
         self.retries = retries
@@ -105,7 +105,7 @@ class MissingOutputs(ParslError):
     """
 
     def __init__(self, reason, outputs):
-        super().__init__()
+        super().__init__(reason)
         self.reason = reason
         self.outputs = outputs
 
@@ -147,7 +147,7 @@ class DependencyError(ParslError):
     """
 
     def __init__(self, dependent_exceptions, reason, outputs):
-        super().__init__()
+        super().__init__(reason)
         self.dependent_exceptions = dependent_exceptions
         self.reason = reason
         self.outputs = outputs


Test patch: