Repository: Parsl/parsl

Issue:
Make parsl.load() load the thread pool config
We currently begin the user guide with a discussion of apps, futures, etc, but do not show a complete example (including the configuration) until significantly later in the documentation. I think it is reasonable to wait until later for a detailed discussion of config options, but in that case, we should consider removing the DFK from the examples and loading a default one (`ThreadPoolExecutor`) if none has been loaded.


Discussion:
I'm changing the name to clarify this proposal. The proposal is to load a default DFK if none has been loaded. The motivation for doing so is so that we can show a complete example of a simple python app earlier in the documentation; to start with running simple apps instead of start by talking about configs.
parsl.load() requires a config. We should make a default config so that parsl.load() works. 

Resolving patch:
diff --git a/parsl/dataflow/dflow.py b/parsl/dataflow/dflow.py
--- a/parsl/dataflow/dflow.py
+++ b/parsl/dataflow/dflow.py
@@ -30,7 +30,6 @@
 from parsl.dataflow.states import States, FINAL_STATES, FINAL_FAILURE_STATES
 from parsl.dataflow.usage_tracking.usage import UsageTracker
 from parsl.utils import get_version
-from parsl.app.errors import RemoteException
 from parsl.monitoring.db_logger import get_db_logger
 from parsl.monitoring import app_monitor
 from parsl.monitoring import logging_server
@@ -101,10 +100,19 @@ def __init__(self, config=Config()):
             self.db_logger = get_db_logger()
         else:
             self.db_logger = get_db_logger(monitoring_config=self.monitoring_config)
-        self.workflow_name = os.path.basename(str(inspect.stack()[1][1]))
-        self.workflow_version = None
+        self.workflow_name = None
         if self.monitoring_config is not None and self.monitoring_config.workflow_name is not None:
             self.workflow_name = self.monitoring_config.workflow_name
+        else:
+            for frame in inspect.stack():
+                fname = os.path.basename(str(frame.filename))
+                parsl_file_names = ['dflow.py']
+                # Find first file name not considered a parsl file
+                if fname not in parsl_file_names:
+                    self.workflow_name = fname
+                    break
+
+        self.workflow_version = None
         if self.monitoring_config is not None and self.monitoring_config.version is not None:
             self.workflow_version = self.monitoring_config.version
         self.time_began = time.time()
@@ -931,7 +939,7 @@ def clear(cls):
         cls._dfk = None
 
     @classmethod
-    def load(cls, config):
+    def load(cls, config=None):
         """Load a DataFlowKernel.
 
         Args:
@@ -942,7 +950,11 @@ def load(cls, config):
         """
         if cls._dfk is not None:
             raise RuntimeError('Config has already been loaded')
-        cls._dfk = DataFlowKernel(config)
+
+        if config is None:
+            cls._dfk = DataFlowKernel(Config())
+        else:
+            cls._dfk = DataFlowKernel(config)
 
         return cls._dfk
 


Test patch:
diff --git a/parsl/tests/test_python_apps/test_parsl_load_default_config.py b/parsl/tests/test_python_apps/test_parsl_load_default_config.py
new file mode 100644
--- /dev/null
+++ b/parsl/tests/test_python_apps/test_parsl_load_default_config.py
@@ -0,0 +1,24 @@
+import parsl
+from parsl import *
+
+dfk = parsl.load()
+
+
+@App('python', dfk)
+def cpu_stress(inputs=[], outputs=[]):
+    s = 0
+    for i in range(10**8):
+        s += i
+    return s
+
+
+def test_parsl_load_default_config():
+    a1, b1 = [cpu_stress(),
+              cpu_stress()]
+    a1.result()
+    b1.result()
+    dfk.cleanup()
+
+
+if __name__ == '__main__':
+    test_parsl_load_default_config()