Start a workflow by given name for specified data.

    The name of the workflow to start is considered unique and it is
    equal to the name of a file containing the workflow definition.

    The data passed could be a list of Python standard data types such as
    strings, dict, integers etc. to run through the workflow. Inside the
    workflow tasks, this data is then available through ``obj.data``.

    Or alternatively, pass the WorkflowObject to work on via
    ``object_id`` parameter. NOTE: This will replace any value in ``data``.

    This is also a Celery (http://celeryproject.org) task, so you can
    access the ``start.delay`` function to enqueue the execution of the
    workflow asynchronously.

    :param workflow_name: the workflow name to run. Ex: "my_workflow".
    :type workflow_name: str

    :param data: the workflow name to run. Ex: "my_workflow" (optional if
        ``object_id`` provided).
    :type data: tuple

    :param object_id: id of ``WorkflowObject`` to run (optional).
    :type object_id: int

    :return: UUID of the workflow engine that ran the workflow.

def start(workflow_name, data=None, object_id=None, **kwargs):
    """Start a workflow by given name for specified data.

    The name of the workflow to start is considered unique and it is
    equal to the name of a file containing the workflow definition.

    The data passed could be a list of Python standard data types such as
    strings, dict, integers etc. to run through the workflow. Inside the
    workflow tasks, this data is then available through ``obj.data``.

    Or alternatively, pass the WorkflowObject to work on via
    ``object_id`` parameter. NOTE: This will replace any value in ``data``.

    This is also a Celery (http://celeryproject.org) task, so you can
    access the ``start.delay`` function to enqueue the execution of the
    workflow asynchronously.

    :param workflow_name: the workflow name to run. Ex: "my_workflow".
    :type workflow_name: str

    :param data: the workflow name to run. Ex: "my_workflow" (optional if
        ``object_id`` provided).
    :type data: tuple

    :param object_id: id of ``WorkflowObject`` to run (optional).
    :type object_id: int

    :return: UUID of the workflow engine that ran the workflow.
    """
    from .proxies import workflow_object_class
    from .worker_engine import run_worker

    if data is None and object_id is None:
        raise WorkflowsMissingData("No data or object_id passed to task.ß")

    if object_id is not None:
        obj = workflow_object_class.get(object_id)
        if not obj:
            raise WorkflowsMissingObject(
                "Cannot find object: {0}".format(object_id)
            )
        data = [obj]
    else:
        if not isinstance(data, (list, tuple)):
            data = [data]

    return text_type(run_worker(workflow_name, data, **kwargs).uuid)