annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/urllib3/filepost.py @ 69:33d812a61356

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