+1
-1
pyproject.toml
+1
-1
pyproject.toml
+6
src/pyzotero/zotero.py
+6
src/pyzotero/zotero.py
···
1879
1879
msg,
1880
1880
)
1881
1881
return None # Don't do anything if payload comes with keys
1882
+
# Set contentType for each attachment if not already provided
1883
+
for item in self.payload:
1884
+
if not item.get("contentType"):
1885
+
filepath = str(self.basedir.joinpath(item["filename"]))
1886
+
detected_type = mimetypes.guess_type(filepath)[0]
1887
+
item["contentType"] = detected_type or "application/octet-stream"
1882
1888
liblevel = "/{t}/{u}/items"
1883
1889
# Create one or more new attachments
1884
1890
headers = {"Zotero-Write-Token": token(), "Content-Type": "application/json"}
+104
tests/test_zotero.py
+104
tests/test_zotero.py
···
1157
1157
os.remove(temp_file_path)
1158
1158
1159
1159
@httpretty.activate
1160
+
def testFileUploadSetsContentType(self):
1161
+
"""Tests that contentType is automatically set during upload based on file extension"""
1162
+
zot = z.Zotero("myuserID", "user", "myuserkey")
1163
+
1164
+
# Create a temporary PDF file for testing
1165
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload.pdf")
1166
+
with open(temp_file_path, "w") as f:
1167
+
f.write("Fake PDF content")
1168
+
1169
+
# Variable to capture the request body
1170
+
captured_body = []
1171
+
1172
+
def request_callback(request, uri, response_headers):
1173
+
body = json.loads(request.body)
1174
+
captured_body.append(body)
1175
+
return [200, response_headers, json.dumps({"success": {"0": "ITEMKEY123"}})]
1176
+
1177
+
HTTPretty.register_uri(
1178
+
HTTPretty.POST,
1179
+
"https://api.zotero.org/users/myuserID/items",
1180
+
body=request_callback,
1181
+
content_type="application/json",
1182
+
)
1183
+
1184
+
# Create payload with empty contentType (mimics Zotero API template)
1185
+
payload = [
1186
+
{
1187
+
"filename": "test_upload.pdf",
1188
+
"title": "Test PDF",
1189
+
"linkMode": "imported_file",
1190
+
"contentType": "",
1191
+
}
1192
+
]
1193
+
1194
+
mock_auth_data = {"exists": True}
1195
+
1196
+
with (
1197
+
patch.object(z.Zupload, "_verify", return_value=None),
1198
+
patch.object(z.Zupload, "_get_auth", return_value=mock_auth_data),
1199
+
):
1200
+
upload = z.Zupload(
1201
+
zot, payload, basedir=os.path.join(self.cwd, "api_responses")
1202
+
)
1203
+
upload.upload()
1204
+
1205
+
# Verify contentType was automatically set to application/pdf
1206
+
self.assertEqual(len(captured_body), 1)
1207
+
self.assertEqual(captured_body[0][0].get("contentType"), "application/pdf")
1208
+
1209
+
os.remove(temp_file_path)
1210
+
1211
+
@httpretty.activate
1212
+
def testFileUploadPreservesUserContentType(self):
1213
+
"""Tests that user-provided contentType is not overridden"""
1214
+
zot = z.Zotero("myuserID", "user", "myuserkey")
1215
+
1216
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload.txt")
1217
+
with open(temp_file_path, "w") as f:
1218
+
f.write("Test content")
1219
+
1220
+
captured_body = []
1221
+
1222
+
def request_callback(request, uri, response_headers):
1223
+
body = json.loads(request.body)
1224
+
captured_body.append(body)
1225
+
return [200, response_headers, json.dumps({"success": {"0": "ITEMKEY123"}})]
1226
+
1227
+
HTTPretty.register_uri(
1228
+
HTTPretty.POST,
1229
+
"https://api.zotero.org/users/myuserID/items",
1230
+
body=request_callback,
1231
+
content_type="application/json",
1232
+
)
1233
+
1234
+
# Create payload WITH explicit contentType
1235
+
payload = [
1236
+
{
1237
+
"filename": "test_upload.txt",
1238
+
"title": "Test File",
1239
+
"linkMode": "imported_file",
1240
+
"contentType": "application/custom-type",
1241
+
}
1242
+
]
1243
+
1244
+
mock_auth_data = {"exists": True}
1245
+
1246
+
with (
1247
+
patch.object(z.Zupload, "_verify", return_value=None),
1248
+
patch.object(z.Zupload, "_get_auth", return_value=mock_auth_data),
1249
+
):
1250
+
upload = z.Zupload(
1251
+
zot, payload, basedir=os.path.join(self.cwd, "api_responses")
1252
+
)
1253
+
upload.upload()
1254
+
1255
+
# Verify user-provided contentType was preserved
1256
+
self.assertEqual(len(captured_body), 1)
1257
+
self.assertEqual(
1258
+
captured_body[0][0].get("contentType"), "application/custom-type"
1259
+
)
1260
+
1261
+
os.remove(temp_file_path)
1262
+
1263
+
@httpretty.activate
1160
1264
def testFileUploadWithPreexistingKeys(self):
1161
1265
"""Tests file upload process when the payload already contains keys"""
1162
1266
zot = z.Zotero("myuserID", "user", "myuserkey")