limited input file name parsing
There seems to be no expansion of variables, etc on filenames.
E.g. I can't use ~/ or $HOME.

diff --git a/docs/adv_examples/adapt_ta.rst b/docs/adv_examples/adapt_ta.rst
index c333ca06..1a4464ca 100644
--- a/docs/adv_examples/adapt_ta.rst
+++ b/docs/adv_examples/adapt_ta.rst
@@ -4,31 +4,47 @@
 Adaptive applications: Task-attribute
 *************************************
 
-We encourage you to take a look at the Pipeline of Ensembles example on the next page and compare it with the above
-pattern.
+We encourage you to take a look at the Pipeline of Ensembles example on the
+next page and compare it with the above pattern.
 
 .. note:: The reader is assumed to be familiar with the :ref:`PST Model <app_model>` and to have read through the :ref:`introduction` of Ensemble Toolkit.
 
 .. note:: This chapter assumes that you have successfully installed Ensemble Toolkit, if not see :ref:`Installation`.
 
 
-You can download the complete code discussed in this section :download:`here <../../examples/advanced/adapt_ta.py>`
-or find it in your virtualenv under ``share/radical.entk/advanced/scripts``.
+You can download the complete code discussed in this section :download:`here
+<../../examples/advanced/adapt_ta.py>` or find it in your virtualenv under
+``share/radical.entk/advanced/scripts``.
 
-For any adaptive capability within a Pipeline, we need to use the post execution property of a Stage object. Decisions
-can only be performed once all tasks of a Stage are completed as the concurrent tasks cannot be interrupted by design.
-The post execution property of a Stage requires 3 function handles: a function that returns a boolean, a function that is
-executed when the boolean result is True, and a function that is executed when the boolean result is False.
+For any adaptive capability within a Pipeline, we need to use the post
+execution property of a Stage object. Decisions can only be performed once all
+tasks of a Stage reached a final state (running tasks cannot be interrupted by
+design).  The post execution property of a Stage requires a callable function
+that can influence the next stages of a workflow.
 
 .. code-block:: python
 
-    s = Stage()
-    s.post_exec = {
-                    'condition': name of boolean function,
-                    'on_true': function to be executed if boolean result is True,
-                    'on_false': function to be executed if boolean result is False
-                }
+        CUR_NEW_STAGE=0
+        MAX_NEW_STAGE=4
 
+        s1.post_exec = func_post
+
+        def func_post():
+
+            global CUR_NEW_STAGE, MAX_NEW_STAGE
+
+            if CUR_NEW_STAGE <= MAX_NEW_STAGE:
+                CUR_NEW_STAGE += 1
+                s = Stage()
+
+                for i in range(10):
+                    t = Task()
+                    t.executable = '/bin/sleep'
+                    t.arguments = ['30']
+                    s.add_tasks(t)
+
+                s.post_exec = func_condition
+                p.add_stages(s)
 
 
 In the following example, we create 1 Pipeline with five stages. There are 10
@@ -36,7 +52,7 @@ tasks in each Stage, each running 'sleep 30'. After a Stage is DONE (i.e. all
 tasks in the Stage have completed execution), a condition is evaluated that
 checks whether the current stage is less than the max number of stages in the
 Pipeline. If yes, then the arguments of the tasks of the next Stage are
-modified. If not, no operation is performed.
+modified. If not, no operation is performed, and the pipeline will terminate.
 
 
 
diff --git a/docs/adv_examples/adapt_tc.rst b/docs/adv_examples/adapt_tc.rst
index 5b1c2383..78075508 100644
--- a/docs/adv_examples/adapt_tc.rst
+++ b/docs/adv_examples/adapt_tc.rst
@@ -15,26 +15,32 @@ pattern.
 You can download the complete code discussed in this section :download:`here <../../examples/advanced/adapt_tc.py>` or
 find it in your virtualenv under ``share/radical.entk/advanced/scripts``.
 
-For any adaptive capability within a Pipeline, we need to use the post execution property of a Stage object. Decisions
-can only be performed once all tasks of a Stage are completed as the concurrent tasks cannot be interrupted by design.
-The post execution property of a Stage requires 3 function handles: a function that returns a boolean, a function that is
-executed when the boolean result is True, and a function that is executed when the boolean result is False.
+For any adaptive capability within a Pipeline, we need to use the post
+execution property of a Stage object. Decisions can only be performed once all
+tasks of a Stage reached a final state (running tasks cannot be interrupted by
+design).  The post execution property of a Stage requires a callable function
+that can influence the next stages of a workflow.
 
 .. code-block:: python
 
-    s = Stage()
-    s.post_exec = {
-                    'condition': name of boolean function,
-                    'on_true': function to be executed if boolean result is True,
-                    'on_false': function to be executed if boolean result is False
-                }
+        CUR_NEW_STAGE=0
+        MAX_NEW_STAGE=4
 
+        def func_post():
+            if CUR_NEW_STAGE <= MAX_NEW_STAGE:
+                ...
 
+        s = Stage()
+        s.post_exec = func_post
 
-In the following example, we initially create 1 Pipeline with one Stage. There are 10 tasks in the first Stage that each
-runs 'sleep 30'. After the Stage is DONE (i.e. all tasks in the Stage have completed execution), a condition is evaluated
-that checks whether the number of new stages added is less than 4. If yes, we add a new Stage with similar tasks as before
-to the Pipeline. If 4 stages have already been added, no more stages are added.
+
+
+In the following example, we initially create 1 Pipeline with one Stage. There
+are 10 tasks in the first Stage that each runs 'sleep 30'. After the Stage is
+DONE (i.e. all tasks in the Stage have completed execution), a condition is
+evaluated that checks whether the number of new stages added is less than 4. If
+yes, we add a new Stage with similar tasks as before to the Pipeline. If
+4 stages have already been added, no more stages are added.
 
 
 
@@ -42,9 +48,11 @@ to the Pipeline. If 4 stages have already been added, no more stages are added.
 
     python adapt_tc.py
 
-Let's take a look at the complete code in the example. You can generate a more verbose output by setting the environment
-variable ``RADICAL_ENTK_VERBOSE=DEBUG``.
+Let's take a look at the complete code in the example. You can generate a more
+verbose output by setting the environment variable
+``RADICAL_ENTK_VERBOSE=DEBUG``.
 
 A look at the complete code in this section:
 
 .. literalinclude:: ../../examples/advanced/adapt_tc.py
+
diff --git a/docs/adv_examples/adapt_to.rst b/docs/adv_examples/adapt_to.rst
index e6456908..db0dd886 100644
--- a/docs/adv_examples/adapt_to.rst
+++ b/docs/adv_examples/adapt_to.rst
@@ -15,36 +15,43 @@ pattern.
 You can download the complete code discussed in this section :download:`here <../../examples/advanced/adapt_to.py>` or
 find it in your virtualenv under ``share/radical.entk/advanced/scripts``.
 
-For any adaptive capability within a Pipeline, we need to use the post execution property of a Stage object. Decisions
-can only be performed once all tasks of a Stage are completed as the concurrent tasks cannot be interrupted by design.
-The post execution property of a Stage requires 3 function handles: a function that returns a boolean, a function that is
-executed when the boolean result is True, and a function that is executed when the boolean result is False.
+For any adaptive capability within a Pipeline, we need to use the post
+execution property of a Stage object. Decisions can only be performed once all
+tasks of a Stage reached a final state (running tasks cannot be interrupted by
+design).  The post execution property of a Stage requires a callable function
+that can influence the next stages of a workflow.
 
 .. code-block:: python
 
-    s = Stage()
-    s.post_exec = {
-                    'condition': name of boolean function,
-                    'on_true': function to be executed if boolean result is True,
-                    'on_false': function to be executed if boolean result is False
-                }
+        CUR_NEW_STAGE=0
+        MAX_NEW_STAGE=4
 
+        def func_post():
+            if CUR_NEW_STAGE <= MAX_NEW_STAGE:
+                ...
 
+        s = Stage()
+        s.post_exec = func_post
 
-In the following example, we create 1 Pipeline with five stages. There are 10 tasks in each Stage that each run
-'sleep 30'. After a Stage is DONE (i.e. all tasks of the Stage have completed execution), a condition is evaluated
-that checks whether the current stage is less than the max number of stages in the Pipeline. If yes, then the remaining
-stages are shuffled. If not, no operation is performed.
 
 
+In the following example, we create 1 Pipeline with five stages. There are 10
+tasks in each Stage that each run 'sleep 30'. After a Stage is DONE (i.e. all
+tasks of the Stage have completed execution), a condition is evaluated that
+checks whether the current stage is less than the max number of stages in the
+Pipeline. If yes, then the remaining stages are shuffled. If not, no operation
+is performed.
+
 
 .. code-block:: bash
 
     python adapt_to.py
 
-Let's take a look at the complete code in the example. You can generate a more verbose output by setting the environment
-variable ``RADICAL_ENTK_VERBOSE=DEBUG``.
+Let's take a look at the complete code in the example. You can generate a more
+verbose output by setting the environment variable
+``RADICAL_ENTK_VERBOSE=DEBUG``.
 
 A look at the complete code in this section:
 
 .. literalinclude:: ../../examples/advanced/adapt_to.py
+
diff --git a/docs/user_guide/adding_tasks.rst b/docs/user_guide/adding_tasks.rst
index 481cd39a..8e3ec9d3 100644
--- a/docs/user_guide/adding_tasks.rst
+++ b/docs/user_guide/adding_tasks.rst
@@ -29,6 +29,28 @@ and **add** them to the Stage using the **add_task()** method.
 
     python add_tasks.py
 
+.. note:: Individual Task must be created each time in order to treat all the items uniquely inside a Stage. For example,
+          for loop can be used for creating multiple tasks and creating Task object needs to be included inside iteration.
+
+.. code-block:: python
+
+    # Five tasks to be added
+    s = Stage()
+    task_dict = {
+        't.cpu_reqs': {
+        'processes'          : 10,
+        'threads_per_process': 1,
+        'process_type'       : "MPI",
+        'thread_type'        : "OpenMP"
+        }}
+
+    for i in range(5): 
+        task_dict['name']      = "task-{}".format(i)
+        task_dict['arguments'] = ["file-{}".format(i)]
+        # Creating new Task object and adding to Stage at every iteration
+        s.add_tasks(Task(from_dict=task_dict))
+
+    print("Adding shared tasks. Total: {}".format(len(s.tasks)))
 
 Let's take a look at the complete code in the example. You can generate a more verbose output by setting the environment
 variable ``RADICAL_ENTK_VERBOSE=DEBUG``.
diff --git a/examples/advanced/adapt_ta.py b/examples/advanced/adapt_ta.py
index fb53eeaa..2afc005e 100755
--- a/examples/advanced/adapt_ta.py
+++ b/examples/advanced/adapt_ta.py
@@ -15,25 +15,18 @@ MAX_NEW_STAGE=4
 
 def generate_pipeline():
 
-    def func_condition():
+    def func_post():
 
         global CUR_NEW_STAGE, MAX_NEW_STAGE
 
         if CUR_NEW_STAGE <= MAX_NEW_STAGE:
-            func_on_true()
+            CUR_NEW_STAGE += 1
+            for t in p.stages[CUR_NEW_STAGE].tasks:
+                dur = randint(10,30)
+                t.arguments = [str(dur)]
+        else:
+            print('Done')
 
-        func_on_false()
-
-    def func_on_true():
-
-        global CUR_NEW_STAGE
-        CUR_NEW_STAGE += 1
-        for t in p.stages[CUR_NEW_STAGE].tasks:
-            dur = randint(10,30)
-            t.arguments = [str(dur)]
-
-    def func_on_false():
-        print('Done')
 
     # Create a Pipeline object
     p = Pipeline()
@@ -53,7 +46,7 @@ def generate_pipeline():
             s1.add_tasks(t1)
 
         # Add post-exec to the Stage
-        s1.post_exec = func_condition
+        s1.post_exec = func_post
 
         # Add Stage to the Pipeline
         p.add_stages(s1)
diff --git a/examples/advanced/adapt_tc.py b/examples/advanced/adapt_tc.py
index e296f6b5..3efc7190 100755
--- a/examples/advanced/adapt_tc.py
+++ b/examples/advanced/adapt_tc.py
@@ -15,32 +15,22 @@ MAX_NEW_STAGE=4
 
 def generate_pipeline():
 
-    def func_condition():
+    def func_post():
 
         global CUR_NEW_STAGE, MAX_NEW_STAGE
 
         if CUR_NEW_STAGE <= MAX_NEW_STAGE:
-            func_on_true()
 
-        func_on_false()
-
-    def func_on_true():
-
-        global CUR_NEW_STAGE
-
-        CUR_NEW_STAGE += 1
-
-        s = Stage()
-
-        for i in range(10):
-            t = Task()
-            t.executable = '/bin/sleep'
-            t.arguments = [ '30']
-
-            s.add_tasks(t)
+            CUR_NEW_STAGE += 1
+            s = Stage()
+            for i in range(10):
+                t = Task()
+                t.executable = '/bin/sleep'
+                t.arguments  = [ '30']
+                s.add_tasks(t)
 
         # Add post-exec to the Stage
-        s.post_exec = func_condition
+        s.post_exec = func_post
 
         p.add_stages(s)
 
@@ -63,7 +53,7 @@ def generate_pipeline():
         s1.add_tasks(t1)
 
     # Add post-exec to the Stage
-    s1.post_exec = func_condition
+    s1.post_exec = func_post
 
     # Add Stage to the Pipeline
     p.add_stages(s1)
diff --git a/examples/advanced/adapt_to.py b/examples/advanced/adapt_to.py
index cd1b4cc8..1954d706 100755
--- a/examples/advanced/adapt_to.py
+++ b/examples/advanced/adapt_to.py
@@ -15,24 +15,16 @@ MAX_NEW_STAGE=4
 
 def generate_pipeline():
 
-    def func_condition():
+    def func_post():
 
         global CUR_NEW_STAGE, MAX_NEW_STAGE
 
         if CUR_NEW_STAGE <= MAX_NEW_STAGE:
-            func_on_true()
+            CUR_NEW_STAGE += 1
+            shuffle(p.stages[CUR_NEW_STAGE:])
 
-        func_on_false()
-
-    def func_on_true():
-
-        global CUR_NEW_STAGE
-        CUR_NEW_STAGE += 1
-
-        shuffle(p.stages[CUR_NEW_STAGE:])
-
-    def func_on_false():
-        print('Done')
+        else:
+            print('Done')
 
     # Create a Pipeline object
     p = Pipeline()
@@ -52,7 +44,7 @@ def generate_pipeline():
             s1.add_tasks(t1)
 
         # Add post-exec to the Stage
-        s1.post_exec = func_condition
+        s1.post_exec = func_post
 
         # Add Stage to the Pipeline
         p.add_stages(s1)
diff --git a/examples/misc/async_repex.py b/examples/misc/async_repex.py
index 3b7f9993..470de6f6 100755
--- a/examples/misc/async_repex.py
+++ b/examples/misc/async_repex.py
@@ -10,14 +10,6 @@ import radical.utils as ru
 
 t_0 = time.time()
 
-# ------------------------------------------------------------------------------
-#
-def void():
-    # entk needs callables as post_exec conditionals, even if there is nothing
-    # to decide...
-    pass
-
-
 # ------------------------------------------------------------------------------
 #
 class ReplicaExchange(re.AppManager):
@@ -42,10 +34,10 @@ class ReplicaExchange(re.AppManager):
         self._log  = ru.Logger('radical.repex.exc')
         self._dout = open('dump.log', 'a')
 
-        re.AppManager.__init__(self, autoterminate=False, port=5672) 
+        re.AppManager.__init__(self, autoterminate=False, port=5672)
         self.resource_desc = {"resource" : 'local.localhost',
                               "walltime" : 30,
-                              "cpus"     : 16}                                
+                              "cpus"     : 16}
 
         self._replicas = list()
         self._waitlist = list()
@@ -63,7 +55,7 @@ class ReplicaExchange(re.AppManager):
 
         # run the replica pipelines
         self.workflow = set(self._replicas)
-        self.run() 
+        self.run()
 
 
     # --------------------------------------------------------------------------
diff --git a/examples/misc/suspend_pipelines.py b/examples/misc/suspend_pipelines.py
index 32600edf..7107d4a7 100755
--- a/examples/misc/suspend_pipelines.py
+++ b/examples/misc/suspend_pipelines.py
@@ -24,15 +24,20 @@ def generate_pipeline(master=False):
     global pipes
 
     if master:
-        def func_condition_1():
+        def func_post_1():
             for p in pipes[1:]:
                 p.suspend()
-        def func_condition_2():
+
+        def func_post_2():
             for p in pipes[1:]:
                 p.resume()
+            # return list of resumed pipeline IDs
+            return [p.uid for p in pipes[1:]]
+
     else:
-        def func_condition_1(): pass
-        def func_condition_2(): pass
+        def func_post_1(): pass
+        def func_post_2(): pass
+
     # --------------------------------------------------------------------------
 
     # create a pipeline, stage and tasks
@@ -44,7 +49,7 @@ def generate_pipeline(master=False):
 
     s1 = re.Stage()
     s1.add_tasks(t1)
-    s1.post_exec = func_condition_1
+    s1.post_exec = func_post_1
 
     t2 = re.Task()
     t2.executable = '/bin/sleep'
@@ -52,7 +57,7 @@ def generate_pipeline(master=False):
 
     s2 = re.Stage()
     s2.add_tasks(t2)
-    s2.post_exec = func_condition_2
+    s2.post_exec = func_post_2
 
     p = re. Pipeline()
     p.add_stages(s1)
diff --git a/examples/user_guide/add_shared_data.py b/examples/user_guide/add_shared_data.py
index 30d3f4cf..35ddcefc 100755
--- a/examples/user_guide/add_shared_data.py
+++ b/examples/user_guide/add_shared_data.py
@@ -58,8 +58,6 @@ if __name__ == '__main__':
             'cpus': 1
     }
 
-    os.environ['RADICAL_PILOT_DBURL'] = 'mongodb://entk:entk123@ds227821.mlab.com:27821/entk_0_7_0_release'
-
     # Create Application Manager
     appman = AppManager(hostname=hostname, port=port)
 
diff --git a/src/radical/entk/stage/stage.py b/src/radical/entk/stage/stage.py
index 14d14381..810572b4 100644
--- a/src/radical/entk/stage/stage.py
+++ b/src/radical/entk/stage/stage.py
@@ -121,24 +121,43 @@ class Stage(object):
 
         return self._state_history
 
+
     @property
     def post_exec(self):
         '''
-        The post_exec property enables adaptivity in EnTK. A function, func_1,
-        is evaluated to produce a boolean result. Function func_2 is executed
-        if the result is True and func_3 is executed if the result is False.
-        Following is the expected structure:
-
-        self._post_exec = {
-                            |  'condition' : func_1,
-                            |  'on_true'   : func_2,
-                            |  'on_false'  : func_3}
+        The post_exec property enables adaptivity in EnTK. post_exec receives a
+        Python callable object i.e. function, which will be evaluated when a
+        stage is finished.
+
+        Note: if a post_exec callback resumes any suspended pipelines, it MUST
+        return a list with the IDs of those pipelines - otherwise the resume
+        will not be acted upon.
+
+        Example:
+
+        s1.post_exec = func_post
+
+        def func_post():
+
+            if condition is met:
+                s = Stage()
+                t = Task()
+                t.executable = '/bin/sleep'
+                t.arguments = ['30']
+                s.add_tasks(t)
+                p.add_stages(s)
+
+            else:
+                # do nothing
+                pass
         '''
+
         return self._post_exec
 
-    # ------------------------------------------------------------------------------------------------------------------
+
+    # --------------------------------------------------------------------------
     # Setter functions
-    # ------------------------------------------------------------------------------------------------------------------
+    # --------------------------------------------------------------------------
 
     @name.setter
     def name(self, value):
@@ -197,9 +216,11 @@ class Stage(object):
     #
     def add_tasks(self, value):
         """
-        Adds tasks to the existing set of tasks of the Stage
+        Adds task(s) to a Stage by using a set union operation. Every Task
+        element is unique, no duplicate is allowed. Existing Task
+        won't be added but updated with changes.
 
-        :argument: set of tasks
+        :argument: iterable task object
         """
         tasks = self._validate_entities(value)
         self._tasks.update(tasks)
diff --git a/src/radical/entk/task/task.py b/src/radical/entk/task/task.py
index 2ac87ed4..3e33547e 100644
--- a/src/radical/entk/task/task.py
+++ b/src/radical/entk/task/task.py
@@ -305,8 +305,9 @@ class Task(object):
     @property
     def upload_input_data(self):
         '''
-        List of files to be transferred from local machine to the location of
-        the current task on the remote machine.
+        Transfers data (filenames in a list) from a local client (e.g. laptop)
+        to the location of the current task (or data staging area) before it
+        starts.
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -319,8 +320,19 @@ class Task(object):
     @property
     def copy_input_data(self):
         '''
-        List of files to be copied from a location on the remote machine to the
-        location of current task on the remote machine.
+        Copies data (filenames in a list) from another task to a current task
+        (or data staging area) before it starts.
+
+        The following is an example
+
+        ```python
+        t2.copy_input_data =
+        ['$Pipeline_%s_Stage_%s_Task_%s/output.txt'%(p.name,
+        s1.name, t1.name)]
+
+        # output.txt is copied from a t1 task to a current task before it
+        # starts.
+        ```
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -333,8 +345,8 @@ class Task(object):
     @property
     def link_input_data(self):
         '''
-        List of files to be linked from a location on the remote machine to the
-        location of current task on the remote machine.
+        Symlinks data (filenames in a list) from another task to a current task
+        (or data staging area) before it starts.
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -347,8 +359,8 @@ class Task(object):
     @property
     def move_input_data(self):
         '''
-        List of files to be move from a location on the remote machine to the
-        location of current task on the remote machine.
+        Moves data (filenames in a list) from another task to a current task
+        (or data staging area) before it starts.
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -361,8 +373,17 @@ class Task(object):
     @property
     def copy_output_data(self):
         '''
-        List of files to be copied from the location of the current task to
-        another location on the remote machine.
+        Copies data (filenames in a list) from a current task to another task
+        (or data staging area) when a task is finished.
+
+        The following is an example
+
+        ```python
+        t.copy_output_data = [ 'results.txt > $SHARED/results.txt' ]
+
+        # results.txt is copied to a data staging area `$SHARED` when a task is
+        # finised.
+        ```
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -375,8 +396,8 @@ class Task(object):
     @property
     def link_output_data(self):
         '''
-        List of files to be linked from the location of current task on the
-        remote machine to a location on the remote machine.
+        Symlins data (filenames in a list) from a current task to another task
+        (or data staging area) when a task is finished.
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -389,8 +410,8 @@ class Task(object):
     @property
     def move_output_data(self):
         '''
-        List of files to be copied from the location of the current task to
-        another location on the remote machine.
+        Moves data (filenames in a list) from a current task to another task
+        (or data staging area) when a task is finished.
 
         :getter: return the list of files
         :setter: assign the list of files
@@ -403,8 +424,18 @@ class Task(object):
     @property
     def download_output_data(self):
         '''
-        List of files to be downloaded from the location of the current task to
-        a location on the local machine.
+        Downloads data (filenames in a list) from a current task to a local
+        client (e.g. laptop) when a task is finished.
+
+        The following is an example
+
+        ```python
+        t.download_output_data = [ 'results.txt' ]
+
+        # results.txt is transferred to a local client (e.g. laptop) when a
+        # current task finised.
+        ```
+
 
         :getter: return the list of files
         :setter: assign the list of files
['docs/user_guide/adding_tasks.rst', 'docs/adv_examples/adapt_to.rst', 'src/radical/entk/task/task.py', 'examples/advanced/adapt_tc.py', 'docs/adv_examples/adapt_tc.rst', 'examples/misc/suspend_pipelines.py', 'examples/advanced/adapt_ta.py', 'src/radical/entk/stage/stage.py', 'examples/advanced/adapt_to.py', 'docs/adv_examples/adapt_ta.rst', 'examples/user_guide/add_shared_data.py', 'examples/misc/async_repex.py']