format: use 4 spaces
This commit is contained in:
+1
-1
@@ -7,4 +7,4 @@ charset = utf-8
|
||||
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
from paperlib.cli import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
+36
-36
@@ -16,42 +16,42 @@ DEFAULT_CONFIG_FILENAME = "config.toml"
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class LibraryPaths:
|
||||
"""Resolved filesystem layout for a paper library."""
|
||||
"""Resolved filesystem layout for a paper library."""
|
||||
|
||||
root: Path
|
||||
config_dir: Path
|
||||
papers_dir: Path
|
||||
inbox_dir: Path
|
||||
db_dir: Path
|
||||
cache_dir: Path
|
||||
db_path: Path
|
||||
config_path: Path
|
||||
root: Path
|
||||
config_dir: Path
|
||||
papers_dir: Path
|
||||
inbox_dir: Path
|
||||
db_dir: Path
|
||||
cache_dir: Path
|
||||
db_path: Path
|
||||
config_path: Path
|
||||
|
||||
@classmethod
|
||||
def from_root(cls, root: Path) -> LibraryPaths:
|
||||
"""Build a standard library layout from a root directory."""
|
||||
resolved_root = root.expanduser().resolve()
|
||||
config_dir = resolved_root / DEFAULT_CONFIG_DIRNAME
|
||||
db_dir = resolved_root / DEFAULT_DB_DIRNAME
|
||||
return cls(
|
||||
root=resolved_root,
|
||||
config_dir=config_dir,
|
||||
papers_dir=resolved_root / DEFAULT_PAPERS_DIRNAME,
|
||||
inbox_dir=resolved_root / DEFAULT_INBOX_DIRNAME,
|
||||
db_dir=db_dir,
|
||||
cache_dir=resolved_root / DEFAULT_CACHE_DIRNAME,
|
||||
db_path=db_dir / DEFAULT_DB_FILENAME,
|
||||
config_path=config_dir / DEFAULT_CONFIG_FILENAME,
|
||||
)
|
||||
@classmethod
|
||||
def from_root(cls, root: Path) -> LibraryPaths:
|
||||
"""Build a standard library layout from a root directory."""
|
||||
resolved_root = root.expanduser().resolve()
|
||||
config_dir = resolved_root / DEFAULT_CONFIG_DIRNAME
|
||||
db_dir = resolved_root / DEFAULT_DB_DIRNAME
|
||||
return cls(
|
||||
root=resolved_root,
|
||||
config_dir=config_dir,
|
||||
papers_dir=resolved_root / DEFAULT_PAPERS_DIRNAME,
|
||||
inbox_dir=resolved_root / DEFAULT_INBOX_DIRNAME,
|
||||
db_dir=db_dir,
|
||||
cache_dir=resolved_root / DEFAULT_CACHE_DIRNAME,
|
||||
db_path=db_dir / DEFAULT_DB_FILENAME,
|
||||
config_path=config_dir / DEFAULT_CONFIG_FILENAME,
|
||||
)
|
||||
|
||||
def create_directories(self) -> None:
|
||||
"""Create the standard library directories if they do not exist."""
|
||||
for path in (
|
||||
self.root,
|
||||
self.config_dir,
|
||||
self.papers_dir,
|
||||
self.inbox_dir,
|
||||
self.db_dir,
|
||||
self.cache_dir,
|
||||
):
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
def create_directories(self) -> None:
|
||||
"""Create the standard library directories if they do not exist."""
|
||||
for path in (
|
||||
self.root,
|
||||
self.config_dir,
|
||||
self.papers_dir,
|
||||
self.inbox_dir,
|
||||
self.db_dir,
|
||||
self.cache_dir,
|
||||
):
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@@ -31,35 +31,36 @@ class DatabaseManager:
|
||||
with self._get_connection() as conn:
|
||||
# Main papers table
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS papers (
|
||||
paper_id TEXT PRIMARY KEY,
|
||||
source_type TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
title TEXT NOT NULL,
|
||||
authors_json TEXT NOT NULL, -- JSON array of authors
|
||||
published_date TEXT, -- ISO format
|
||||
updated_date TEXT, -- ISO format
|
||||
categories_json TEXT NOT NULL, -- JSON array of categories
|
||||
pdf_path TEXT,
|
||||
paper_md_path TEXT,
|
||||
summary_json_path TEXT,
|
||||
summary_md_path TEXT,
|
||||
imported_at TEXT NOT NULL, -- ISO format
|
||||
conversion_status TEXT NOT NULL,
|
||||
summary_status TEXT NOT NULL,
|
||||
tags_json TEXT NOT NULL, -- JSON array of tags
|
||||
notes TEXT NOT NULL,
|
||||
|
||||
-- Computed fields for search
|
||||
search_text TEXT, -- Full-text search content
|
||||
author_list TEXT, -- Space-separated authors for search
|
||||
category_list TEXT -- Space-separated categories for search
|
||||
)
|
||||
""")
|
||||
CREATE TABLE IF NOT EXISTS papers (
|
||||
paper_id TEXT PRIMARY KEY,
|
||||
source_type TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
title TEXT NOT NULL,
|
||||
authors_json TEXT NOT NULL, -- JSON array of authors
|
||||
published_date TEXT, -- ISO format
|
||||
updated_date TEXT, -- ISO format
|
||||
categories_json TEXT NOT NULL, -- JSON array of categories
|
||||
pdf_path TEXT,
|
||||
paper_md_path TEXT,
|
||||
summary_json_path TEXT,
|
||||
summary_md_path TEXT,
|
||||
imported_at TEXT NOT NULL, -- ISO format
|
||||
conversion_status TEXT NOT NULL,
|
||||
summary_status TEXT NOT NULL,
|
||||
tags_json TEXT NOT NULL, -- JSON array of tags
|
||||
notes TEXT NOT NULL,
|
||||
|
||||
-- Computed fields for search
|
||||
search_text TEXT, -- Full-text search content
|
||||
author_list TEXT, -- Space-separated authors for search
|
||||
category_list TEXT -- Space-separated categories
|
||||
)
|
||||
""")
|
||||
|
||||
# Create indexes for common queries
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_papers_source_type ON papers(source_type)"
|
||||
"CREATE INDEX IF NOT EXISTS idx_papers_source_type "
|
||||
"ON papers(source_type)"
|
||||
)
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_papers_source_id ON papers(source_id)"
|
||||
@@ -73,52 +74,51 @@ class DatabaseManager:
|
||||
"ON papers(summary_status)"
|
||||
)
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_papers_imported_at ON papers(imported_at)"
|
||||
"CREATE INDEX IF NOT EXISTS idx_papers_imported_at "
|
||||
"ON papers(imported_at)"
|
||||
)
|
||||
|
||||
# Full-text search virtual table
|
||||
conn.execute("""
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS papers_fts USING fts5(
|
||||
paper_id UNINDEXED,
|
||||
title,
|
||||
authors,
|
||||
search_text,
|
||||
categories,
|
||||
tags,
|
||||
notes,
|
||||
content='papers',
|
||||
content_rowid='rowid'
|
||||
)
|
||||
""")
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS papers_fts USING fts5(
|
||||
paper_id UNINDEXED,
|
||||
title,
|
||||
authors,
|
||||
search_text,
|
||||
categories,
|
||||
tags,
|
||||
notes
|
||||
)
|
||||
""")
|
||||
|
||||
def index_paper(self, metadata: PaperMetadata) -> None:
|
||||
"""Index a paper in the database."""
|
||||
import json
|
||||
|
||||
with self._get_connection() as conn:
|
||||
# Prepare data for insertion
|
||||
parts = [
|
||||
metadata.title,
|
||||
" ".join(metadata.authors),
|
||||
" ".join(metadata.categories),
|
||||
" ".join(metadata.tags),
|
||||
metadata.notes,
|
||||
]
|
||||
search_text = " ".join(parts)
|
||||
author_list = " ".join(metadata.authors)
|
||||
category_list = " ".join(metadata.categories)
|
||||
# Prepare data for insertion
|
||||
parts = [
|
||||
metadata.title,
|
||||
" ".join(metadata.authors),
|
||||
" ".join(metadata.categories),
|
||||
" ".join(metadata.tags),
|
||||
metadata.notes,
|
||||
]
|
||||
search_text = " ".join(parts)
|
||||
author_list = " ".join(metadata.authors)
|
||||
category_list = " ".join(metadata.categories)
|
||||
|
||||
# Insert or replace in main table
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT OR REPLACE INTO papers (
|
||||
paper_id, source_type, source_id, title, authors_json,
|
||||
published_date, updated_date, categories_json, pdf_path,
|
||||
paper_md_path, summary_json_path, summary_md_path,
|
||||
imported_at, conversion_status, summary_status,
|
||||
tags_json, notes, search_text, author_list, category_list
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
INSERT OR REPLACE INTO papers (
|
||||
paper_id, source_type, source_id, title, authors_json,
|
||||
published_date, updated_date, categories_json, pdf_path,
|
||||
paper_md_path, summary_json_path, summary_md_path,
|
||||
imported_at, conversion_status, summary_status,
|
||||
tags_json, notes, search_text, author_list, category_list
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
metadata.paper_id,
|
||||
metadata.source_type.value,
|
||||
@@ -150,10 +150,10 @@ class DatabaseManager:
|
||||
# Update FTS table
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT OR REPLACE INTO papers_fts (
|
||||
paper_id, title, authors, search_text, categories, tags, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
INSERT OR REPLACE INTO papers_fts (
|
||||
paper_id, title, authors, search_text, categories, tags, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
metadata.paper_id,
|
||||
metadata.title,
|
||||
@@ -226,12 +226,12 @@ class DatabaseManager:
|
||||
# Use FTS for full-text search
|
||||
cursor = conn.execute(
|
||||
"""
|
||||
SELECT papers.* FROM papers_fts
|
||||
JOIN papers ON papers.paper_id = papers_fts.paper_id
|
||||
WHERE papers_fts MATCH ?
|
||||
ORDER BY rank
|
||||
LIMIT ?
|
||||
""",
|
||||
SELECT papers.* FROM papers_fts
|
||||
JOIN papers ON papers.paper_id = papers_fts.paper_id
|
||||
WHERE papers_fts MATCH ?
|
||||
ORDER BY rank
|
||||
LIMIT ?
|
||||
""",
|
||||
(query, limit),
|
||||
)
|
||||
|
||||
@@ -257,7 +257,8 @@ class DatabaseManager:
|
||||
where_clause = f"{field} LIKE ?"
|
||||
params = [f"%{value}%"]
|
||||
|
||||
query = f"SELECT * FROM papers WHERE {where_clause} ORDER BY imported_at DESC LIMIT ?"
|
||||
order_by = "ORDER BY imported_at DESC LIMIT ?"
|
||||
query = f"SELECT * FROM papers WHERE {where_clause} {order_by}"
|
||||
params.append(limit)
|
||||
|
||||
with self._get_connection() as conn:
|
||||
@@ -284,7 +285,8 @@ class DatabaseManager:
|
||||
|
||||
# By conversion status
|
||||
cursor = conn.execute(
|
||||
"SELECT conversion_status, COUNT(*) as count FROM papers GROUP BY conversion_status"
|
||||
"SELECT conversion_status, COUNT(*) as count FROM papers "
|
||||
"GROUP BY conversion_status"
|
||||
)
|
||||
stats["by_conversion_status"] = {
|
||||
row["conversion_status"]: row["count"] for row in cursor
|
||||
@@ -292,7 +294,8 @@ class DatabaseManager:
|
||||
|
||||
# By summary status
|
||||
cursor = conn.execute(
|
||||
"SELECT summary_status, COUNT(*) as count FROM papers GROUP BY summary_status"
|
||||
"SELECT summary_status, COUNT(*) as count FROM papers "
|
||||
"GROUP BY summary_status"
|
||||
)
|
||||
stats["by_summary_status"] = {
|
||||
row["summary_status"]: row["count"] for row in cursor
|
||||
|
||||
Reference in New Issue
Block a user