pyzotero 1.5.27__tar.gz → 1.6.0__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.
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.github/workflows/tests.yml +1 -1
- {pyzotero-1.5.27/src/pyzotero.egg-info → pyzotero-1.6.0}/PKG-INFO +1 -1
- {pyzotero-1.5.27 → pyzotero-1.6.0}/doc/index.rst +1 -1
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/_version.py +2 -2
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero/zotero.py +40 -15
- {pyzotero-1.5.27 → pyzotero-1.6.0/src/pyzotero.egg-info}/PKG-INFO +1 -1
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.coveragerc +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.github/ISSUE_TEMPLATE/usage_question.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.github/dependabot.yml +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.github/pull_request_template.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.gitignore +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/.readthedocs.yaml +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/AUTHORS +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/CITATION.cff +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/CONTRIBUTING.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/CONTRIBUTORS.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/LICENSE.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/README.md +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/__init__.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/doc/Makefile +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/doc/_templates/layout.html +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/doc/cat.png +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/doc/conf.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/dump_contributors.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/pyproject.toml +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/setup.cfg +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/setup.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero/__init__.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero/zotero_errors.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero.egg-info/SOURCES.txt +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero.egg-info/dependency_links.txt +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero.egg-info/requires.txt +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/src/pyzotero.egg-info/top_level.txt +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/__init__.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/attachments_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/citation_doc.xml +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/collection_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/collection_tags.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/collection_versions.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/collections_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/creation_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/groups_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/item_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/item_fields.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/item_file.pdf +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/item_template.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/item_types.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/item_versions.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/items_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/keys_doc.txt +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/api_responses/tags_doc.json +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/tests/test_zotero.py +0 -0
- {pyzotero-1.5.27 → pyzotero-1.6.0}/uv.lock +0 -0
|
@@ -23,7 +23,7 @@ Getting started (short version)
|
|
|
23
23
|
3. You'll also need [*]_ to get an **API key** from the Zotero `site <https://www.zotero.org/settings/keys/new>`_
|
|
24
24
|
4. Are you accessing your own Zotero library? Set``library_type`` to ``'user'``
|
|
25
25
|
5. Are you accessing a shared group library? Set``library_type`` to ``'group'``
|
|
26
|
-
6. **Read-only** access to your local Zotero library is available: set ``local=True
|
|
26
|
+
6. **Read-only** access to your local Zotero library is available: set ``local=True``
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
.. _hello-world:
|
|
@@ -24,8 +24,16 @@ import uuid
|
|
|
24
24
|
import zipfile
|
|
25
25
|
from collections import OrderedDict
|
|
26
26
|
from functools import wraps
|
|
27
|
-
from pathlib import Path
|
|
28
|
-
from urllib.parse import
|
|
27
|
+
from pathlib import Path, PurePosixPath
|
|
28
|
+
from urllib.parse import (
|
|
29
|
+
parse_qs,
|
|
30
|
+
parse_qsl,
|
|
31
|
+
quote,
|
|
32
|
+
unquote,
|
|
33
|
+
urlencode,
|
|
34
|
+
urlparse,
|
|
35
|
+
urlunparse,
|
|
36
|
+
)
|
|
29
37
|
|
|
30
38
|
import bibtexparser
|
|
31
39
|
import feedparser
|
|
@@ -153,11 +161,6 @@ def retrieve(func):
|
|
|
153
161
|
"""
|
|
154
162
|
if kwargs:
|
|
155
163
|
self.add_parameters(**kwargs)
|
|
156
|
-
res = func(self, *args)
|
|
157
|
-
parsed = urlparse(res)
|
|
158
|
-
querydict = parse_qs(parsed.query)
|
|
159
|
-
if not querydict.get("locale"):
|
|
160
|
-
self.add_parameters(locale=self.locale)
|
|
161
164
|
retrieved = self._retrieve_data(func(self, *args))
|
|
162
165
|
# we now always have links in the header response
|
|
163
166
|
self.links = self._extract_links()
|
|
@@ -277,8 +280,10 @@ class Zotero:
|
|
|
277
280
|
"""Store Zotero credentials"""
|
|
278
281
|
if not local:
|
|
279
282
|
self.endpoint = "https://api.zotero.org"
|
|
283
|
+
self.local = False
|
|
280
284
|
else:
|
|
281
285
|
self.endpoint = "http://localhost:23119/api"
|
|
286
|
+
self.local = True
|
|
282
287
|
if library_id and library_type:
|
|
283
288
|
self.library_id = library_id
|
|
284
289
|
# library_type determines whether query begins w. /users or /groups
|
|
@@ -326,6 +331,21 @@ class Zotero:
|
|
|
326
331
|
self.backoff = False
|
|
327
332
|
self.backoff_duration = 0.0
|
|
328
333
|
|
|
334
|
+
def _check_for_component(self, url, component):
|
|
335
|
+
"""Check a url path query fragment for a specific query parameter"""
|
|
336
|
+
if parse_qs(url).get(component):
|
|
337
|
+
return True
|
|
338
|
+
return False
|
|
339
|
+
|
|
340
|
+
def _striplocal(self, url):
|
|
341
|
+
if self.local:
|
|
342
|
+
parsed = urlparse(url)
|
|
343
|
+
purepath = PurePosixPath(unquote(parsed.path))
|
|
344
|
+
newpath = "/".join(purepath.parts[2:])
|
|
345
|
+
replaced = parsed._replace(path="/" + newpath)
|
|
346
|
+
return urlunparse(replaced)
|
|
347
|
+
return url
|
|
348
|
+
|
|
329
349
|
def _set_backoff(self, duration):
|
|
330
350
|
"""
|
|
331
351
|
Set a backoff
|
|
@@ -411,10 +431,15 @@ class Zotero:
|
|
|
411
431
|
self.self_link = request
|
|
412
432
|
# ensure that we wait if there's an active backoff
|
|
413
433
|
self._check_backoff()
|
|
414
|
-
if
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
434
|
+
# don't set locale if the url already contains it
|
|
435
|
+
if params and self.links:
|
|
436
|
+
if not self._check_for_component(self.links.get("next"), "locale"):
|
|
437
|
+
params["locale"] = self.locale
|
|
438
|
+
if not params and self.links:
|
|
439
|
+
if not self._check_for_component(self.links.get("next"), "locale"):
|
|
440
|
+
params = {"locale": self.locale}
|
|
441
|
+
else:
|
|
442
|
+
params = {}
|
|
418
443
|
self.request = requests.get(
|
|
419
444
|
url=full_url, headers=self.default_headers(), params=params
|
|
420
445
|
)
|
|
@@ -850,10 +875,10 @@ class Zotero:
|
|
|
850
875
|
@retrieve
|
|
851
876
|
def follow(self):
|
|
852
877
|
"""Return the result of the call to the URL in the 'Next' link"""
|
|
853
|
-
if self.links.get("next"):
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
878
|
+
if n := self.links.get("next"):
|
|
879
|
+
newurl = self._striplocal(n)
|
|
880
|
+
return newurl
|
|
881
|
+
return
|
|
857
882
|
|
|
858
883
|
def iterfollow(self):
|
|
859
884
|
"""Generator for self.follow()"""
|
|
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
|
|
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
|
|
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
|