Skip to content

Commit

Permalink
Support content=str in upload_attachment()
Browse files Browse the repository at this point in the history
  • Loading branch information
mesozoic committed Sep 8, 2024
1 parent bf8e9ea commit ee095e3
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 21 deletions.
15 changes: 3 additions & 12 deletions pyairtable/api/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,7 @@
import urllib.parse
import warnings
from pathlib import Path
from typing import (
Any,
BinaryIO,
Dict,
Iterable,
Iterator,
List,
Optional,
Union,
overload,
)
from typing import Any, Dict, Iterable, Iterator, List, Optional, Union, overload

import pyairtable.models
from pyairtable.api.retrying import Retry
Expand Down Expand Up @@ -711,7 +701,7 @@ def upload_attachment(
record_id: RecordId,
field: str,
filename: Union[str, Path],
content: Optional[bytes] = None,
content: Optional[Union[str, bytes]] = None,
content_type: Optional[str] = None,
) -> UploadAttachmentResultDict:
""" """
Expand All @@ -730,6 +720,7 @@ def upload_attachment(

# TODO: figure out how to handle the atypical subdomain in a more graceful fashion
url = f"https://content.airtable.com/v0/{self.base.id}/{record_id}/{field}/uploadAttachment"
content = content.encode() if isinstance(content, str) else content
payload = {
"contentType": content_type,
"filename": filename,
Expand Down
2 changes: 1 addition & 1 deletion pyairtable/orm/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class AttachmentsList(ChangeTrackingList[AttachmentDict]):
def upload(
self,
filename: Union[str, Path],
content: Optional[bytes] = None,
content: Optional[Union[str, bytes]] = None,
content_type: Optional[str] = None,
) -> None:
"""
Expand Down
7 changes: 4 additions & 3 deletions tests/test_api_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,19 +618,20 @@ def mock_upload_attachment(requests_mock, table):
)


def test_upload_attachment(mock_upload_attachment, table):
@pytest.mark.parametrize("content", [b"Hello, World!", "Hello, World!"])
def test_upload_attachment(mock_upload_attachment, table, content):
"""
Test that we can upload an attachment to a record.
"""
table.upload_attachment(RECORD_ID, FIELD_ID, "sample.txt", b"Hello, World!")
table.upload_attachment(RECORD_ID, FIELD_ID, "sample.txt", content)
assert mock_upload_attachment.last_request.json() == {
"contentType": "text/plain",
"file": "SGVsbG8sIFdvcmxkIQ==\n", # base64 encoded "Hello, World!"
"filename": "sample.txt",
}


def test_upload_attachment__no_content(mock_upload_attachment, table, tmp_path):
def test_upload_attachment__no_content_type(mock_upload_attachment, table, tmp_path):
"""
Test that we can upload an attachment to a record.
"""
Expand Down
12 changes: 7 additions & 5 deletions tests/test_orm_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,23 @@ def mock_upload():
yield m


def test_attachment_upload(mock_upload, tmp_path):
@pytest.mark.parametrize("content", [b"Hello, world!", "Hello, world!"])
def test_attachment_upload(mock_upload, tmp_path, content):
"""
Test that we can add an attachment to a record.
"""
tmp_file = tmp_path / "a.txt"
tmp_file.write_text("Hello, world!")
fp = tmp_path / "a.txt"
writer = fp.write_text if isinstance(content, str) else fp.write_bytes
writer(content)

record = fake_record()
instance = Fake.from_record(record)
instance.attachments.upload(tmp_file)
instance.attachments.upload(fp)

mock_upload.assert_called_once_with(
record["id"],
"Files",
filename=tmp_file,
filename=fp,
content=None,
content_type=None,
)
Expand Down

0 comments on commit ee095e3

Please sign in to comment.