annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/urllib3/filepost.py @ 68:5028fdace37b

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 16:23:26 -0400
parents
children
rev   line source
jpayne@68 1 from __future__ import annotations
jpayne@68 2
jpayne@68 3 import binascii
jpayne@68 4 import codecs
jpayne@68 5 import os
jpayne@68 6 import typing
jpayne@68 7 from io import BytesIO
jpayne@68 8
jpayne@68 9 from .fields import _TYPE_FIELD_VALUE_TUPLE, RequestField
jpayne@68 10
jpayne@68 11 writer = codecs.lookup("utf-8")[3]
jpayne@68 12
jpayne@68 13 _TYPE_FIELDS_SEQUENCE = typing.Sequence[
jpayne@68 14 typing.Union[typing.Tuple[str, _TYPE_FIELD_VALUE_TUPLE], RequestField]
jpayne@68 15 ]
jpayne@68 16 _TYPE_FIELDS = typing.Union[
jpayne@68 17 _TYPE_FIELDS_SEQUENCE,
jpayne@68 18 typing.Mapping[str, _TYPE_FIELD_VALUE_TUPLE],
jpayne@68 19 ]
jpayne@68 20
jpayne@68 21
jpayne@68 22 def choose_boundary() -> str:
jpayne@68 23 """
jpayne@68 24 Our embarrassingly-simple replacement for mimetools.choose_boundary.
jpayne@68 25 """
jpayne@68 26 return binascii.hexlify(os.urandom(16)).decode()
jpayne@68 27
jpayne@68 28
jpayne@68 29 def iter_field_objects(fields: _TYPE_FIELDS) -> typing.Iterable[RequestField]:
jpayne@68 30 """
jpayne@68 31 Iterate over fields.
jpayne@68 32
jpayne@68 33 Supports list of (k, v) tuples and dicts, and lists of
jpayne@68 34 :class:`~urllib3.fields.RequestField`.
jpayne@68 35
jpayne@68 36 """
jpayne@68 37 iterable: typing.Iterable[RequestField | tuple[str, _TYPE_FIELD_VALUE_TUPLE]]
jpayne@68 38
jpayne@68 39 if isinstance(fields, typing.Mapping):
jpayne@68 40 iterable = fields.items()
jpayne@68 41 else:
jpayne@68 42 iterable = fields
jpayne@68 43
jpayne@68 44 for field in iterable:
jpayne@68 45 if isinstance(field, RequestField):
jpayne@68 46 yield field
jpayne@68 47 else:
jpayne@68 48 yield RequestField.from_tuples(*field)
jpayne@68 49
jpayne@68 50
jpayne@68 51 def encode_multipart_formdata(
jpayne@68 52 fields: _TYPE_FIELDS, boundary: str | None = None
jpayne@68 53 ) -> tuple[bytes, str]:
jpayne@68 54 """
jpayne@68 55 Encode a dictionary of ``fields`` using the multipart/form-data MIME format.
jpayne@68 56
jpayne@68 57 :param fields:
jpayne@68 58 Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`).
jpayne@68 59 Values are processed by :func:`urllib3.fields.RequestField.from_tuples`.
jpayne@68 60
jpayne@68 61 :param boundary:
jpayne@68 62 If not specified, then a random boundary will be generated using
jpayne@68 63 :func:`urllib3.filepost.choose_boundary`.
jpayne@68 64 """
jpayne@68 65 body = BytesIO()
jpayne@68 66 if boundary is None:
jpayne@68 67 boundary = choose_boundary()
jpayne@68 68
jpayne@68 69 for field in iter_field_objects(fields):
jpayne@68 70 body.write(f"--{boundary}\r\n".encode("latin-1"))
jpayne@68 71
jpayne@68 72 writer(body).write(field.render_headers())
jpayne@68 73 data = field.data
jpayne@68 74
jpayne@68 75 if isinstance(data, int):
jpayne@68 76 data = str(data) # Backwards compatibility
jpayne@68 77
jpayne@68 78 if isinstance(data, str):
jpayne@68 79 writer(body).write(data)
jpayne@68 80 else:
jpayne@68 81 body.write(data)
jpayne@68 82
jpayne@68 83 body.write(b"\r\n")
jpayne@68 84
jpayne@68 85 body.write(f"--{boundary}--\r\n".encode("latin-1"))
jpayne@68 86
jpayne@68 87 content_type = f"multipart/form-data; boundary={boundary}"
jpayne@68 88
jpayne@68 89 return body.getvalue(), content_type