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.
- {zotkit-0.2.0/zotkit.egg-info → zotkit-0.3.0}/PKG-INFO +17 -1
- {zotkit-0.2.0 → zotkit-0.3.0}/README.md +16 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/pyproject.toml +1 -1
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit/__init__.py +1 -1
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit/cli.py +53 -1
- {zotkit-0.2.0 → zotkit-0.3.0/zotkit.egg-info}/PKG-INFO +17 -1
- {zotkit-0.2.0 → zotkit-0.3.0}/LICENSE +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/setup.cfg +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit/core.py +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit.egg-info/SOURCES.txt +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit.egg-info/dependency_links.txt +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit.egg-info/entry_points.txt +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit.egg-info/requires.txt +0 -0
- {zotkit-0.2.0 → zotkit-0.3.0}/zotkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zotkit
|
|
3
|
-
Version: 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
|
+
[](https://pypi.org/project/zotkit/)
|
|
24
|
+
[](https://pypi.org/project/zotkit/)
|
|
25
|
+
[](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
|
+
[](https://pypi.org/project/zotkit/)
|
|
4
|
+
[](https://pypi.org/project/zotkit/)
|
|
5
|
+
[](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.
|
|
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"
|
|
@@ -10,7 +10,8 @@ import json
|
|
|
10
10
|
import sys
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
|
|
13
|
-
from .
|
|
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.
|
|
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
|
+
[](https://pypi.org/project/zotkit/)
|
|
24
|
+
[](https://pypi.org/project/zotkit/)
|
|
25
|
+
[](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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|