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