zotero_db
zocrates.rag.zotero_db ¶
Read-only access layer for the Zotero SQLite database.
All queries use a URI connection opened in read-only mode to guarantee we never accidentally write to the user's library.
ARXIV_ID_PATTERN
module-attribute
¶
_PUBLICATION_FIELDS
module-attribute
¶
_PUBLICATION_FIELDS = ('publicationTitle', 'proceedingsTitle', 'bookTitle', 'repository', 'websiteTitle', 'blogTitle', 'publisher', 'institution', 'university', 'encyclopediaTitle', 'dictionaryTitle')
ZoteroAttachment
dataclass
¶
An attachment (PDF, HTML, etc.) linked to a Zotero item.
ZoteroDB ¶
Read-only façade over zotero.sqlite.
Initialize ZoteroDB.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sqlite_path
|
Path
|
Absolute path to the |
required |
storage_dir
|
Path
|
Absolute path to the Zotero |
required |
Source code in zocrates/rag/zotero_db.py
get_active_item_keys ¶
Return a set of item keys that exist in the library and are not deleted or parent-deleted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_keys
|
list[str]
|
List of Zotero item keys (can include regular items, attachments, notes). |
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of active item keys. |
Source code in zocrates/rag/zotero_db.py
get_all_arxiv_ids ¶
Return a set of all normalized arXiv IDs across active non-deleted items in the library.
Source code in zocrates/rag/zotero_db.py
get_all_attachments ¶
Return all file attachments with a parent item across the library.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content_types
|
tuple[str, ...]
|
Tuple of MIME types to include. |
('application/pdf', 'text/html', 'text/markdown', 'text/plain')
|
Returns:
| Type | Description |
|---|---|
list[ZoteroAttachment]
|
List of |
Source code in zocrates/rag/zotero_db.py
get_all_convertible_attachments ¶
Return all valid document attachments in the library in a single fast query.
Source code in zocrates/rag/zotero_db.py
get_all_dedup_records ¶
Return lightweight records (title, year, creators, doi, arxiv_id) for active items for fuzzy dedup.
Source code in zocrates/rag/zotero_db.py
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 | |
get_all_dois ¶
Return a set of all normalized DOIs across active non-deleted items in the library.
Source code in zocrates/rag/zotero_db.py
get_all_item_relations ¶
Return all explicit item relations as (source_key, target_key) pairs.
Source code in zocrates/rag/zotero_db.py
get_all_items ¶
Return all non-attachment, non-deleted items in the library.
Returns:
| Type | Description |
|---|---|
list[ZoteroItem]
|
List of fully populated |
Source code in zocrates/rag/zotero_db.py
get_all_notes ¶
Return all notes (standalone and child notes) in the library.
Returns:
| Type | Description |
|---|---|
list[ZoteroNote]
|
List of |
Source code in zocrates/rag/zotero_db.py
get_all_titles ¶
Return a list of all titles across active non-deleted items in the library.
Source code in zocrates/rag/zotero_db.py
get_attachment_by_id ¶
Fetch a single file attachment by its item ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_id
|
int
|
Numeric Zotero item ID of the attachment. |
required |
Returns:
| Type | Description |
|---|---|
ZoteroAttachment | None
|
|
ZoteroAttachment | None
|
or deleted. |
Source code in zocrates/rag/zotero_db.py
get_attachment_by_key ¶
Fetch a single file attachment by its item key or parent item key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_key
|
str
|
Zotero item key string (attachment key or parent item key). |
required |
Returns:
| Type | Description |
|---|---|
ZoteroAttachment | None
|
|
Source code in zocrates/rag/zotero_db.py
get_attachments ¶
get_attachments(parent_item_id, content_types=('application/pdf', 'text/html', 'text/markdown', 'text/plain'))
Return file attachments for a given parent item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent_item_id
|
int
|
Numeric ID of the parent Zotero item. |
required |
content_types
|
tuple[str, ...]
|
Tuple of MIME types to include; defaults to PDF, HTML, Markdown, and plain text. |
('application/pdf', 'text/html', 'text/markdown', 'text/plain')
|
Returns:
| Type | Description |
|---|---|
list[ZoteroAttachment]
|
List of |
list[ZoteroAttachment]
|
paths ( |
list[ZoteroAttachment]
|
The |
list[ZoteroAttachment]
|
available, otherwise the attachment filename. |
Source code in zocrates/rag/zotero_db.py
get_item ¶
Fetch a single item with full metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_id
|
int
|
Numeric Zotero item ID. |
required |
Returns:
| Type | Description |
|---|---|
ZoteroItem | None
|
Fully populated |
ZoteroItem | None
|
and relations), or |
Source code in zocrates/rag/zotero_db.py
get_item_by_key ¶
Fetch a single item by its string key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_key
|
str
|
Zotero item key string (e.g. '89X2ELQ6'). |
required |
Returns:
| Type | Description |
|---|---|
ZoteroItem | None
|
Fully populated |
Source code in zocrates/rag/zotero_db.py
get_item_date_modified ¶
Fetch the last modified timestamp for an item as timezone-aware UTC datetime.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_key
|
str
|
8-character Zotero alphanumeric key. |
required |
Returns:
| Type | Description |
|---|---|
datetime | None
|
Timezone-aware UTC datetime, or None if item not found. |
Source code in zocrates/rag/zotero_db.py
get_item_keys_in_collection ¶
Return the unique item keys for all items belonging to a collection name or key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection_name
|
str
|
Name or key of the collection. |
required |
recursive
|
bool
|
If True and parentCollectionID exists, includes items in all subcollections. |
True
|
Returns:
| Type | Description |
|---|---|
list[str]
|
List of unique item keys. |
Source code in zocrates/rag/zotero_db.py
get_item_relations ¶
Return target item keys related to the specified item.
Source code in zocrates/rag/zotero_db.py
get_item_tags ¶
Return tag names for an item, optionally filtered by tag type (0=user, 1=automatic).
Source code in zocrates/rag/zotero_db.py
get_items_by_ids ¶
Fetch multiple items by their numeric IDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_ids
|
list[int]
|
List of numeric Zotero item IDs. |
required |
Returns:
| Type | Description |
|---|---|
list[ZoteroItem]
|
List of fully populated |
list[ZoteroItem]
|
tags, and collections). Items not found or deleted are silently |
list[ZoteroItem]
|
omitted. |
Source code in zocrates/rag/zotero_db.py
get_new_item_ids_since ¶
Return item IDs created after last_seen_item_id for incremental sync.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
last_seen_item_id
|
int
|
The highest item ID already processed. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
Sorted list of numeric item IDs greater than |
list[int]
|
that are not attachments, notes, or deleted items. |
Source code in zocrates/rag/zotero_db.py
get_note_by_id ¶
Fetch a single note by note item ID.
Source code in zocrates/rag/zotero_db.py
get_note_by_key ¶
Fetch a single note by its Zotero item key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
note_key
|
str
|
The alphanumeric Zotero item key of the note. |
required |
Returns:
| Type | Description |
|---|---|
ZoteroNote | None
|
A |
ZoteroNote | None
|
or the item has been deleted. |
Source code in zocrates/rag/zotero_db.py
get_notes_for_item ¶
Return child notes attached to a specific parent item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent_item_id
|
int
|
Numeric ID of the parent Zotero item. |
required |
Returns:
| Type | Description |
|---|---|
list[ZoteroNote]
|
List of |
Source code in zocrates/rag/zotero_db.py
get_stale_item_keys ¶
Identify cached items whose Zotero metadata has been modified since conversion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
converted_map
|
dict[str, str]
|
Mapping of attachment/note item_key -> converted_at ISO string. |
required |
key_to_atts
|
dict[str, list[str]]
|
Mapping of query key (parent_item_key or direct item_key) to list of associated attachment/note item_keys. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Sorted, unique list of attachment/note item_keys whose metadata is stale. |
Source code in zocrates/rag/zotero_db.py
get_standalone_attachments ¶
get_standalone_attachments(content_types=('application/pdf', 'text/html', 'text/markdown', 'text/plain'))
Return standalone file attachments (attachments without a parent item).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content_types
|
tuple[str, ...]
|
Tuple of MIME types to include. |
('application/pdf', 'text/html', 'text/markdown', 'text/plain')
|
Returns:
| Type | Description |
|---|---|
list[ZoteroAttachment]
|
List of |
Source code in zocrates/rag/zotero_db.py
get_standalone_notes ¶
Return top-level standalone notes (notes without a parent item).
Returns:
| Type | Description |
|---|---|
list[ZoteroNote]
|
List of |
Source code in zocrates/rag/zotero_db.py
invalidate_schema_cache ¶
is_item_active ¶
Check if a single item key exists and is not deleted (or parent-deleted).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_key
|
str
|
Zotero item key. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the item exists and is active, False otherwise. |
Source code in zocrates/rag/zotero_db.py
ZoteroItem
dataclass
¶
ZoteroItem(item_id, item_key, item_type, title, creators=list(), year=None, publication=None, doi=None, url=None, abstract=None, tags=list(), collections=list(), relations=list(), arxiv_id=None)
Lightweight representation of a Zotero library item.
ZoteroNote
dataclass
¶
A Zotero note item (standalone or attached to a parent item).
_cleanup_sqlite_snapshots ¶
Remove all cached snapshot temp files (registered via atexit).
Source code in zocrates/rag/zotero_db.py
_get_connection ¶
Resolve and open a raw SQLite connection to the Zotero database.
Source code in zocrates/rag/zotero_db.py
_is_pid_alive ¶
Check whether a process with the given PID is currently alive.
Source code in zocrates/rag/zotero_db.py
_open_db ¶
Open the Zotero SQLite DB with a read-correct, lock-safe strategy.
Tiered connection strategy (WAL-correct as of the fresh-profile fix):
mode=ro: the correct view whenever SQLite can take the shared read path — Zotero running in WAL mode (readers never block writers under WAL), or a cleanly closed database. A read-only connection sees committed WAL frames, so un-checkpointed data is visible.- Snapshot copy: when
mode=rofails (e.g. an unclean Zotero shutdown leaves an un-checkpointed-walsidecar with no-shm— a read-only connection cannot recover the WAL and reports "database is locked"), the DB plus its-wal/-journalsidecars are copied to a private temp file and opened read-write so SQLite performs WAL recovery on the copy. The snapshot is cached per source path and invalidated whenever the main file mtime or WAL size changes (static while Zotero is closed, so the copy cost is paid at most once per Zotero session state). immutable=1last resort (legacy behavior): bypasses OS locks but silently ignores WAL journals — only reached when both strategies above fail, e.g. truly read-only filesystems.
immutable=1 alone is NOT sufficient in general: Zotero writes into
zotero.sqlite-wal and only merges into the main file on checkpoint
(typically at shutdown), so a fresh session's committed items can exist
exclusively in the WAL. Reading the main file with immutable=1 then
reports an empty library even though the user sees items in Zotero.
The file path is URL-encoded because Zotero data directories may contain spaces or special characters that break SQLite URI parameter parsing.
Must be used as a context manager (with _open_db(path) as conn:).
The connection and OS file locks are deterministically closed on exit.
Source code in zocrates/rag/zotero_db.py
_open_snapshot_connection ¶
Open a private recovered copy of the Zotero DB (WAL fallback tier).
Copies the main DB plus -wal / -journal sidecars into a private
temp directory and opens the copy read-write, letting SQLite recover
committed WAL frames on open. Cached per source path until the main
file mtime or WAL size changes (the fallback regime is by definition a
static, Zotero-closed state, so the copy cost is paid once).
Source code in zocrates/rag/zotero_db.py
_parse_utc_datetime ¶
Parse a date string into a timezone-aware UTC datetime.
Source code in zocrates/rag/zotero_db.py
_sqlite_snapshot_signature ¶
Signature used to invalidate cached snapshots: main mtime + WAL size + WAL mtime.
Source code in zocrates/rag/zotero_db.py
_sweep_stale_sqlite_snapshots ¶
Scan and clean up orphaned snapshot temp directories from dead processes or legacy runs.
Source code in zocrates/rag/zotero_db.py
extract_arxiv_id ¶
Extract and normalize an arXiv ID from extra text, URL, or DOI.
Source code in zocrates/rag/zotero_db.py
extract_year ¶
Extract a 4-digit year string from a Zotero date value.
Source code in zocrates/rag/zotero_db.py
normalize_arxiv_id ¶
Normalize an arXiv identifier by stripping URL prefixes, 'arxiv:' tags, and version suffixes.
Source code in zocrates/rag/zotero_db.py
normalize_doi ¶
Normalize DOI by stripping standard URI and resolver prefixes and lowercasing.