format: use 4 spaces

This commit is contained in:
2026-04-17 15:24:15 -04:00
parent 82e4ed6fec
commit 06eff1c255
4 changed files with 112 additions and 109 deletions
+1 -1
View File
@@ -7,4 +7,4 @@ charset = utf-8
[*.py]
indent_style = space
indent_size = 2
indent_size = 4
+1 -1
View File
@@ -3,4 +3,4 @@
from paperlib.cli import main
if __name__ == "__main__":
main()
main()
+36 -36
View File
@@ -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)
+74 -71
View File
@@ -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