code: def query(self, query, archiver="", timeout=DEFAULT_TIMEOUT):
          
          if archiver == "":
              archiver = self.archivers[0]
  
          nonce = random.randint(0, 2**32)
          ev = threading.Event()
          response = {}
          def _handleresult(msg):
              # decode, throw away if not correct nonce
              got_response = False
              error = getError(nonce, msg)
              if error is not None:
                  got_response = True
                  response["error"] = error
  
              metadata = getMetadata(nonce, msg)
              if metadata is not None:
                  got_response = True
                  response["metadata"] = metadata
  
              timeseries = getTimeseries(nonce, msg)
              if timeseries is not None:
                  got_response = True
                  response["timeseries"] = timeseries
  
              if got_response:
                  ev.set()
  
          vk = self.vk[:-1] # remove last part of VK because archiver doesn't expect it
  
          # set up receiving
          self.c.subscribe("{0}/s.giles/_/i.archiver/signal/{1},queries".format(archiver, vk), _handleresult)
  
          # execute query
          q_struct = msgpack.packb({"Query": query, "Nonce": nonce})
          po = PayloadObject((2,0,8,1), None, q_struct)
          self.c.publish("{0}/s.giles/_/i.archiver/slot/query".format(archiver), payload_objects=(po,))
  
          ev.wait(timeout)
          if len(response) == 0: # no results
              raise TimeoutException("Query of {0} timed out".format(query))
          return response
docs: Runs the given pundat query and returns the results as a Python object.
  
          Arguments:
          [query]: the query string
          [archiver]: if specified, this is the archiver to use. Else, it will run on the first archiver passed
                      into the constructor for the client
          [timeout]: time in seconds to wait for a response from the archiver