filepost.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from __future__ import absolute_import
  2. import codecs
  3. from uuid import uuid4
  4. from io import BytesIO
  5. from .packages import six
  6. from .packages.six import b
  7. from .fields import RequestField
  8. writer = codecs.lookup('utf-8')[3]
  9. def choose_boundary():
  10. """
  11. Our embarrassingly-simple replacement for mimetools.choose_boundary.
  12. """
  13. return uuid4().hex
  14. def iter_field_objects(fields):
  15. """
  16. Iterate over fields.
  17. Supports list of (k, v) tuples and dicts, and lists of
  18. :class:`~urllib3.fields.RequestField`.
  19. """
  20. if isinstance(fields, dict):
  21. i = six.iteritems(fields)
  22. else:
  23. i = iter(fields)
  24. for field in i:
  25. if isinstance(field, RequestField):
  26. yield field
  27. else:
  28. yield RequestField.from_tuples(*field)
  29. def iter_fields(fields):
  30. """
  31. .. deprecated:: 1.6
  32. Iterate over fields.
  33. The addition of :class:`~urllib3.fields.RequestField` makes this function
  34. obsolete. Instead, use :func:`iter_field_objects`, which returns
  35. :class:`~urllib3.fields.RequestField` objects.
  36. Supports list of (k, v) tuples and dicts.
  37. """
  38. if isinstance(fields, dict):
  39. return ((k, v) for k, v in six.iteritems(fields))
  40. return ((k, v) for k, v in fields)
  41. def encode_multipart_formdata(fields, boundary=None):
  42. """
  43. Encode a dictionary of ``fields`` using the multipart/form-data MIME format.
  44. :param fields:
  45. Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`).
  46. :param boundary:
  47. If not specified, then a random boundary will be generated using
  48. :func:`mimetools.choose_boundary`.
  49. """
  50. body = BytesIO()
  51. if boundary is None:
  52. boundary = choose_boundary()
  53. for field in iter_field_objects(fields):
  54. body.write(b('--%s\r\n' % (boundary)))
  55. writer(body).write(field.render_headers())
  56. data = field.data
  57. if isinstance(data, int):
  58. data = str(data) # Backwards compatibility
  59. if isinstance(data, six.text_type):
  60. writer(body).write(data)
  61. else:
  62. body.write(data)
  63. body.write(b'\r\n')
  64. body.write(b('--%s--\r\n' % (boundary)))
  65. content_type = str('multipart/form-data; boundary=%s' % boundary)
  66. return body.getvalue(), content_type