pyzotero 1.7.0__tar.gz → 1.7.2__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 (34) hide show
  1. {pyzotero-1.7.0 → pyzotero-1.7.2}/PKG-INFO +7 -1
  2. {pyzotero-1.7.0 → pyzotero-1.7.2}/README.md +6 -0
  3. {pyzotero-1.7.0 → pyzotero-1.7.2}/doc/index.rst +7 -0
  4. {pyzotero-1.7.0 → pyzotero-1.7.2}/pyproject.toml +1 -1
  5. {pyzotero-1.7.0 → pyzotero-1.7.2}/src/pyzotero/cli.py +52 -5
  6. {pyzotero-1.7.0 → pyzotero-1.7.2}/LICENSE.md +0 -0
  7. {pyzotero-1.7.0 → pyzotero-1.7.2}/doc/Makefile +0 -0
  8. {pyzotero-1.7.0 → pyzotero-1.7.2}/doc/_templates/layout.html +0 -0
  9. {pyzotero-1.7.0 → pyzotero-1.7.2}/doc/cat.png +0 -0
  10. {pyzotero-1.7.0 → pyzotero-1.7.2}/doc/conf.py +0 -0
  11. {pyzotero-1.7.0 → pyzotero-1.7.2}/src/pyzotero/__init__.py +0 -0
  12. {pyzotero-1.7.0 → pyzotero-1.7.2}/src/pyzotero/filetransport.py +0 -0
  13. {pyzotero-1.7.0 → pyzotero-1.7.2}/src/pyzotero/zotero.py +0 -0
  14. {pyzotero-1.7.0 → pyzotero-1.7.2}/src/pyzotero/zotero_errors.py +0 -0
  15. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/__init__.py +0 -0
  16. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/attachments_doc.json +0 -0
  17. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/citation_doc.xml +0 -0
  18. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/collection_doc.json +0 -0
  19. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/collection_tags.json +0 -0
  20. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/collection_versions.json +0 -0
  21. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/collections_doc.json +0 -0
  22. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/creation_doc.json +0 -0
  23. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/groups_doc.json +0 -0
  24. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/item_doc.json +0 -0
  25. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/item_fields.json +0 -0
  26. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/item_file.pdf +0 -0
  27. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/item_template.json +0 -0
  28. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/item_types.json +0 -0
  29. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/item_versions.json +0 -0
  30. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/items_doc.json +0 -0
  31. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/keys_doc.txt +0 -0
  32. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/api_responses/tags_doc.json +0 -0
  33. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/test_async.py +0 -0
  34. {pyzotero-1.7.0 → pyzotero-1.7.2}/tests/test_zotero.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyzotero
3
- Version: 1.7.0
3
+ Version: 1.7.2
4
4
  Summary: Python wrapper for the Zotero API
5
5
  Keywords: Zotero,DH
6
6
  Author: Stephan Hügel
@@ -126,6 +126,12 @@ pyzotero listcollections
126
126
  pyzotero itemtypes
127
127
  ```
128
128
 
129
+ ## Search Behaviour
130
+
131
+ By default, `pyzotero search` searches only top-level item titles and metadata fields.
132
+
133
+ When the `--fulltext` flag is used, the search expands to include all full-text indexed content, including PDFs and other attachments. Since most full-text content comes from PDF attachments rather than top-level items, the CLI automatically retrieves the parent bibliographic items for any matching attachments. This ensures you receive useful bibliographic records (journal articles, books, etc.) rather than raw attachment items.
134
+
129
135
  ## Output Format
130
136
 
131
137
  By default, the CLI outputs human-readable text with a subset of metadata including:
@@ -59,6 +59,12 @@ pyzotero listcollections
59
59
  pyzotero itemtypes
60
60
  ```
61
61
 
62
+ ## Search Behaviour
63
+
64
+ By default, `pyzotero search` searches only top-level item titles and metadata fields.
65
+
66
+ When the `--fulltext` flag is used, the search expands to include all full-text indexed content, including PDFs and other attachments. Since most full-text content comes from PDF attachments rather than top-level items, the CLI automatically retrieves the parent bibliographic items for any matching attachments. This ensures you receive useful bibliographic records (journal articles, books, etc.) rather than raw attachment items.
67
+
62
68
  ## Output Format
63
69
 
64
70
  By default, the CLI outputs human-readable text with a subset of metadata including:
@@ -152,6 +152,13 @@ List available item types:
152
152
 
153
153
  pyzotero itemtypes
154
154
 
155
+ Search Behaviour
156
+ ----------------
157
+
158
+ By default, ``pyzotero search`` searches only top-level item titles and metadata fields.
159
+
160
+ When the ``--fulltext`` flag is used, the search expands to include all full-text indexed content, including PDFs and other attachments. Since most full-text content comes from PDF attachments rather than top-level items, the CLI automatically retrieves the parent bibliographic items for any matching attachments. This ensures you receive useful bibliographic records (journal articles, books, etc.) rather than raw attachment items.
161
+
155
162
  Output Format
156
163
  -------------
157
164
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyzotero"
3
- version = "1.7.0"
3
+ version = "1.7.2"
4
4
  description = "Python wrapper for the Zotero API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -5,7 +5,8 @@ import sys
5
5
 
6
6
  import click
7
7
 
8
- from pyzotero import zotero
8
+ from pyzotero import __version__, zotero
9
+ from pyzotero.zotero import chunks
9
10
 
10
11
 
11
12
  def _get_zotero_client(locale="en-US"):
@@ -14,6 +15,7 @@ def _get_zotero_client(locale="en-US"):
14
15
 
15
16
 
16
17
  @click.group()
18
+ @click.version_option(version=__version__, prog_name="pyzotero")
17
19
  @click.option(
18
20
  "--locale",
19
21
  default="en-US",
@@ -36,7 +38,7 @@ def main(ctx, locale):
36
38
  @click.option(
37
39
  "--fulltext",
38
40
  is_flag=True,
39
- help="Enable full-text search (qmode='everything')",
41
+ help="Search full-text content including PDFs. Retrieves parent items when attachments match.",
40
42
  )
41
43
  @click.option(
42
44
  "--itemtype",
@@ -63,6 +65,12 @@ def main(ctx, locale):
63
65
  def search(ctx, query, fulltext, itemtype, collection, limit, output_json): # noqa: PLR0912, PLR0915
64
66
  """Search local Zotero library.
65
67
 
68
+ By default, searches top-level items in titles and metadata.
69
+
70
+ When --fulltext is enabled, searches all items including attachment content
71
+ (PDFs, documents, etc.). If a match is found in an attachment, the parent
72
+ bibliographic item is retrieved and included in results.
73
+
66
74
  Examples:
67
75
  pyzotero search -q "machine learning"
68
76
 
@@ -92,8 +100,43 @@ def search(ctx, query, fulltext, itemtype, collection, limit, output_json): # n
92
100
  # Join multiple item types with || for OR search
93
101
  params["itemType"] = " || ".join(itemtype)
94
102
 
95
- # Execute search using collection_items_top() if collection specified, otherwise top()
96
- if collection:
103
+ # Execute search
104
+ # When fulltext is enabled, use items() or collection_items() to get both
105
+ # top-level items and attachments. Otherwise use top() or collection_items_top()
106
+ # to only get top-level items.
107
+ if fulltext:
108
+ if collection:
109
+ results = zot.collection_items(collection, **params)
110
+ else:
111
+ results = zot.items(**params)
112
+
113
+ # When using fulltext, we need to retrieve parent items for any attachments
114
+ # that matched, since most full-text content comes from PDFs and other attachments
115
+ top_level_items = []
116
+ attachment_items = []
117
+
118
+ for item in results:
119
+ data = item.get("data", {})
120
+ if "parentItem" in data:
121
+ attachment_items.append(item)
122
+ else:
123
+ top_level_items.append(item)
124
+
125
+ # Retrieve parent items for attachments in batches of 50
126
+ parent_items = []
127
+ if attachment_items:
128
+ parent_ids = list(
129
+ {item["data"]["parentItem"] for item in attachment_items}
130
+ )
131
+ for chunk in chunks(parent_ids, 50):
132
+ parent_items.extend(zot.get_subset(chunk))
133
+
134
+ # Combine top-level items and parent items, removing duplicates by key
135
+ all_items = top_level_items + parent_items
136
+ items_dict = {item["data"]["key"]: item for item in all_items}
137
+ results = list(items_dict.values())
138
+ # Non-fulltext search: use top() or collection_items_top() as before
139
+ elif collection:
97
140
  results = zot.collection_items_top(collection, **params)
98
141
  else:
99
142
  results = zot.top(**params)
@@ -168,7 +211,11 @@ def search(ctx, query, fulltext, itemtype, collection, limit, output_json): # n
168
211
 
169
212
  # Output results
170
213
  if output_json:
171
- click.echo(json.dumps(output_items, indent=2))
214
+ click.echo(
215
+ json.dumps(
216
+ {"count": len(output_items), "items": output_items}, indent=2
217
+ )
218
+ )
172
219
  else:
173
220
  click.echo(f"\nFound {len(results)} items:\n")
174
221
  for idx, item_obj in enumerate(output_items, 1):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes