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.
- parakeet_index_docstore_sqlite-0.1.0/.gitignore +85 -0
- parakeet_index_docstore_sqlite-0.1.0/PKG-INFO +22 -0
- parakeet_index_docstore_sqlite-0.1.0/README.md +7 -0
- parakeet_index_docstore_sqlite-0.1.0/parakeet_index/docstore/sqlite/__init__.py +3 -0
- parakeet_index_docstore_sqlite-0.1.0/parakeet_index/docstore/sqlite/base.py +147 -0
- parakeet_index_docstore_sqlite-0.1.0/pyproject.toml +29 -0
|
@@ -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,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
|
+
]
|