def _replace_workspaces(self, parameters, user_workspace):

        def replace_in_value(value):
            value_type = type(value)
            if value_type in TYPE_DICT.keys():
                replace_func = TYPE_DICT[value_type]
                new_value = replace_func(value)
                return new_value
            return value

        def replace_in_string(string_value):
            new_string_value = re.sub('\$\(APP_WORKSPACE\)', self.app_workspace.path, string_value)
            new_string_value = re.sub('\$\(USER_WORKSPACE\)', user_workspace.path, new_string_value)
            return new_string_value

        def replace_in_dict(dict_value):
            new_dict_value = dict()
            for key, value in dict_value.iteritems():
                new_dict_value[key] = replace_in_value(value)
            return new_dict_value

        def replace_in_list(list_value):
            new_list_value = [replace_in_value(value) for value in list_value]
            return new_list_value

        def replace_in_tuple(tuple_value):
            new_tuple_value = tuple(replace_in_list(tuple_value))
            return new_tuple_value

        TYPE_DICT = {str: replace_in_string,
                     dict: replace_in_dict,
                     list: replace_in_list,
                     tuple: replace_in_tuple,
                    }

        new_parameters = dict()
        for parameter, value in parameters.iteritems():
            new_value = replace_in_value(value)
            new_parameters[parameter] = new_value
        return new_parameters
First identify strongly connected components, then perform a
dataset/ETHPy150Open tethysplatform/tethys/tethys_compute/job_manager.py/JobManager._replace_workspaces--crossover with--dataset/ETHPy150Open jlisee/xpkg/python/xpkg/util.py/robust_topological_sort