docs: def table(dicts, columns, csv=False, pretty=False):
      """Query a list of dicts with a list of queries and return a table.
  
      A "table" is a list of OrderedDicts each having the same keys in the same
      order.
  
      :param dicts: the list of input dicts
      :type dicts: list of dicts
  
      :param columns: the list of column query dicts, or the path to a JSON file
          containing the list of column query dicts
      :type columns: list of dicts, or string
  
      :param csv: return a UTF8-encoded, CSV-formatted string instead of a list
          of dicts
      :type csv: bool
  
      :rtype: list of dicts, or CSV string
  
      """
      # Optionally read columns from file.
      if isinstance(columns, basestring):
          columns = _read_columns_file(columns)
  
      # Either "pattern" or "pattern_path" (but not both) is allowed in the
      # columns.json file, but "pattern" gets normalised to "pattern_path" here.
      for column in columns.values():
          if "pattern" in column:
              assert "pattern_path" not in column, (
                  'A column must have either a "pattern" or a "pattern_path"'
                  "but not both")
              column["pattern_path"] = column["pattern"]
              del column["pattern"]
  
  
      table_ = []
      for d in dicts:
          row = collections.OrderedDict()  # The row we'll return in the table.
          for column_title, column_spec in columns.items():
              if not column_spec.get('return_multiple_columns', False):
                  row[column_title] = query(dict_=d, **column_spec)
              else:
                  multiple_columns = query(dict_=d, **column_spec)
                  for k, v in multiple_columns.items():
                      row[k] = v
  
          table_.append(row)
  
      if pretty:
          # Return a pretty-printed string (looks like a nice table when printed
          # to stdout).
          return tabulate.tabulate(table_, tablefmt="grid", headers="keys")
      elif csv:
          # Return a string of CSV-formatted text.
          return _table_to_csv(table_)
      else:
          # Return a list of dicts.
          return table_