/tests/web/multipartform.py

https://bitbucket.org/prologic/circuits/ · Python · 58 lines · 44 code · 10 blank · 4 comment · 9 complexity · b81b4f4da8e0c98550dd6c9452635789 MD5 · raw file

  1. import itertools
  2. from mimetypes import guess_type
  3. from email.generator import _make_boundary
  4. class MultiPartForm(dict):
  5. def __init__(self):
  6. self.files = []
  7. self.boundary = _make_boundary()
  8. def get_content_type(self):
  9. return "multipart/form-data; boundary=%s" % self.boundary
  10. def add_file(self, fieldname, filename, fd, mimetype=None):
  11. body = fd.read()
  12. if mimetype is None:
  13. mimetype = guess_type(filename)[0] or "application/octet-stream"
  14. self.files.append((fieldname, filename, mimetype, body))
  15. def bytes(self):
  16. parts = []
  17. part_boundary = bytearray("--%s" % self.boundary, "ascii")
  18. # Add the form fields
  19. parts.extend([
  20. part_boundary,
  21. bytearray(
  22. "Content-Disposition: form-data; name=\"%s\"" % k,
  23. "ascii"
  24. ),
  25. bytes(),
  26. v if isinstance(v, bytes) else bytearray(v, "ascii")
  27. ] for k, v in list(self.items()))
  28. # Add the files to upload
  29. parts.extend([
  30. part_boundary,
  31. bytearray(
  32. "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"" % (
  33. fieldname, filename),
  34. "ascii"
  35. ),
  36. bytearray("Content-Type: %s" % content_type, "ascii"),
  37. bytearray(),
  38. body if isinstance(body, bytes) else bytearray(body, "ascii"),
  39. ] for fieldname, filename, content_type, body in self.files)
  40. # Flatten the list and add closing boundary marker,
  41. # then return CR+LF separated data
  42. flattened = list(itertools.chain(*parts))
  43. flattened.append(bytearray("--%s--" % self.boundary, "ascii"))
  44. res = bytearray()
  45. for item in flattened:
  46. res += item
  47. res += bytearray("\r\n", "ascii")
  48. return res