docs: def run(juttle,
          deployment_name,
          program_name=None,
          persist=False,
          token_manager=None,
          app_url=defaults.APP_URL):
      """
      run a juttle program through the juttle streaming API and return the
      various events that are part of running a Juttle program which include:
  
          * Initial job status details including information to associate
            multiple flowgraphs with their individual outputs (sinks):
            {
              "status": "ok",
              "job": {
                "channel_id": "56bde5f0",
                "_start_time": "2015-10-03T06:59:49.233Z",
                "alias": "jut-tools program 1443855588",
                "_ms_begin": 1443855589233,
                "user": "0fbbd98d-cf33-4582-8ca1-15a3d3fee510",
                "timeout": 5,
                "id": "b973bce6"
              },
              "now": "2015-10-03T06:59:49.230Z",
              "stats": ...
              "sinks": [
                {
                  "location": {
                    "start": {
                      "column": 17,
                      "line": 1,
                      "offset": 16
                    },
                    "end": {
                      "column": 24,
                      "line": 1,
                      "offset": 23
                    },
                    "filename": "main"
                  },
                  "name": "table",
                  "channel": "sink237",
                  "options": {
                    "_jut_time_bounds": []
                  }
                },
                ... as many sinks as there are flowgrpahs in your program
              ]
             }
  
          * Each set of points returned along with the indication of which sink
            they belong to:
            {
              "points": [ array of points ],
              "sink": sink_id
            }
  
          * Error event indicating where in your program the error occurred
            {
              "error": true,
              payload with "info" and "context" explaining exact error
            }
  
          * Warning event indicating where in your program the error occurred
            {
              "warning": true,
              payload with "info" and "context" explaining exact warning
            }
  
          * ...
  
      juttle: juttle program to execute
      deployment_name: the deployment name to execute the program on
      persist: if set to True then we won't wait for response data and will
               disconnect from the websocket leaving the program running in
               the background if it is uses a background output
               (http://docs.jut.io/juttle-guide/#background_outputs) and
               therefore becomes a persistent job.
      token_manager: auth.TokenManager object
      app_url: optional argument used primarily for internal Jut testing
      """
      headers = token_manager.get_access_token_headers()
  
      data_url = get_juttle_data_url(deployment_name,
                                     app_url=app_url,
                                     token_manager=token_manager)
  
      websocket = __wss_connect(data_url, token_manager)
  
      data = websocket.recv()
      channel_id_obj = json.loads(data)
  
      if is_debug_enabled():
          debug('got channel response %s', json.dumps(channel_id_obj))
  
      channel_id = channel_id_obj['channel_id']
      juttle_job = {
          'channel_id': channel_id,
          'alias': program_name,
          'program': juttle
      }
  
      response = requests.post('%s/api/v1/jobs' % data_url,
                               data=json.dumps(juttle_job),
                               headers=headers)
  
      if response.status_code != 200:
          yield {
              "error": True,
              "context": response.json()
          }
          return
  
      job_info = response.json()
      # yield job_info so the caller to this method can figure out which sinks
      # correlate to which flowgraphs
      yield job_info
      job_id = job_info['job']['id']
  
      if is_debug_enabled():
          debug('started job %s', json.dumps(job_info))
  
      for data in connect_job(job_id,
                              deployment_name,
                              token_manager=token_manager,
                              app_url=app_url,
                              persist=persist,
                              websocket=websocket,
                              data_url=data_url):
          yield data