title: csv class writer : a bytes-like object is required, not 'str'
body: <p>For a personal project I'm trying to upgrade the <strong>paterns</strong> package to Python 3. 
  Actually I'm running the test:db.py,  but I'm stuck with the following error in the <strong>'__init__.py'</strong> file, on a csv class:</p>
  
  <p>This is the code snippet od the <strong>save()</strong> function:
  there, we dfine <strong>s</strong> as a <strong>BytesIO()</strong> stream, so the function is asked to stream bytes to a <em>self</em> csv file.
  The error comes from the line: </p>
  
  <pre><code>w.writerows([[csv_header_encode(name, type) for name, type in self.fields]])
  
  TypeError: a bytes-like object is required, not 'str' ( below, also the code for this function)
  </code></pre>
  
  <p>it's supposed that csv_header_encode to deliver bytes, and I checked this and it does, but somehow, in its conversion to list it changes to 'str'.
  And if I change the <strong>s</strong> encoding to StringsIO then the complaining comes from</p>
  
  <pre><code> f.write(BOM_UTF8)
  </code></pre>
  
  <p>Any help will be appreciated.</p>
  
  <pre><code>def save(self, path, separator=",", encoder=lambda v: v, headers=False, password=None, **kwargs):
      """ Exports the table to a unicode text file at the given path.
          Rows in the file are separated with a newline.
          Columns in a row are separated with the given separator (by default, comma).
          For data types other than string, int, float, bool or None, a custom string encoder can be given.
      """
      # Optional parameters include all arguments for csv.writer(), see:
      # http://docs.python.org/library/csv.html#csv.writer
      kwargs.setdefault("delimiter", separator)
      kwargs.setdefault("quoting", csvlib.QUOTE_ALL)
      # csv.writer will handle str, int, float and bool:
      s = BytesIO()
      w = csvlib.writer(s,  **kwargs)
      if headers and self.fields is not None:
          w.writerows([[csv_header_encode(name, type) for name, type in self.fields]])
      w.writerows([[encode_utf8(encoder(v)) for v in row] for row in self])
      s = s.getvalue()
      s = s.strip()
      s = re.sub("([^\"]|^)\"None\"", "\\1None", s)
      s = (s if not password else encrypt_string(s, password)).encode('latin-1')
      f = open(path, "wt")
      f.write(BOM_UTF8)
      f.write(s)
      f.close()
  
  def csv_header_encode(field, type=STRING):
      # csv_header_encode("age", INTEGER) =&gt; "age (INTEGER)".
      t = re.sub(r"^varchar\(.*?\)", "string", (type or ""))
      t = t and " (%s)" % t or ""
      return "%s%s" % (encode_utf8(field or ""), t.upper())
  </code></pre>