pyzotero 1.6.6__tar.gz → 1.6.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. {pyzotero-1.6.6 → pyzotero-1.6.7}/PKG-INFO +2 -1
  2. {pyzotero-1.6.6 → pyzotero-1.6.7}/pyproject.toml +1 -0
  3. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/_version.py +2 -2
  4. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero/zotero.py +57 -38
  5. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero.egg-info/PKG-INFO +2 -1
  6. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero.egg-info/requires.txt +1 -0
  7. {pyzotero-1.6.6 → pyzotero-1.6.7}/uv.lock +24 -0
  8. {pyzotero-1.6.6 → pyzotero-1.6.7}/.coveragerc +0 -0
  9. {pyzotero-1.6.6 → pyzotero-1.6.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  10. {pyzotero-1.6.6 → pyzotero-1.6.7}/.github/ISSUE_TEMPLATE/usage_question.md +0 -0
  11. {pyzotero-1.6.6 → pyzotero-1.6.7}/.github/dependabot.yml +0 -0
  12. {pyzotero-1.6.6 → pyzotero-1.6.7}/.github/pull_request_template.md +0 -0
  13. {pyzotero-1.6.6 → pyzotero-1.6.7}/.github/workflows/tests.yml +0 -0
  14. {pyzotero-1.6.6 → pyzotero-1.6.7}/.gitignore +0 -0
  15. {pyzotero-1.6.6 → pyzotero-1.6.7}/.readthedocs.yaml +0 -0
  16. {pyzotero-1.6.6 → pyzotero-1.6.7}/AUTHORS +0 -0
  17. {pyzotero-1.6.6 → pyzotero-1.6.7}/CITATION.cff +0 -0
  18. {pyzotero-1.6.6 → pyzotero-1.6.7}/CONTRIBUTING.md +0 -0
  19. {pyzotero-1.6.6 → pyzotero-1.6.7}/CONTRIBUTORS.md +0 -0
  20. {pyzotero-1.6.6 → pyzotero-1.6.7}/LICENSE.md +0 -0
  21. {pyzotero-1.6.6 → pyzotero-1.6.7}/README.md +0 -0
  22. {pyzotero-1.6.6 → pyzotero-1.6.7}/__init__.py +0 -0
  23. {pyzotero-1.6.6 → pyzotero-1.6.7}/doc/Makefile +0 -0
  24. {pyzotero-1.6.6 → pyzotero-1.6.7}/doc/_templates/layout.html +0 -0
  25. {pyzotero-1.6.6 → pyzotero-1.6.7}/doc/cat.png +0 -0
  26. {pyzotero-1.6.6 → pyzotero-1.6.7}/doc/conf.py +0 -0
  27. {pyzotero-1.6.6 → pyzotero-1.6.7}/doc/index.rst +0 -0
  28. {pyzotero-1.6.6 → pyzotero-1.6.7}/dump_contributors.py +0 -0
  29. {pyzotero-1.6.6 → pyzotero-1.6.7}/setup.cfg +0 -0
  30. {pyzotero-1.6.6 → pyzotero-1.6.7}/setup.py +0 -0
  31. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero/__init__.py +0 -0
  32. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero/zotero_errors.py +0 -0
  33. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero.egg-info/SOURCES.txt +0 -0
  34. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero.egg-info/dependency_links.txt +0 -0
  35. {pyzotero-1.6.6 → pyzotero-1.6.7}/src/pyzotero.egg-info/top_level.txt +0 -0
  36. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/__init__.py +0 -0
  37. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/attachments_doc.json +0 -0
  38. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/citation_doc.xml +0 -0
  39. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/collection_doc.json +0 -0
  40. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/collection_tags.json +0 -0
  41. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/collection_versions.json +0 -0
  42. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/collections_doc.json +0 -0
  43. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/creation_doc.json +0 -0
  44. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/groups_doc.json +0 -0
  45. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/item_doc.json +0 -0
  46. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/item_fields.json +0 -0
  47. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/item_file.pdf +0 -0
  48. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/item_template.json +0 -0
  49. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/item_types.json +0 -0
  50. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/item_versions.json +0 -0
  51. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/items_doc.json +0 -0
  52. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/keys_doc.txt +0 -0
  53. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/api_responses/tags_doc.json +0 -0
  54. {pyzotero-1.6.6 → pyzotero-1.6.7}/tests/test_zotero.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pyzotero
3
- Version: 1.6.6
3
+ Version: 1.6.7
4
4
  Summary: Python wrapper for the Zotero API
5
5
  Author-email: Stephan Hügel <urschrei@gmail.com>
6
6
  License: # Blue Oak Model License
@@ -63,6 +63,7 @@ Requires-Dist: feedparser>=6.0.11
63
63
  Requires-Dist: pytz
64
64
  Requires-Dist: bibtexparser
65
65
  Requires-Dist: httpx>=0.28.1
66
+ Requires-Dist: httpx-file>=0.2.0
66
67
  Provides-Extra: test
67
68
  Requires-Dist: pytest>=7.4.2; extra == "test"
68
69
  Requires-Dist: httpretty; extra == "test"
@@ -8,6 +8,7 @@ dependencies = [
8
8
  "pytz",
9
9
  "bibtexparser",
10
10
  "httpx>=0.28.1",
11
+ "httpx-file>=0.2.0",
11
12
  ]
12
13
  authors = [{ name = "Stephan Hügel", email = "urschrei@gmail.com" }]
13
14
  license = {file = "LICENSE.md"}
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.6.6'
16
- __version_tuple__ = version_tuple = (1, 6, 6)
15
+ __version__ = version = '1.6.7'
16
+ __version_tuple__ = version_tuple = (1, 6, 7)
@@ -40,6 +40,7 @@ import feedparser
40
40
  import httpx
41
41
  import pytz
42
42
  from httpx import Request
43
+ from httpx_file import Client as File_Client
43
44
 
44
45
  import pyzotero as pz
45
46
 
@@ -190,38 +191,9 @@ def retrieve(func):
190
191
  and self.content.search(str(self.request.url)).group(0)
191
192
  or "bib"
192
193
  )
193
- # JSON by default
194
- formats = {
195
- "application/atom+xml": "atom",
196
- "application/x-bibtex": "bibtex",
197
- "application/json": "json",
198
- "text/html": "snapshot",
199
- "text/plain": "plain",
200
- "application/pdf; charset=utf-8": "pdf",
201
- "application/pdf": "pdf",
202
- "application/msword": "doc",
203
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
204
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
205
- "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
206
- "application/zip": "zip",
207
- "application/epub+zip": "zip",
208
- "audio/mpeg": "mp3",
209
- "video/mp4": "mp4",
210
- "audio/x-wav": "wav",
211
- "video/x-msvideo": "avi",
212
- "application/octet-stream": "octet",
213
- "application/x-tex": "tex",
214
- "application/x-texinfo": "texinfo",
215
- "image/jpeg": "jpeg",
216
- "image/png": "png",
217
- "image/gif": "gif",
218
- "image/tiff": "tiff",
219
- "application/postscript": "postscript",
220
- "application/rtf": "rtf",
221
- }
222
194
  # select format, or assume JSON
223
195
  content_type_header = self.request.headers["Content-Type"].lower() + ";"
224
- fmt = formats.get(
196
+ fmt = self.formats.get(
225
197
  # strip "; charset=..." segment
226
198
  content_type_header[0 : content_type_header.index(";")],
227
199
  "json",
@@ -321,12 +293,44 @@ class Zotero:
321
293
  self.tag_data = False
322
294
  self.request = None
323
295
  self.snapshot = False
324
- self.client = httpx.Client(headers=self.default_headers())
296
+ self.client = httpx.Client(
297
+ headers=self.default_headers(), follow_redirects=True
298
+ )
325
299
  # these aren't valid item fields, so never send them to the server
326
300
  self.temp_keys = set(["key", "etag", "group_id", "updated"])
327
301
  # determine which processor to use for the parsed content
328
302
  self.fmt = re.compile(r"(?<=format=)\w+")
329
303
  self.content = re.compile(r"(?<=content=)\w+")
304
+ # JSON by default
305
+ self.formats = {
306
+ "application/atom+xml": "atom",
307
+ "application/x-bibtex": "bibtex",
308
+ "application/json": "json",
309
+ "text/html": "snapshot",
310
+ "text/plain": "plain",
311
+ "text/markdown": "plain",
312
+ "application/pdf; charset=utf-8": "pdf",
313
+ "application/pdf": "pdf",
314
+ "application/msword": "doc",
315
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
316
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
317
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
318
+ "application/zip": "zip",
319
+ "application/epub+zip": "zip",
320
+ "audio/mpeg": "mp3",
321
+ "video/mp4": "mp4",
322
+ "audio/x-wav": "wav",
323
+ "video/x-msvideo": "avi",
324
+ "application/octet-stream": "octet",
325
+ "application/x-tex": "tex",
326
+ "application/x-texinfo": "texinfo",
327
+ "image/jpeg": "jpeg",
328
+ "image/png": "png",
329
+ "image/gif": "gif",
330
+ "image/tiff": "tiff",
331
+ "application/postscript": "postscript",
332
+ "application/rtf": "rtf",
333
+ }
330
334
  self.processors = {
331
335
  "bib": self._bib_processor,
332
336
  "citation": self._citation_processor,
@@ -479,13 +483,28 @@ class Zotero:
479
483
  # Unfortunately, httpx doesn't like to merge query paramaters in the url string and passed params
480
484
  # so we strip the url params, combining them with our existing url_params
481
485
  final_url, final_params = merge_params(full_url, merged_params)
482
- self.request = self.client.get(
483
- url=final_url,
484
- params=final_params,
485
- headers=self.default_headers(),
486
- timeout=timeout,
487
- )
488
- self.request.encoding = "utf-8"
486
+ # file URI errors are raised immediately so we have to try here
487
+ try:
488
+ self.request = self.client.get(
489
+ url=final_url,
490
+ params=final_params,
491
+ headers=self.default_headers(),
492
+ timeout=timeout,
493
+ )
494
+ self.request.encoding = "utf-8"
495
+ except httpx.UnsupportedProtocol:
496
+ # File URI handler logic
497
+ fc = File_Client()
498
+ request = fc.get(
499
+ url=final_url,
500
+ params=final_params,
501
+ headers=self.default_headers(),
502
+ timeout=timeout,
503
+ follow_redirects=True,
504
+ )
505
+ self.request = request
506
+ # since we'll be writing bytes, we need to set this to a type that will trigger the bytes processor
507
+ self.request.headers["Content-Type"] = "text/plain"
489
508
  try:
490
509
  self.request.raise_for_status()
491
510
  except httpx.HTTPError as exc:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pyzotero
3
- Version: 1.6.6
3
+ Version: 1.6.7
4
4
  Summary: Python wrapper for the Zotero API
5
5
  Author-email: Stephan Hügel <urschrei@gmail.com>
6
6
  License: # Blue Oak Model License
@@ -63,6 +63,7 @@ Requires-Dist: feedparser>=6.0.11
63
63
  Requires-Dist: pytz
64
64
  Requires-Dist: bibtexparser
65
65
  Requires-Dist: httpx>=0.28.1
66
+ Requires-Dist: httpx-file>=0.2.0
66
67
  Provides-Extra: test
67
68
  Requires-Dist: pytest>=7.4.2; extra == "test"
68
69
  Requires-Dist: httpretty; extra == "test"
@@ -2,6 +2,7 @@ feedparser>=6.0.11
2
2
  pytz
3
3
  bibtexparser
4
4
  httpx>=0.28.1
5
+ httpx-file>=0.2.0
5
6
 
6
7
  [test]
7
8
  pytest>=7.4.2
@@ -1,6 +1,15 @@
1
1
  version = 1
2
2
  requires-python = ">=3.9"
3
3
 
4
+ [[package]]
5
+ name = "aiofiles"
6
+ version = "24.1.0"
7
+ source = { registry = "https://pypi.org/simple" }
8
+ sdist = { url = "https://files.pythonhosted.org/packages/0b/03/a88171e277e8caa88a4c77808c20ebb04ba74cc4681bf1e9416c862de237/aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c", size = 30247 }
9
+ wheels = [
10
+ { url = "https://files.pythonhosted.org/packages/a5/45/30bb92d442636f570cb5651bc661f52b610e2eec3f891a5dc3a4c3667db0/aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5", size = 15896 },
11
+ ]
12
+
4
13
  [[package]]
5
14
  name = "anyio"
6
15
  version = "4.5.2"
@@ -152,6 +161,19 @@ wheels = [
152
161
  { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
153
162
  ]
154
163
 
164
+ [[package]]
165
+ name = "httpx-file"
166
+ version = "0.2.0"
167
+ source = { registry = "https://pypi.org/simple" }
168
+ dependencies = [
169
+ { name = "aiofiles" },
170
+ { name = "httpx" },
171
+ ]
172
+ sdist = { url = "https://files.pythonhosted.org/packages/b4/f7/737dbfaa3b3288ce69f75fad9a4cd22cae60d71763618ddd849018895172/httpx-file-0.2.0.tar.gz", hash = "sha256:a00f1dd02c9ffb5e7e072205c30f7ae0d867c397318b045a40b3268f2cdfa932", size = 4250 }
173
+ wheels = [
174
+ { url = "https://files.pythonhosted.org/packages/f4/9c/4f3fba4c1b5a8919c3f6d407a41df43980c6a03a631d49f458b9546da128/httpx_file-0.2.0-py3-none-any.whl", hash = "sha256:9a425b351bf65aa394c02096204dc3fa8b647573a289079f927d3e3abfa3c7c8", size = 4471 },
175
+ ]
176
+
155
177
  [[package]]
156
178
  name = "idna"
157
179
  version = "3.10"
@@ -359,6 +381,7 @@ dependencies = [
359
381
  { name = "bibtexparser" },
360
382
  { name = "feedparser" },
361
383
  { name = "httpx" },
384
+ { name = "httpx-file" },
362
385
  { name = "pytz" },
363
386
  ]
364
387
 
@@ -376,6 +399,7 @@ requires-dist = [
376
399
  { name = "feedparser", specifier = ">=6.0.11" },
377
400
  { name = "httpretty", marker = "extra == 'test'" },
378
401
  { name = "httpx", specifier = ">=0.28.1" },
402
+ { name = "httpx-file", specifier = ">=0.2.0" },
379
403
  { name = "ipython", marker = "extra == 'test'" },
380
404
  { name = "pytest", marker = "extra == 'test'", specifier = ">=7.4.2" },
381
405
  { name = "python-dateutil", marker = "extra == 'test'" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes