ebk 0.4.4__py3-none-any.whl
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.
- ebk/__init__.py +35 -0
- ebk/ai/__init__.py +23 -0
- ebk/ai/knowledge_graph.py +450 -0
- ebk/ai/llm_providers/__init__.py +26 -0
- ebk/ai/llm_providers/anthropic.py +209 -0
- ebk/ai/llm_providers/base.py +295 -0
- ebk/ai/llm_providers/gemini.py +285 -0
- ebk/ai/llm_providers/ollama.py +294 -0
- ebk/ai/metadata_enrichment.py +394 -0
- ebk/ai/question_generator.py +328 -0
- ebk/ai/reading_companion.py +224 -0
- ebk/ai/semantic_search.py +433 -0
- ebk/ai/text_extractor.py +393 -0
- ebk/calibre_import.py +66 -0
- ebk/cli.py +6433 -0
- ebk/config.py +230 -0
- ebk/db/__init__.py +37 -0
- ebk/db/migrations.py +507 -0
- ebk/db/models.py +725 -0
- ebk/db/session.py +144 -0
- ebk/decorators.py +1 -0
- ebk/exports/__init__.py +0 -0
- ebk/exports/base_exporter.py +218 -0
- ebk/exports/echo_export.py +279 -0
- ebk/exports/html_library.py +1743 -0
- ebk/exports/html_utils.py +87 -0
- ebk/exports/hugo.py +59 -0
- ebk/exports/jinja_export.py +286 -0
- ebk/exports/multi_facet_export.py +159 -0
- ebk/exports/opds_export.py +232 -0
- ebk/exports/symlink_dag.py +479 -0
- ebk/exports/zip.py +25 -0
- ebk/extract_metadata.py +341 -0
- ebk/ident.py +89 -0
- ebk/library_db.py +1440 -0
- ebk/opds.py +748 -0
- ebk/plugins/__init__.py +42 -0
- ebk/plugins/base.py +502 -0
- ebk/plugins/hooks.py +442 -0
- ebk/plugins/registry.py +499 -0
- ebk/repl/__init__.py +9 -0
- ebk/repl/find.py +126 -0
- ebk/repl/grep.py +173 -0
- ebk/repl/shell.py +1677 -0
- ebk/repl/text_utils.py +320 -0
- ebk/search_parser.py +413 -0
- ebk/server.py +3608 -0
- ebk/services/__init__.py +28 -0
- ebk/services/annotation_extraction.py +351 -0
- ebk/services/annotation_service.py +380 -0
- ebk/services/export_service.py +577 -0
- ebk/services/import_service.py +447 -0
- ebk/services/personal_metadata_service.py +347 -0
- ebk/services/queue_service.py +253 -0
- ebk/services/tag_service.py +281 -0
- ebk/services/text_extraction.py +317 -0
- ebk/services/view_service.py +12 -0
- ebk/similarity/__init__.py +77 -0
- ebk/similarity/base.py +154 -0
- ebk/similarity/core.py +471 -0
- ebk/similarity/extractors.py +168 -0
- ebk/similarity/metrics.py +376 -0
- ebk/skills/SKILL.md +182 -0
- ebk/skills/__init__.py +1 -0
- ebk/vfs/__init__.py +101 -0
- ebk/vfs/base.py +298 -0
- ebk/vfs/library_vfs.py +122 -0
- ebk/vfs/nodes/__init__.py +54 -0
- ebk/vfs/nodes/authors.py +196 -0
- ebk/vfs/nodes/books.py +480 -0
- ebk/vfs/nodes/files.py +155 -0
- ebk/vfs/nodes/metadata.py +385 -0
- ebk/vfs/nodes/root.py +100 -0
- ebk/vfs/nodes/similar.py +165 -0
- ebk/vfs/nodes/subjects.py +184 -0
- ebk/vfs/nodes/tags.py +371 -0
- ebk/vfs/resolver.py +228 -0
- ebk/vfs_router.py +275 -0
- ebk/views/__init__.py +32 -0
- ebk/views/dsl.py +668 -0
- ebk/views/service.py +619 -0
- ebk-0.4.4.dist-info/METADATA +755 -0
- ebk-0.4.4.dist-info/RECORD +87 -0
- ebk-0.4.4.dist-info/WHEEL +5 -0
- ebk-0.4.4.dist-info/entry_points.txt +2 -0
- ebk-0.4.4.dist-info/licenses/LICENSE +21 -0
- ebk-0.4.4.dist-info/top_level.txt +1 -0
ebk/config.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration management for EBK.
|
|
3
|
+
|
|
4
|
+
Handles loading and saving user configuration from:
|
|
5
|
+
- XDG config directory: ~/.config/ebk/config.json
|
|
6
|
+
- Fallback: ~/.ebk/config.json
|
|
7
|
+
- Legacy: ~/.ebkrc (for backward compatibility)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, Any, Optional
|
|
13
|
+
from dataclasses import dataclass, asdict, field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class LLMConfig:
|
|
18
|
+
"""LLM provider configuration."""
|
|
19
|
+
provider: str = "ollama"
|
|
20
|
+
model: str = "llama3.2"
|
|
21
|
+
host: str = "localhost"
|
|
22
|
+
port: int = 11434
|
|
23
|
+
api_key: Optional[str] = None
|
|
24
|
+
temperature: float = 0.7
|
|
25
|
+
max_tokens: Optional[int] = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class ServerConfig:
|
|
30
|
+
"""Web server configuration."""
|
|
31
|
+
host: str = "0.0.0.0"
|
|
32
|
+
port: int = 8000
|
|
33
|
+
auto_open_browser: bool = False
|
|
34
|
+
page_size: int = 50
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class CLIConfig:
|
|
39
|
+
"""CLI default options."""
|
|
40
|
+
verbose: bool = False
|
|
41
|
+
color: bool = True
|
|
42
|
+
page_size: int = 50
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class LibraryConfig:
|
|
47
|
+
"""Library-related settings."""
|
|
48
|
+
default_path: Optional[str] = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class EBKConfig:
|
|
53
|
+
"""Main EBK configuration."""
|
|
54
|
+
llm: LLMConfig = field(default_factory=LLMConfig)
|
|
55
|
+
server: ServerConfig = field(default_factory=ServerConfig)
|
|
56
|
+
cli: CLIConfig = field(default_factory=CLIConfig)
|
|
57
|
+
library: LibraryConfig = field(default_factory=LibraryConfig)
|
|
58
|
+
|
|
59
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
60
|
+
"""Convert to dictionary."""
|
|
61
|
+
return {
|
|
62
|
+
"llm": asdict(self.llm),
|
|
63
|
+
"server": asdict(self.server),
|
|
64
|
+
"cli": asdict(self.cli),
|
|
65
|
+
"library": asdict(self.library),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'EBKConfig':
|
|
70
|
+
"""Create from dictionary."""
|
|
71
|
+
llm_data = data.get("llm", {})
|
|
72
|
+
server_data = data.get("server", {})
|
|
73
|
+
cli_data = data.get("cli", {})
|
|
74
|
+
library_data = data.get("library", {})
|
|
75
|
+
return cls(
|
|
76
|
+
llm=LLMConfig(**llm_data),
|
|
77
|
+
server=ServerConfig(**server_data),
|
|
78
|
+
cli=CLIConfig(**cli_data),
|
|
79
|
+
library=LibraryConfig(**library_data),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_config_path() -> Path:
|
|
84
|
+
"""
|
|
85
|
+
Get configuration file path.
|
|
86
|
+
|
|
87
|
+
Follows XDG Base Directory specification:
|
|
88
|
+
1. $XDG_CONFIG_HOME/ebk/config.json (usually ~/.config/ebk/config.json)
|
|
89
|
+
2. Fallback: ~/.ebk/config.json
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Path to config file
|
|
93
|
+
"""
|
|
94
|
+
# Try XDG config directory first
|
|
95
|
+
xdg_config_home = Path.home() / ".config"
|
|
96
|
+
if xdg_config_home.exists():
|
|
97
|
+
config_dir = xdg_config_home / "ebk"
|
|
98
|
+
else:
|
|
99
|
+
# Fallback to ~/.ebk
|
|
100
|
+
config_dir = Path.home() / ".ebk"
|
|
101
|
+
|
|
102
|
+
return config_dir / "config.json"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def load_config() -> EBKConfig:
|
|
106
|
+
"""
|
|
107
|
+
Load configuration from file.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
EBKConfig instance with loaded values or defaults
|
|
111
|
+
"""
|
|
112
|
+
config_path = get_config_path()
|
|
113
|
+
|
|
114
|
+
if not config_path.exists():
|
|
115
|
+
# Return default config
|
|
116
|
+
return EBKConfig()
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
with open(config_path, 'r') as f:
|
|
120
|
+
data = json.load(f)
|
|
121
|
+
return EBKConfig.from_dict(data)
|
|
122
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
123
|
+
print(f"Warning: Failed to load config from {config_path}: {e}")
|
|
124
|
+
print("Using default configuration")
|
|
125
|
+
return EBKConfig()
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def save_config(config: EBKConfig) -> None:
|
|
129
|
+
"""
|
|
130
|
+
Save configuration to file.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
config: Configuration to save
|
|
134
|
+
"""
|
|
135
|
+
config_path = get_config_path()
|
|
136
|
+
|
|
137
|
+
# Create directory if it doesn't exist
|
|
138
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
139
|
+
|
|
140
|
+
# Write config
|
|
141
|
+
with open(config_path, 'w') as f:
|
|
142
|
+
json.dump(config.to_dict(), f, indent=2)
|
|
143
|
+
|
|
144
|
+
print(f"Configuration saved to {config_path}")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def ensure_config_exists() -> Path:
|
|
148
|
+
"""
|
|
149
|
+
Ensure configuration file exists, creating with defaults if not.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Path to config file
|
|
153
|
+
"""
|
|
154
|
+
config_path = get_config_path()
|
|
155
|
+
|
|
156
|
+
if not config_path.exists():
|
|
157
|
+
config = EBKConfig()
|
|
158
|
+
save_config(config)
|
|
159
|
+
print(f"Created default configuration at {config_path}")
|
|
160
|
+
|
|
161
|
+
return config_path
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def update_config(
|
|
165
|
+
# LLM settings
|
|
166
|
+
llm_provider: Optional[str] = None,
|
|
167
|
+
llm_model: Optional[str] = None,
|
|
168
|
+
llm_host: Optional[str] = None,
|
|
169
|
+
llm_port: Optional[int] = None,
|
|
170
|
+
llm_api_key: Optional[str] = None,
|
|
171
|
+
llm_temperature: Optional[float] = None,
|
|
172
|
+
llm_max_tokens: Optional[int] = None,
|
|
173
|
+
# Server settings
|
|
174
|
+
server_host: Optional[str] = None,
|
|
175
|
+
server_port: Optional[int] = None,
|
|
176
|
+
server_auto_open: Optional[bool] = None,
|
|
177
|
+
server_page_size: Optional[int] = None,
|
|
178
|
+
# CLI settings
|
|
179
|
+
cli_verbose: Optional[bool] = None,
|
|
180
|
+
cli_color: Optional[bool] = None,
|
|
181
|
+
cli_page_size: Optional[int] = None,
|
|
182
|
+
# Library settings
|
|
183
|
+
library_default_path: Optional[str] = None,
|
|
184
|
+
) -> None:
|
|
185
|
+
"""
|
|
186
|
+
Update configuration.
|
|
187
|
+
|
|
188
|
+
Only updates provided values, leaving others unchanged.
|
|
189
|
+
"""
|
|
190
|
+
config = load_config()
|
|
191
|
+
|
|
192
|
+
# Update LLM config
|
|
193
|
+
if llm_provider is not None:
|
|
194
|
+
config.llm.provider = llm_provider
|
|
195
|
+
if llm_model is not None:
|
|
196
|
+
config.llm.model = llm_model
|
|
197
|
+
if llm_host is not None:
|
|
198
|
+
config.llm.host = llm_host
|
|
199
|
+
if llm_port is not None:
|
|
200
|
+
config.llm.port = llm_port
|
|
201
|
+
if llm_api_key is not None:
|
|
202
|
+
config.llm.api_key = llm_api_key
|
|
203
|
+
if llm_temperature is not None:
|
|
204
|
+
config.llm.temperature = llm_temperature
|
|
205
|
+
if llm_max_tokens is not None:
|
|
206
|
+
config.llm.max_tokens = llm_max_tokens
|
|
207
|
+
|
|
208
|
+
# Update server config
|
|
209
|
+
if server_host is not None:
|
|
210
|
+
config.server.host = server_host
|
|
211
|
+
if server_port is not None:
|
|
212
|
+
config.server.port = server_port
|
|
213
|
+
if server_auto_open is not None:
|
|
214
|
+
config.server.auto_open_browser = server_auto_open
|
|
215
|
+
if server_page_size is not None:
|
|
216
|
+
config.server.page_size = server_page_size
|
|
217
|
+
|
|
218
|
+
# Update CLI config
|
|
219
|
+
if cli_verbose is not None:
|
|
220
|
+
config.cli.verbose = cli_verbose
|
|
221
|
+
if cli_color is not None:
|
|
222
|
+
config.cli.color = cli_color
|
|
223
|
+
if cli_page_size is not None:
|
|
224
|
+
config.cli.page_size = cli_page_size
|
|
225
|
+
|
|
226
|
+
# Update library config
|
|
227
|
+
if library_default_path is not None:
|
|
228
|
+
config.library.default_path = library_default_path
|
|
229
|
+
|
|
230
|
+
save_config(config)
|
ebk/db/__init__.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database module for ebk.
|
|
3
|
+
|
|
4
|
+
Provides SQLAlchemy session management and initialization.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .models import (
|
|
8
|
+
Base, Book, Author, Subject, Identifier, File, ExtractedText,
|
|
9
|
+
TextChunk, Cover, Concept, BookConcept, ConceptRelation,
|
|
10
|
+
ReadingSession, Annotation, PersonalMetadata, Tag
|
|
11
|
+
)
|
|
12
|
+
from .session import get_session, init_db, close_db
|
|
13
|
+
from .migrations import run_all_migrations, check_migrations
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
'Base',
|
|
17
|
+
'Book',
|
|
18
|
+
'Author',
|
|
19
|
+
'Subject',
|
|
20
|
+
'Identifier',
|
|
21
|
+
'File',
|
|
22
|
+
'ExtractedText',
|
|
23
|
+
'TextChunk',
|
|
24
|
+
'Cover',
|
|
25
|
+
'Concept',
|
|
26
|
+
'BookConcept',
|
|
27
|
+
'ConceptRelation',
|
|
28
|
+
'ReadingSession',
|
|
29
|
+
'Annotation',
|
|
30
|
+
'PersonalMetadata',
|
|
31
|
+
'Tag',
|
|
32
|
+
'get_session',
|
|
33
|
+
'init_db',
|
|
34
|
+
'close_db',
|
|
35
|
+
'run_all_migrations',
|
|
36
|
+
'check_migrations'
|
|
37
|
+
]
|