annotate urllib3/filepost.py @ 14:18e1cb6018fd

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