lestash 1.64.2__tar.gz → 1.64.4__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.
- {lestash-1.64.2 → lestash-1.64.4}/PKG-INFO +2 -2
- {lestash-1.64.2 → lestash-1.64.4}/pyproject.toml +1 -1
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/sources.py +14 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/database.py +14 -3
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/google_auth.py +1 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_history.py +16 -0
- {lestash-1.64.2 → lestash-1.64.4}/.gitignore +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/README.md +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/__main__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/config.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/db.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/embeddings.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/enrich.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/google.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/items.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/main.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/media.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/cli/profiles.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/config.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/db_admin.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/embeddings.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/enrichment.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/exceptions.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/google_drive.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/logging.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/TUNING.md +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/annotations.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/cleanup.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/extractor.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/images.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/links.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/ocr.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/persistence.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/runner.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/types.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/pdf_enrich/version.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/core/text_extract.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/models/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/models/item.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/models/source.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/models/tag.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/plugins/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/plugins/base.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/plugins/loader.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/src/lestash/plugins/publisher.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/conftest.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/__init__.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/conftest.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_annotations.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_cleanup.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_extractor.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_images.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_links.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_ocr.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_persistence.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/pdf_enrich/test_runner.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_db_admin.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_items_display.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_post_cache.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_publisher.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_sources_enable.py +0 -0
- {lestash-1.64.2 → lestash-1.64.4}/tests/test_text_extract.py +0 -0
|
@@ -239,6 +239,20 @@ def sync_source(
|
|
|
239
239
|
except ImportError:
|
|
240
240
|
pass
|
|
241
241
|
|
|
242
|
+
# Resolve parent_id for YouTube transcripts captured before
|
|
243
|
+
# (or alongside) their video item.
|
|
244
|
+
if name == "youtube":
|
|
245
|
+
try:
|
|
246
|
+
from lestash_youtube.source import (
|
|
247
|
+
resolve_youtube_transcript_parents,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
resolved = resolve_youtube_transcript_parents(conn)
|
|
251
|
+
if resolved:
|
|
252
|
+
console.print(f" [dim]Resolved {resolved} transcript parent(s)[/dim]")
|
|
253
|
+
except ImportError:
|
|
254
|
+
pass
|
|
255
|
+
|
|
242
256
|
# Update source last_sync
|
|
243
257
|
conn.execute(
|
|
244
258
|
"""
|
|
@@ -10,6 +10,7 @@ import logging
|
|
|
10
10
|
import sqlite3
|
|
11
11
|
from collections.abc import Iterable, Iterator
|
|
12
12
|
from contextlib import contextmanager
|
|
13
|
+
from datetime import UTC, datetime
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
from typing import TYPE_CHECKING
|
|
15
16
|
|
|
@@ -21,7 +22,7 @@ if TYPE_CHECKING:
|
|
|
21
22
|
logger = logging.getLogger(__name__)
|
|
22
23
|
|
|
23
24
|
# Current schema version - increment when adding migrations
|
|
24
|
-
SCHEMA_VERSION =
|
|
25
|
+
SCHEMA_VERSION = 12
|
|
25
26
|
|
|
26
27
|
# Base schema (version 0) - applied to new databases
|
|
27
28
|
SCHEMA = """
|
|
@@ -34,7 +35,7 @@ CREATE TABLE IF NOT EXISTS items (
|
|
|
34
35
|
title TEXT,
|
|
35
36
|
content TEXT NOT NULL,
|
|
36
37
|
author TEXT,
|
|
37
|
-
created_at DATETIME,
|
|
38
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
38
39
|
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
39
40
|
is_own_content BOOLEAN DEFAULT FALSE,
|
|
40
41
|
metadata TEXT,
|
|
@@ -379,6 +380,15 @@ MIGRATIONS = [
|
|
|
379
380
|
CREATE INDEX IF NOT EXISTS idx_syndications_item ON syndications(item_id);
|
|
380
381
|
""",
|
|
381
382
|
),
|
|
383
|
+
(
|
|
384
|
+
12,
|
|
385
|
+
"Backfill items.created_at NULLs with fetched_at",
|
|
386
|
+
# items.created_at had no default, so rows written without a date
|
|
387
|
+
# (API-created notes, gemini imports, etc.) stored NULL. fetched_at is
|
|
388
|
+
# the best available capture-time proxy. Insert-layer defaults in
|
|
389
|
+
# upsert_item()/create_item() prevent future NULLs.
|
|
390
|
+
"UPDATE items SET created_at = fetched_at WHERE created_at IS NULL;",
|
|
391
|
+
),
|
|
382
392
|
]
|
|
383
393
|
|
|
384
394
|
|
|
@@ -606,6 +616,7 @@ def upsert_item(conn: sqlite3.Connection, item: ItemCreate) -> int:
|
|
|
606
616
|
import json
|
|
607
617
|
|
|
608
618
|
metadata_json = json.dumps(item.metadata) if item.metadata else None
|
|
619
|
+
created_at = item.created_at or datetime.now(UTC)
|
|
609
620
|
pre_max = max_history_id(conn)
|
|
610
621
|
conn.execute(
|
|
611
622
|
"""
|
|
@@ -632,7 +643,7 @@ def upsert_item(conn: sqlite3.Connection, item: ItemCreate) -> int:
|
|
|
632
643
|
item.title,
|
|
633
644
|
item.content,
|
|
634
645
|
item.author,
|
|
635
|
-
|
|
646
|
+
created_at,
|
|
636
647
|
item.is_own_content,
|
|
637
648
|
metadata_json,
|
|
638
649
|
item.parent_id,
|
|
@@ -447,6 +447,22 @@ class TestChangeReason:
|
|
|
447
447
|
assert rows[0]["change_reason"] == "sync"
|
|
448
448
|
assert rows[0]["content_old"] == "original"
|
|
449
449
|
|
|
450
|
+
def test_upsert_item_defaults_created_at(self, test_db):
|
|
451
|
+
"""Upsert without a created_at should not store NULL."""
|
|
452
|
+
with get_connection(test_db) as conn:
|
|
453
|
+
upsert_item(
|
|
454
|
+
conn,
|
|
455
|
+
ItemCreate(
|
|
456
|
+
source_type="note",
|
|
457
|
+
source_id="undated",
|
|
458
|
+
content="no date",
|
|
459
|
+
),
|
|
460
|
+
)
|
|
461
|
+
row = conn.execute(
|
|
462
|
+
"SELECT created_at FROM items WHERE source_id = ?", ("undated",)
|
|
463
|
+
).fetchone()
|
|
464
|
+
assert row[0] is not None
|
|
465
|
+
|
|
450
466
|
def test_pdf_enricher_marks_history_as_enricher(self, test_db):
|
|
451
467
|
from lestash.core.pdf_enrich.persistence import mark_source_unavailable
|
|
452
468
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|