parakeet-index-docstore-sqlite 0.1.0__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.
@@ -0,0 +1,85 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ #IDE
10
+ .DS_Store
11
+ .idea
12
+ .vscode
13
+
14
+ # Distribution / packaging
15
+ .Python
16
+ build/
17
+ develop-eggs/
18
+ dist/
19
+ downloads/
20
+ eggs/
21
+ .eggs/
22
+ lib/
23
+ lib64/
24
+ parts/
25
+ sdist/
26
+ var/
27
+ wheels/
28
+ share/python-wheels/
29
+ *.egg-info/
30
+ .installed.cfg
31
+ *.egg
32
+ MANIFEST
33
+
34
+ # PyInstaller
35
+ # Usually these files are written by a python script from a template
36
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
37
+ *.manifest
38
+ *.spec
39
+
40
+ # Installer logs
41
+ pip-log.txt
42
+ pip-delete-this-directory.txt
43
+
44
+ # Unit test / coverage reports
45
+ htmlcov/
46
+ .tox/
47
+ .nox/
48
+ .coverage
49
+ .coverage.*
50
+ .cache
51
+ nosetests.xml
52
+ coverage.xml
53
+ *.cover
54
+ *.py,cover
55
+ .hypothesis/
56
+ .pytest_cache/
57
+ cover/
58
+
59
+ # Mkdocs documentation
60
+ docs/_build/
61
+ docs/api_reference/site/
62
+
63
+ # Ruff
64
+ .ruff_cache/
65
+
66
+ # PyBuilder
67
+ .pybuilder/
68
+ target/
69
+
70
+ # Jupyter Notebook
71
+ .ipynb_checkpoints
72
+
73
+ # pyenv
74
+ # For a library or package, you might want to ignore these files since the code is
75
+ # intended to run in multiple environments; otherwise, check them in:
76
+ .python-version
77
+
78
+ # Environments
79
+ .env
80
+ .venv
81
+ env/
82
+ venv/
83
+ ENV/
84
+ env.bak/
85
+ venv.bak/
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.5
2
+ Name: parakeet-index-docstore-sqlite
3
+ Version: 0.1.0
4
+ Summary: parakeet-index docstore sqlite integration
5
+ Author-email: Leonardo Furnielis <leonardofurnielis@outlook.com>
6
+ License: Apache-2.0
7
+ Requires-Python: <3.14,>=3.11
8
+ Requires-Dist: parakeet-index-core<0.2.0,>=0.1.2
9
+ Requires-Dist: sqlalchemy<2.1.0,>=2.0.51
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest-asyncio<2.0.0,>=1.4.0; extra == 'dev'
12
+ Requires-Dist: pytest<10.0.0,>=9.1.1; extra == 'dev'
13
+ Requires-Dist: ruff<0.16.0,>=0.15.20; extra == 'dev'
14
+ Description-Content-Type: text/markdown
15
+
16
+ # Parakeet Index docstore integration - SQLite
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install parakeet-index-docstore-sqlite
22
+ ```
@@ -0,0 +1,7 @@
1
+ # Parakeet Index docstore integration - SQLite
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ pip install parakeet-index-docstore-sqlite
7
+ ```
@@ -0,0 +1,3 @@
1
+ from parakeet_index.docstore.sqlite.base import SQLiteDocStore
2
+
3
+ __all__ = ["SQLiteDocStore"]
@@ -0,0 +1,147 @@
1
+ from datetime import datetime, timezone
2
+ from typing import Any
3
+
4
+ from parakeet_index.core.bridge.pydantic import Field, PrivateAttr
5
+ from parakeet_index.core.docstore import BaseDocStore
6
+ from parakeet_index.core.document import Document
7
+
8
+
9
+ class SQLiteDocStore(BaseDocStore):
10
+ """
11
+ SQLite-backed document store.
12
+
13
+ Attributes:
14
+ db_path (str): Path to the SQLite database file. Defaults to ``parakeet-index-docstore.db``.
15
+
16
+ Example:
17
+ ```python
18
+ from parakeet_index.docstore.sqlite import SQLiteDocStore
19
+
20
+ doc_store = SQLiteDocStore(db_path="./my-index.db")
21
+ ```
22
+ """
23
+
24
+ db_path: str = Field(
25
+ default="parakeet-index-docstore.db",
26
+ description="Path to the SQLite database file.",
27
+ )
28
+
29
+ _engine: Any = PrivateAttr()
30
+ _table: Any = PrivateAttr()
31
+
32
+ def model_post_init(self, __context): # noqa: PYI063
33
+ from sqlalchemy import (
34
+ Column,
35
+ Index,
36
+ MetaData,
37
+ String,
38
+ Table,
39
+ Text,
40
+ create_engine,
41
+ )
42
+
43
+ self._engine = create_engine(f"sqlite:///{self.db_path}")
44
+
45
+ metadata = MetaData()
46
+ self._table = Table(
47
+ "parakeet_index_docstore",
48
+ metadata,
49
+ Column("doc_id", String, primary_key=True),
50
+ Column("doc_hash", String, nullable=False),
51
+ Column("text", Text, nullable=False),
52
+ Column("created_at", String, nullable=False),
53
+ Column("updated_at", String, nullable=False),
54
+ Index("idx_doc_hash", "doc_hash"),
55
+ )
56
+ metadata.create_all(self._engine)
57
+
58
+ @classmethod
59
+ def class_name(cls) -> str:
60
+ return "SQLiteDocStore"
61
+
62
+ def upsert_documents(self, documents: list[Document]) -> None:
63
+ """Insert or update document records."""
64
+ if not documents:
65
+ return
66
+
67
+ from sqlalchemy.dialects.sqlite import insert
68
+
69
+ now = datetime.now(timezone.utc).isoformat()
70
+
71
+ values = [
72
+ {
73
+ "doc_id": doc.id_,
74
+ "doc_hash": doc.hash,
75
+ "text": doc.get_content(),
76
+ "created_at": now,
77
+ "updated_at": now,
78
+ }
79
+ for doc in documents
80
+ ]
81
+
82
+ stmt = insert(self._table)
83
+ stmt = stmt.on_conflict_do_update(
84
+ index_elements=["doc_id"],
85
+ set_={
86
+ "doc_hash": stmt.excluded.doc_hash,
87
+ "text": stmt.excluded.text,
88
+ "updated_at": stmt.excluded.updated_at,
89
+ },
90
+ )
91
+
92
+ with self._engine.begin() as conn:
93
+ conn.execute(stmt, values)
94
+
95
+ def list_documents(self) -> list[Document]:
96
+ """Return all documents currently stored, including text."""
97
+ from sqlalchemy import select
98
+
99
+ stmt = select(
100
+ self._table.c.doc_id,
101
+ self._table.c.text,
102
+ )
103
+
104
+ with self._engine.connect() as conn:
105
+ rows = conn.execute(stmt).fetchall()
106
+
107
+ return [Document(id_=row[0], text=row[1]) for row in rows]
108
+
109
+ def delete_documents(self, ids: list[str]) -> None:
110
+ """Delete records by document ID."""
111
+ if not ids:
112
+ return
113
+
114
+ from sqlalchemy import delete
115
+
116
+ stmt = delete(self._table).where(self._table.c.doc_id.in_(ids))
117
+
118
+ with self._engine.begin() as conn:
119
+ conn.execute(stmt)
120
+
121
+ def get_document_hash(self, doc_id: str) -> str | None:
122
+ """Get the stored hash for a single document, if it exists."""
123
+ from sqlalchemy import select
124
+
125
+ stmt = select(self._table.c.doc_hash).where(self._table.c.doc_id == doc_id)
126
+
127
+ with self._engine.connect() as conn:
128
+ row = conn.execute(stmt).fetchone()
129
+
130
+ return row[0] if row is not None else None
131
+
132
+ def get_document(self, doc_id: str) -> Document | None:
133
+ """Return a single document record by Id, including text."""
134
+ from sqlalchemy import select
135
+
136
+ stmt = select(
137
+ self._table.c.doc_id,
138
+ self._table.c.text,
139
+ ).where(self._table.c.doc_id == doc_id)
140
+
141
+ with self._engine.connect() as conn:
142
+ row = conn.execute(stmt).fetchone()
143
+
144
+ if row is None:
145
+ return None
146
+
147
+ return Document(id_=row[0], text=row[1])
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "parakeet-index-docstore-sqlite"
7
+ version = "0.1.0"
8
+ description = "parakeet-index docstore sqlite integration"
9
+ authors = [{ name = "Leonardo Furnielis", email = "leonardofurnielis@outlook.com" }]
10
+ license = { text = "Apache-2.0" }
11
+ readme = "README.md"
12
+ requires-python = ">=3.11,<3.14"
13
+ dependencies = [
14
+ "sqlalchemy>=2.0.51,<2.1.0",
15
+ "parakeet-index-core>=0.1.2,<0.2.0",
16
+ ]
17
+
18
+ [tool.hatch.build.targets.sdist]
19
+ include = ["parakeet_index/"]
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ include = ["parakeet_index/"]
23
+
24
+ [project.optional-dependencies]
25
+ dev = [
26
+ "pytest>=9.1.1,<10.0.0",
27
+ "pytest-asyncio>=1.4.0,<2.0.0",
28
+ "ruff>=0.15.20,<0.16.0",
29
+ ]