filepost.py 2.2 KB

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