docs: def returnCSV(self, keys=None, limit=False, omitHeaderLine=False, quoteChar=None, eolChars='\r\n'):
          r'''Return a list of dictionaries formated as a comma seperated values
          (CSV) list in a string.
  
          Each entry is on one line. By default, each value is seperated by
          commas and each entry is followed by a newline ('\n').
  
          By default, RFC4180 is followed. See:
  
             http://tools.ietf.org/html/rfc4180
  
          The RFC has considerable detail describing the format.
  
          Note regarding certain RFC section 2 sub 4: there is no default
          behavior specified if the last field on a line is empty and thus
          creating a 'trailing comma'. This routine handles it by quoting
          the final field. The first example below demonstrates this for the
          entry with 'name' of 'Larry' and a missing 'income' field. The
          missing field is shown as "" at the end of the line.
             
          Missing keys and/or values of None are simply blank.
  
          Example of use:
  
          >>> test = [
          ...    {"name": "Jim, Phd",         "age": 18  , "income": 93000, "order": 2},
          ...    {"name": "Larry",            "age": None,                  "order": 3},
          ...    {"name": "Joe",              "age": 20  , "income": 15000, "order": 1},
          ...    {"name": "B \"Zip\" O'Tool", "age": 19  , "income": 29000, "order": 4},
          ... ]
          >>> print PLOD(test).returnCSV()   # doctest: +NORMALIZE_WHITESPACE
          age,order,name,income
          18,2,"Jim, Phd",93000
          ,3,Larry,""
          20,1,Joe,15000
          19,4,"B ""Zip"" O'Tool",29000
          <BLANKLINE>
          >>> print PLOD(test).returnCSV(limit=3, omitHeaderLine=True, quoteChar="'", eolChars='\n')
          '18','2','Jim, Phd','93000'
          '','3','Larry',''
          '20','1','Joe','15000'
          <BLANKLINE>
          >>> print PLOD(test).returnCSV(keys=["name", "age"], quoteChar='"', eolChars='\n')
          "name","age"
          "Jim, Phd","18"
          "Larry",""
          "Joe","20"
          "B ""Zip"" O'Tool","19"
          <BLANKLINE>
          
          :param keys:
             If the 'keys' parameter is passed a list of keys, then only those
             keys are returned. The order of keys in the list is retained. If a
             key is not found in an entry (or in *any* entry), that is not an error
             condition. Those entries simply have an empty value for that position.
  
             NOTE: use this parameter if the order of the keys is critical. Order
             is not guaranteed otherwise.
          :param limit:
             A number limiting the quantity of entries to return. Defaults to
             False, which means that the full list is returned.
          :param omitHeaderLine:
             If set to True, the initial line of text listing the keys
             is not included. Defaults to False.
          :param quoteChar:
             If set to anything (including a single quote), then all fields will
             be surrounded by the quote character.
          :param eolChars:
             These are the characters inserted at the end of each line. By default
             they are CRLF ('\r\n') as specified in RFC4180. To be more pythonic
             you could change it to '\n'.
          :return:
             A string containing a formatted textual representation of the list
             of dictionaries.
          '''
          result = ""
          if quoteChar:
              quoteAll=True
          else:
              quoteAll=False
          # we limit the table if needed
          used_table = self.table
          if limit:
              used_table = []
              for i in range(limit):
                  if len(self.table)>i:
                      used_table.append(self.table[i])
          # we locate all of the attributes
          if keys:
              attr_list = keys
          else:
              attr_list = []
              for row in used_table:
                  for key in row:
                      if not key in attr_list:
                          attr_list.append(key)
          # now we do the pretty print
          if not omitHeaderLine:
              if quoteAll:
                  result += quoteChar
                  temp = quoteChar+","+quoteChar
                  result += temp.join(attr_list)
                  result += quoteChar
              else:
                  result += ",".join(attr_list)
              result += eolChars
          for row in used_table:
              ml = []
              for ctr, key in enumerate(attr_list):
                  if key in row:
                      if row[key] is None:
                          value = ""
                      else:
                          value = str(row[key])
                      if quoteAll:
                          ml.append(internal.csv_quote(quoteChar,value))
                      else:
                          if ('"' in value) or (',' in value):
                              ml.append(internal.csv_quote('"', value))
                          else:
                              if ((ctr+1)==len(attr_list)) and (len(value)==0):
                                  ml.append('""')
                              else:
                                  ml.append(value)
                  else:
                      if quoteAll:
                          ml.append(quoteChar+quoteChar)
                      else:
                          if (ctr+1)==len(attr_list):
                              ml.append('""')
                          else:
                              ml.append("")
              result += ",".join(ml)
              result += eolChars
          return result