Skip to content

Commit 77f8b95

Browse files
committed
starting files arg for uploading
1 parent 12e6b47 commit 77f8b95

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

adafruit_requests.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@
4141

4242
import errno
4343
import json as json_module
44+
import random
4445
import sys
4546

4647
from adafruit_connection_manager import get_connection_manager
4748

4849
if not sys.implementation.name == "circuitpython":
50+
from io import FileIO
4951
from types import TracebackType
5052
from typing import Any, Dict, Optional, Type
5153

@@ -394,6 +396,13 @@ def _send(socket: SocketType, data: bytes):
394396
def _send_as_bytes(self, socket: SocketType, data: str):
395397
return self._send(socket, bytes(data, "utf-8"))
396398

399+
def _generate_boundary_str(self):
400+
hex_characters = "0123456789abcdef"
401+
_boundary = ""
402+
for i in range(32):
403+
_boundary += random.choice(hex_characters)
404+
return _boundary
405+
397406
def _send_header(self, socket, header, value):
398407
if value is None:
399408
return
@@ -415,6 +424,7 @@ def _send_request(
415424
headers: Dict[str, str],
416425
data: Any,
417426
json: Any,
427+
files: Optional[Dict[str, tuple]],
418428
):
419429
# Check headers
420430
self._check_headers(headers)
@@ -425,6 +435,7 @@ def _send_request(
425435
# If json is sent, set content type header and convert to string
426436
if json is not None:
427437
assert data is None
438+
assert files is None
428439
content_type_header = "application/json"
429440
data = json_module.dumps(json)
430441

@@ -441,13 +452,69 @@ def _send_request(
441452
if data and isinstance(data, str):
442453
data = bytes(data, "utf-8")
443454

455+
if data is None:
456+
data = b""
457+
444458
self._send_as_bytes(socket, method)
445459
self._send(socket, b" /")
446460
self._send_as_bytes(socket, path)
447461
self._send(socket, b" HTTP/1.1\r\n")
448462

449463
# create lower-case supplied header list
450464
supplied_headers = {header.lower() for header in headers}
465+
boundary_str = None
466+
467+
if files is not None and isinstance(files, dict):
468+
boundary_str = self._generate_boundary_str()
469+
content_type_header = f"multipart/form-data; boundary={boundary_str}"
470+
471+
for fieldname in files.keys():
472+
if not fieldname.endswith("-name"):
473+
if files[fieldname][0] is not None:
474+
file_content = files[fieldname][1].read()
475+
476+
data += b"--" + boundary_str.encode() + b"\r\n"
477+
data += (
478+
b'Content-Disposition: form-data; name="'
479+
+ fieldname.encode()
480+
+ b'"; filename="'
481+
+ files[fieldname][0].encode()
482+
+ b'"\r\n'
483+
)
484+
if len(files[fieldname]) >= 3:
485+
data += (
486+
b"Content-Type: "
487+
+ files[fieldname][2].encode()
488+
+ b"\r\n"
489+
)
490+
if len(files[fieldname]) >= 4:
491+
for custom_header_key in files[fieldname][3].keys():
492+
data += (
493+
custom_header_key.encode()
494+
+ b": "
495+
+ files[fieldname][3][custom_header_key].encode()
496+
+ b"\r\n"
497+
)
498+
data += b"\r\n"
499+
data += file_content + b"\r\n"
500+
else:
501+
# filename is None
502+
data += b"--" + boundary_str.encode() + b"\r\n"
503+
data += (
504+
b'Content-Disposition: form-data; name="'
505+
+ fieldname.encode()
506+
+ b'"; \r\n'
507+
)
508+
if len(files[fieldname]) >= 3:
509+
data += (
510+
b"Content-Type: "
511+
+ files[fieldname][2].encode()
512+
+ b"\r\n"
513+
)
514+
data += b"\r\n"
515+
data += files[fieldname][1].encode() + b"\r\n"
516+
517+
data += b"--" + boundary_str.encode() + b"--"
451518

452519
# Send headers
453520
if not "host" in supplied_headers:
@@ -478,6 +545,7 @@ def request(
478545
stream: bool = False,
479546
timeout: float = 60,
480547
allow_redirects: bool = True,
548+
files: Optional[Dict[str, tuple]] = None,
481549
) -> Response:
482550
"""Perform an HTTP request to the given url which we will parse to determine
483551
whether to use SSL ('https://') or not. We can also send some provided 'data'
@@ -526,7 +594,9 @@ def request(
526594
)
527595
ok = True
528596
try:
529-
self._send_request(socket, host, method, path, headers, data, json)
597+
self._send_request(
598+
socket, host, method, path, headers, data, json, files
599+
)
530600
except OSError as exc:
531601
last_exc = exc
532602
ok = False

0 commit comments

Comments
 (0)