zotkit 0.2.0__tar.gz → 0.3.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zotkit
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Headless Zotero library management: Web API CRUD plus direct WebDAV attachment upload/download — no desktop app required
5
5
  Author: Shawn
6
6
  License-Expression: MIT
@@ -20,7 +20,12 @@ Dynamic: license-file
20
20
 
21
21
  # zotkit
22
22
 
23
+ [![PyPI](https://img.shields.io/pypi/v/zotkit)](https://pypi.org/project/zotkit/)
24
+ [![Python](https://img.shields.io/pypi/pyversions/zotkit)](https://pypi.org/project/zotkit/)
25
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
26
+
23
27
  **Headless Zotero library management — no desktop app required.**
28
+ [中文速览 →](README.zh-CN.md)
24
29
 
25
30
  "Headless" simply means zotkit never needs the Zotero app (or any window) open: it is a
26
31
  Python library + CLI that talks straight to the
@@ -70,6 +75,9 @@ Copy [`.env.example`](.env.example) to `./.env`, `~/.config/zotkit/env`, or any
70
75
  `attach`/`fetch` automatically use Zotero Storage through the Web API's upload/download
71
76
  endpoints instead. The storage mode is detected from your `.env`, nothing to configure.
72
77
 
78
+ After filling it in, run **`zotkit doctor`** — it validates the config file, API
79
+ access, and attachment storage, and tells you exactly what to fix if anything fails.
80
+
73
81
  Optionally, copy [`conventions.example.toml`](conventions.example.toml) to
74
82
  `conventions.toml` next to your `.env` to define a namespaced tag taxonomy
75
83
  (`field:physics`, `status:to-read`, …). With it in place, `zotkit create` / `zotkit tag`
@@ -160,6 +168,14 @@ Details in [`docs/webdav-format.md`](docs/webdav-format.md).
160
168
  The format was determined by interoperability inspection of the author's own library.
161
169
  This project is not affiliated with or endorsed by Zotero.
162
170
 
171
+ ## Limits & roadmap
172
+
173
+ - `find` currently lists the library client-side — instant for hundreds of items,
174
+ sluggish for many thousands. Server-side search is planned.
175
+ - Group libraries should work for item operations (untested); WebDAV file sync is
176
+ personal-libraries-only (a Zotero limitation).
177
+ - Planned: an MCP server wrapper, server-side search, DOI/arXiv one-shot import.
178
+
163
179
  ## License
164
180
 
165
181
  [MIT](LICENSE). If you build on the WebDAV implementation, a link back is appreciated.
@@ -1,6 +1,11 @@
1
1
  # zotkit
2
2
 
3
+ [![PyPI](https://img.shields.io/pypi/v/zotkit)](https://pypi.org/project/zotkit/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/zotkit)](https://pypi.org/project/zotkit/)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
6
+
3
7
  **Headless Zotero library management — no desktop app required.**
8
+ [中文速览 →](README.zh-CN.md)
4
9
 
5
10
  "Headless" simply means zotkit never needs the Zotero app (or any window) open: it is a
6
11
  Python library + CLI that talks straight to the
@@ -50,6 +55,9 @@ Copy [`.env.example`](.env.example) to `./.env`, `~/.config/zotkit/env`, or any
50
55
  `attach`/`fetch` automatically use Zotero Storage through the Web API's upload/download
51
56
  endpoints instead. The storage mode is detected from your `.env`, nothing to configure.
52
57
 
58
+ After filling it in, run **`zotkit doctor`** — it validates the config file, API
59
+ access, and attachment storage, and tells you exactly what to fix if anything fails.
60
+
53
61
  Optionally, copy [`conventions.example.toml`](conventions.example.toml) to
54
62
  `conventions.toml` next to your `.env` to define a namespaced tag taxonomy
55
63
  (`field:physics`, `status:to-read`, …). With it in place, `zotkit create` / `zotkit tag`
@@ -140,6 +148,14 @@ Details in [`docs/webdav-format.md`](docs/webdav-format.md).
140
148
  The format was determined by interoperability inspection of the author's own library.
141
149
  This project is not affiliated with or endorsed by Zotero.
142
150
 
151
+ ## Limits & roadmap
152
+
153
+ - `find` currently lists the library client-side — instant for hundreds of items,
154
+ sluggish for many thousands. Server-side search is planned.
155
+ - Group libraries should work for item operations (untested); WebDAV file sync is
156
+ personal-libraries-only (a Zotero limitation).
157
+ - Planned: an MCP server wrapper, server-side search, DOI/arXiv one-shot import.
158
+
143
159
  ## License
144
160
 
145
161
  [MIT](LICENSE). If you build on the WebDAV implementation, a link back is appreciated.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "zotkit"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "Headless Zotero library management: Web API CRUD plus direct WebDAV attachment upload/download — no desktop app required"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -2,4 +2,4 @@
2
2
  from .core import Conventions, TagConventionError, Zot, lint_tags, load_conventions
3
3
 
4
4
  __all__ = ["Zot", "lint_tags", "load_conventions", "Conventions", "TagConventionError"]
5
- __version__ = "0.2.0"
5
+ __version__ = "0.3.0"
@@ -10,7 +10,8 @@ import json
10
10
  import sys
11
11
  from pathlib import Path
12
12
 
13
- from .core import Zot, lint_tags, load_conventions
13
+ from . import __version__
14
+ from .core import Zot, lint_tags, load_conventions, load_env
14
15
 
15
16
 
16
17
  def _print_items(rows):
@@ -21,10 +22,58 @@ def _print_items(rows):
21
22
  print(f"\n{len(rows)} match(es)")
22
23
 
23
24
 
25
+ def _doctor() -> int:
26
+ """Validate the whole setup; each failing check explains how to fix it."""
27
+ import httpx
28
+ from urllib.parse import urlsplit
29
+ print(f"zotkit {__version__}")
30
+ try:
31
+ env = load_env()
32
+ except FileNotFoundError as e:
33
+ print(f"✗ config: {e}")
34
+ return 1
35
+ print(f"✓ config: {env['_env_path']}")
36
+ conv = load_conventions()
37
+ print(f"✓ conventions: {'enforced' if conv else 'none configured (tags unrestricted)'}")
38
+ try:
39
+ z = Zot()
40
+ access = z.z.key_info().get("access", {}).get("user", {})
41
+ n = z.z.count_items()
42
+ print(f"✓ Zotero API: library {env['ZOTERO_LIBRARY_ID']} reachable, {n} items, "
43
+ f"write access: {bool(access.get('write'))}")
44
+ except Exception as e:
45
+ print(f"✗ Zotero API: {e}\n check ZOTERO_LIBRARY_ID (numeric userID) and "
46
+ f"ZOTERO_API_KEY at https://www.zotero.org/settings/keys")
47
+ return 1
48
+ if "WEBDAV_URL" in env:
49
+ base, auth = z._webdav()
50
+ host = urlsplit(base).netloc
51
+ try:
52
+ with httpx.Client(auth=auth, timeout=30) as c:
53
+ r1 = c.put(f"{base}/zotkit-doctor-probe.txt", content=b"zotkit doctor probe")
54
+ c.delete(f"{base}/zotkit-doctor-probe.txt")
55
+ if r1.status_code in (200, 201, 204):
56
+ print(f"✓ WebDAV: {host} writable — attachments use WebDAV")
57
+ else:
58
+ print(f"✗ WebDAV: PUT returned {r1.status_code} — check credentials and "
59
+ f"that WEBDAV_URL ends with /zotero/")
60
+ return 1
61
+ except Exception as e:
62
+ print(f"✗ WebDAV: {e}")
63
+ return 1
64
+ else:
65
+ print("✓ attachments: Zotero Storage mode (no WEBDAV_* configured)")
66
+ print("all good ✓")
67
+ return 0
68
+
69
+
24
70
  def main(argv=None):
25
71
  ap = argparse.ArgumentParser(prog="zotkit", description="Headless Zotero library CLI")
72
+ ap.add_argument("--version", action="version", version=f"zotkit {__version__}")
26
73
  sub = ap.add_subparsers(dest="cmd", required=True)
27
74
 
75
+ sub.add_parser("doctor", help="validate setup: config, API access, attachment storage")
76
+
28
77
  p = sub.add_parser("find", help="search items by title/tag/collection")
29
78
  p.add_argument("--title"); p.add_argument("--tag"); p.add_argument("--collection")
30
79
 
@@ -60,6 +109,9 @@ def main(argv=None):
60
109
 
61
110
  a = ap.parse_args(argv)
62
111
 
112
+ if a.cmd == "doctor":
113
+ return _doctor()
114
+
63
115
  if a.cmd == "lint":
64
116
  conv = load_conventions()
65
117
  if conv is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zotkit
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Headless Zotero library management: Web API CRUD plus direct WebDAV attachment upload/download — no desktop app required
5
5
  Author: Shawn
6
6
  License-Expression: MIT
@@ -20,7 +20,12 @@ Dynamic: license-file
20
20
 
21
21
  # zotkit
22
22
 
23
+ [![PyPI](https://img.shields.io/pypi/v/zotkit)](https://pypi.org/project/zotkit/)
24
+ [![Python](https://img.shields.io/pypi/pyversions/zotkit)](https://pypi.org/project/zotkit/)
25
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
26
+
23
27
  **Headless Zotero library management — no desktop app required.**
28
+ [中文速览 →](README.zh-CN.md)
24
29
 
25
30
  "Headless" simply means zotkit never needs the Zotero app (or any window) open: it is a
26
31
  Python library + CLI that talks straight to the
@@ -70,6 +75,9 @@ Copy [`.env.example`](.env.example) to `./.env`, `~/.config/zotkit/env`, or any
70
75
  `attach`/`fetch` automatically use Zotero Storage through the Web API's upload/download
71
76
  endpoints instead. The storage mode is detected from your `.env`, nothing to configure.
72
77
 
78
+ After filling it in, run **`zotkit doctor`** — it validates the config file, API
79
+ access, and attachment storage, and tells you exactly what to fix if anything fails.
80
+
73
81
  Optionally, copy [`conventions.example.toml`](conventions.example.toml) to
74
82
  `conventions.toml` next to your `.env` to define a namespaced tag taxonomy
75
83
  (`field:physics`, `status:to-read`, …). With it in place, `zotkit create` / `zotkit tag`
@@ -160,6 +168,14 @@ Details in [`docs/webdav-format.md`](docs/webdav-format.md).
160
168
  The format was determined by interoperability inspection of the author's own library.
161
169
  This project is not affiliated with or endorsed by Zotero.
162
170
 
171
+ ## Limits & roadmap
172
+
173
+ - `find` currently lists the library client-side — instant for hundreds of items,
174
+ sluggish for many thousands. Server-side search is planned.
175
+ - Group libraries should work for item operations (untested); WebDAV file sync is
176
+ personal-libraries-only (a Zotero limitation).
177
+ - Planned: an MCP server wrapper, server-side search, DOI/arXiv one-shot import.
178
+
163
179
  ## License
164
180
 
165
181
  [MIT](LICENSE). If you build on the WebDAV implementation, a link back is appreciated.
File without changes
File without changes
File without changes