Validates task and adds default values for missing options using the
    following steps.

    1. If there is no input list specified or if it is None, the input spec is
       assumed to be ['*'].

    2. If there are not outputs specified, or if the output spec is None or an
       empty list, the output spec is assumed to be ['*'].

    3. If the input or output spec is not iterable, they are converted into
       single element tuples. If they are any iterable, they are converted into
       tuples.

    4. The task['fn'] option must be callable.

    5. If number of outputs is more than one, task['fn'] must be a generator
       function.

    6. Generator functions are not supported for output spec of '*'.

    Returns new task with updated options

def validate_task(original_task):
    """
    Validates task and adds default values for missing options using the
    following steps.

    1. If there is no input list specified or if it is None, the input spec is
       assumed to be ['*'].

    2. If there are not outputs specified, or if the output spec is None or an
       empty list, the output spec is assumed to be ['*'].

    3. If the input or output spec is not iterable, they are converted into
       single element tuples. If they are any iterable, they are converted into
       tuples.

    4. The task['fn'] option must be callable.

    5. If number of outputs is more than one, task['fn'] must be a generator
       function.

    6. Generator functions are not supported for output spec of '*'.

    Returns new task with updated options
    """
    task = original_task._asdict()

    # Default values for inputs and outputs
    if 'inputs' not in task or task['inputs'] is None:
        task['inputs'] = ['*']

    # Outputs list cannot be empty
    if ('outputs' not in task or
        task['outputs'] is None or
            len(task['outputs']) == 0):
        task['outputs'] = ['*']

    # Convert to tuples (even for single values)
    if not hasattr(task['inputs'], '__iter__') or isinstance(task['inputs'], str):
        task['inputs'] = (task['inputs'],)
    else:
        task['inputs'] = tuple(task['inputs'])

    if not hasattr(task['outputs'], '__iter__') or isinstance(task['outputs'], str):
        task['outputs'] = (task['outputs'],)
    else:
        task['outputs'] = tuple(task['outputs'])

    if not callable(task['fn']):
        raise TypeError('Task function must be a callable object')

    if (len(task['outputs']) > 1 and
            not inspect.isgeneratorfunction(task['fn'])):
        raise TypeError('Multiple outputs are only supported with \
                        generator functions')

    if inspect.isgeneratorfunction(task['fn']):
        if task['outputs'][0] == '*':
            raise TypeError('Generator functions cannot be used for tasks with \
                             output specification "*"')
    return Task(**task)