docs: def search(self, Queue=None, order=None, raw_query=None, Format='l', **kwargs):
          """ Search arbitrary needles in given fields and queue.
  
          Example::
  
              >>> tracker = Rt('http://tracker.example.com/REST/1.0/', 'rt-username', 'top-secret')
              >>> tracker.login()
              >>> tickets = tracker.search(CF_Domain='example.com', Subject__like='warning')
              >>> tickets = tracker.search(Queue='General', order='Status', raw_query="id='1'+OR+id='2'+OR+id='3'")
  
          :keyword Queue:      Queue where to search. If you wish to search across
                               all of your queues, pass the ALL_QUEUES object as the
                               argument.
          :keyword order:      Name of field sorting result list, for descending
                               order put - before the field name. E.g. -Created
                               will put the newest tickets at the beginning
          :keyword raw_query:  A raw query to provide to RT if you know what
                               you are doing. You may still pass Queue and order
                               kwargs, so use these instead of including them in
                               the raw query. You can refer to the RT query builder.
                               If passing raw_query, all other **kwargs will be ignored.
          :keyword Format:     Format of the query:
                                 - i: only `id' fields are populated
                                 - s: only `id' and `subject' fields are populated
                                 - l: multi-line format, all fields are populated
          :keyword kwargs:     Other arguments possible to set if not passing raw_query:
  
                               Requestors, Subject, Cc, AdminCc, Owner, Status,
                               Priority, InitialPriority, FinalPriority,
                               TimeEstimated, Starts, Due, Text,... (according to RT
                               fields)
  
                               Custom fields CF.{<CustomFieldName>} could be set
                               with keywords CF_CustomFieldName.
  
                               To alter lookup operators you can append one of the
                               following endings to each keyword:
  
                               __exact    for operator = (default)
                               __notexact for operator !=
                               __gt       for operator >
                               __lt       for operator <
                               __like     for operator LIKE
                               __notlike  for operator NOT LIKE
  
                               Setting values to keywords constrain search
                               result to the tickets satisfying all of them.
  
          :returns: List of matching tickets. Each ticket is the same dictionary
                    as in :py:meth:`~Rt.get_ticket`.
          :raises:  UnexpectedMessageFormat: Unexpected format of returned message.
                    InvalidQueryError: If raw query is malformed
          """
          get_params = {}
          query = []
          url = 'search/ticket'
          if Queue is not ALL_QUEUES:
              query.append("Queue=\'{}\'".format(Queue or self.default_queue))
          if not raw_query:
              operators_map = {
                  'gt': '>',
                  'lt': '<',
                  'exact': '=',
                  'notexact': '!=',
                  'like': ' LIKE ',
                  'notlike': ' NOT LIKE '
              }
  
              for key, value in iteritems(kwargs):
                  op = '='
                  key_parts = key.split('__')
                  if len(key_parts) > 1:
                      key = '__'.join(key_parts[:-1])
                      op = operators_map.get(key_parts[-1], '=')
                  if key[:3] != 'CF_':
                      query.append("{}{}\'{}\'".format(key, op, value))
                  else:
                      query.append("'CF.{{{}}}'{}\'{}\'".format(key[3:], op, value))
          else:
              query.append(raw_query)
          get_params['query'] = ' AND '.join('(' + part + ')' for part in query)
          if order:
              get_params['orderby'] = order
          get_params['format'] = Format
  
          msg = self.__request(url, get_params=get_params)
          lines = msg.split('\n')
          if len(lines) > 2:
              if self.__get_status_code(lines[0]) != 200 and lines[2].startswith('Invalid query: '):
                  raise InvalidQueryError(lines[2])
              if lines[2].startswith('No matching results.'):
                  return []
  
          if Format == 'l':
              msgs = map(lambda x: x.split('\n'), msg.split('\n--\n'))
              items = []
              for msg in msgs:
                  pairs = {}
                  req_matching = [i for i, m in enumerate(msg) if self.RE_PATTERNS['requestors_pattern'].match(m)]
                  req_id = req_matching[0] if req_matching else None
                  if not req_id:
                      raise UnexpectedMessageFormat('Missing line starting with `Requestors:`.')
                  for i in range(req_id):
                      if ': ' in msg[i]:
                          header, content = self.split_header(msg[i])
                          pairs[header.strip()] = content.strip()
                  requestors = [msg[req_id][12:]]
                  req_id += 1
                  while (req_id < len(msg)) and (msg[req_id][:12] == ' ' * 12):
                      requestors.append(msg[req_id][12:])
                      req_id += 1
                  pairs['Requestors'] = self.__normalize_list(requestors)
                  for i in range(req_id, len(msg)):
                      if ': ' in msg[i]:
                          header, content = self.split_header(msg[i])
                          pairs[header.strip()] = content.strip()
                  if pairs:
                      items.append(pairs)
  
                  if 'Cc' in pairs:
                      pairs['Cc'] = self.__normalize_list(pairs['Cc'])
                  if 'AdminCc' in pairs:
                      pairs['AdminCc'] = self.__normalize_list(pairs['AdminCc'])
  
                  if 'id' not in pairs and not pairs['id'].startswitch('ticket/'):
                      raise UnexpectedMessageFormat('Response from RT didn\'t contain a valid ticket_id')
                  else:
                      pairs['numerical_id'] = pairs['id'].split('ticket/')[1]
  
              return items
          elif Format == 's':
              items = []
              msgs = lines[2:]
              for msg in msgs:
                  if "" == msg:  # Ignore blank line at the end
                      continue
                  ticket_id, subject = self.split_header(msg)
                  items.append({'id': 'ticket/' + ticket_id, 'numerical_id': ticket_id, 'Subject': subject})
              return items
          elif Format == 'i':
              items = []
              msgs = lines[2:]
              for msg in msgs:
                  if "" == msg:  # Ignore blank line at the end
                      continue
                  _, ticket_id = msg.split('/', 1)
                  items.append({'id': 'ticket/' + ticket_id, 'numerical_id': ticket_id})
              return items