# KotaDB Python Client
A simple, PostgreSQL-level easy-to-use Python client for KotaDB with type safety and builder patterns.
[](https://pypi.org/project/kotadb-client/)
## Features
- **Type Safety**: Runtime-validated types (`ValidatedPath`, `ValidatedDocumentId`, etc.)
- **Builder Patterns**: Fluent APIs for safe document and query construction
- **Full API Coverage**: Support for all KotaDB operations (CRUD, search, metadata)
- **Connection Management**: Automatic retries, connection pooling, timeout handling
- **Multiple Search Types**: Text, semantic, and hybrid search capabilities
## Installation
```bash
pip install kotadb-client
```
## Quick Start
```python
from kotadb import KotaDB
# Connect to KotaDB
db = KotaDB("http://localhost:8080")
# Insert a document
doc_id = db.insert({
"path": "/notes/meeting.md",
"title": "Team Meeting Notes",
"content": "Discussed project roadmap and next steps...",
"tags": ["work", "meeting", "planning"]
})
# Search for documents
results = db.query("project roadmap")
for result in results.results:
print(f"Found: {result.document.title} (score: {result.score})")
# Get a specific document
doc = db.get(doc_id)
print(f"Document: {doc.title}")
# Update a document
updated_doc = db.update(doc_id, {
"content": "Updated meeting notes with action items..."
})
# Delete a document
db.delete(doc_id)
```
## Type Safety & Builder Patterns
### Validated Types
Prevent errors at runtime with validated types that mirror the Rust implementation:
```python
from kotadb import ValidatedPath, ValidatedDocumentId, ValidatedTitle
# These will raise ValidationError if invalid
path = ValidatedPath("/notes/meeting.md") # Validates: no null bytes, no parent dir refs, etc.
doc_id = ValidatedDocumentId.parse("123e4567-e89b-12d3-a456-426614174000")
title = ValidatedTitle("My Document Title") # Validates: non-empty, length limits
# Use in document operations
db.insert({
"path": path.as_str(),
"title": title.as_str(),
"content": "Document content..."
})
```
### Document Builder Pattern
Build documents safely with validation at each step:
```python
from kotadb import DocumentBuilder
# Fluent API with validation
doc_id = db.insert_with_builder(
DocumentBuilder()
.path("/knowledge/python-guide.md")
.title("Python Best Practices")
.content("# Python Guide\n\nBest practices for Python development...")
.add_tag("python")
.add_tag("documentation")
.add_metadata("author", "user@example.com")
.add_metadata("priority", "high")
)
```
### Query Builder Pattern
Build complex queries with type safety:
```python
from kotadb import QueryBuilder
# Text search with filters
results = db.query_with_builder(
QueryBuilder()
.text("machine learning algorithms")
.limit(20)
.offset(10)
.tag_filter("ai")
.path_filter("/research/*")
)
# Semantic search
results = db.semantic_search_with_builder(
QueryBuilder()
.text("neural network architectures")
.limit(10)
)
# Hybrid search
results = db.hybrid_search_with_builder(
QueryBuilder()
.text("database optimization techniques")
.semantic_weight(0.8) # 80% semantic, 20% text
.limit(15)
)
```
### Update Builder Pattern
Safely update documents with fine-grained control:
```python
from kotadb import UpdateBuilder
# Update with builder pattern
updated_doc = db.update_with_builder(doc_id,
UpdateBuilder()
.title("Updated Python Guide")
.add_tag("updated")
.add_tag("2024")
.remove_tag("draft")
.add_metadata("last_modified_by", "user123")
.add_metadata("version", "2.0")
)
```
## Connection Options
### Environment Variable
```bash
export KOTADB_URL="http://localhost:8080"
```
```python
# Will use KOTADB_URL automatically
db = KotaDB()
```
### Connection String
```python
# PostgreSQL-style connection string
db = KotaDB("kotadb://localhost:8080/myapp")
# Direct HTTP URL
db = KotaDB("http://localhost:8080")
```
### Context Manager
```python
with KotaDB("http://localhost:8080") as db:
results = db.query("search term")
# Connection automatically closed
```
## Search Options
### Text Search
```python
results = db.query("rust programming patterns", limit=10)
```
### Semantic Search
```python
results = db.semantic_search("machine learning concepts", limit=5)
```
### Hybrid Search
```python
results = db.hybrid_search(
"database optimization",
limit=10,
semantic_weight=0.7 # 70% semantic, 30% text
)
```
## Document Operations
### Create Document
```python
# Using dictionary
doc_id = db.insert({
"path": "/docs/guide.md",
"title": "User Guide",
"content": "How to use the system...",
"tags": ["documentation", "guide"],
"metadata": {"author": "jane@example.com"}
})
# Using CreateDocumentRequest
from kotadb.types import CreateDocumentRequest
doc_request = CreateDocumentRequest(
path="/docs/api.md",
title="API Documentation",
content="API endpoints and usage...",
tags=["api", "docs"]
)
doc_id = db.insert(doc_request)
```
### List Documents
```python
# Get all documents
all_docs = db.list_all()
# With pagination
docs = db.list_all(limit=50, offset=100)
```
### Database Health
```python
# Check health
health = db.health()
print(f"Status: {health['status']}")
# Get statistics
stats = db.stats()
print(f"Document count: {stats['document_count']}")
```
## Error Handling
```python
from kotadb.exceptions import KotaDBError, NotFoundError, ConnectionError
try:
doc = db.get("non-existent-id")
except NotFoundError:
print("Document not found")
except ConnectionError:
print("Failed to connect to database")
except KotaDBError as e:
print(f"Database error: {e}")
```
## Configuration
```python
db = KotaDB(
url="http://localhost:8080",
timeout=30, # Request timeout in seconds
retries=3 # Number of retry attempts
)
```
## Data Types
### Core Types
```python
@dataclass
class Document:
id: str
path: str
title: str
content: str
tags: List[str]
created_at: datetime
updated_at: datetime
size: int
metadata: Optional[Dict[str, Any]]
@dataclass
class QueryResult:
results: List[Document]
total_count: int
query_time_ms: Optional[int]
```
### Validated Types
```python
class ValidatedPath:
"""Path with validation for safety (no traversal, null bytes, etc.)"""
def __init__(self, path: str) -> None: ...
def as_str(self) -> str: ...
class ValidatedDocumentId:
"""Document ID with UUID validation"""
@classmethod
def new(cls) -> 'ValidatedDocumentId': ...
@classmethod
def parse(cls, s: str) -> 'ValidatedDocumentId': ...
def as_str(self) -> str: ...
class ValidatedTitle:
"""Title with length and content validation"""
def __init__(self, title: str) -> None: ...
def as_str(self) -> str: ...
class ValidatedTimestamp:
"""Timestamp with range validation"""
@classmethod
def now(cls) -> 'ValidatedTimestamp': ...
def as_secs(self) -> int: ...
class NonZeroSize:
"""Size value that must be positive"""
def __init__(self, size: int) -> None: ...
def get(self) -> int: ...
```
### Builder Types
```python
class DocumentBuilder:
"""Fluent API for safe document construction"""
def path(self, path: Union[str, ValidatedPath]) -> 'DocumentBuilder': ...
def title(self, title: Union[str, ValidatedTitle]) -> 'DocumentBuilder': ...
def content(self, content: Union[str, bytes, List[int]]) -> 'DocumentBuilder': ...
def add_tag(self, tag: str) -> 'DocumentBuilder': ...
def add_metadata(self, key: str, value: Any) -> 'DocumentBuilder': ...
def build(self) -> CreateDocumentRequest: ...
class QueryBuilder:
"""Fluent API for building search queries"""
def text(self, query: str) -> 'QueryBuilder': ...
def limit(self, limit: int) -> 'QueryBuilder': ...
def offset(self, offset: int) -> 'QueryBuilder': ...
def tag_filter(self, tag: str) -> 'QueryBuilder': ...
def build(self) -> Dict[str, Any]: ...
class UpdateBuilder:
"""Fluent API for safe document updates"""
def title(self, title: Union[str, ValidatedTitle]) -> 'UpdateBuilder': ...
def content(self, content: Union[str, bytes, List[int]]) -> 'UpdateBuilder': ...
def add_tag(self, tag: str) -> 'UpdateBuilder': ...
def remove_tag(self, tag: str) -> 'UpdateBuilder': ...
def add_metadata(self, key: str, value: Any) -> 'UpdateBuilder': ...
def build(self) -> Dict[str, Any]: ...
```
## Development
Install development dependencies:
```bash
pip install -e ".[dev]"
```
Run tests:
```bash
pytest
```
Format code:
```bash
black kotadb/
```
Type checking:
```bash
mypy kotadb/
```
## License
MIT License - see LICENSE file for details.
## Contributing
See CONTRIBUTING.md for contribution guidelines.
## Support
- GitHub Issues: https://github.com/jayminwest/kota-db/issues
- Documentation: https://github.com/jayminwest/kota-db/docs
Raw data
{
"_id": null,
"home_page": "https://github.com/jayminwest/kota-db",
"name": "kotadb-client",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "database, document-store, search, semantic-search, kotadb",
"author": "KotaDB Team",
"author_email": "KotaDB Team <support@kotadb.dev>",
"download_url": "https://files.pythonhosted.org/packages/3b/95/928da1209ef0c3efca5b3aef035f80de4aabecbb46aed458fffe5c54b9c8/kotadb_client-0.5.0.tar.gz",
"platform": null,
"description": "# KotaDB Python Client\n\nA simple, PostgreSQL-level easy-to-use Python client for KotaDB with type safety and builder patterns.\n\n[](https://pypi.org/project/kotadb-client/)\n\n## Features\n\n- **Type Safety**: Runtime-validated types (`ValidatedPath`, `ValidatedDocumentId`, etc.)\n- **Builder Patterns**: Fluent APIs for safe document and query construction\n- **Full API Coverage**: Support for all KotaDB operations (CRUD, search, metadata)\n- **Connection Management**: Automatic retries, connection pooling, timeout handling\n- **Multiple Search Types**: Text, semantic, and hybrid search capabilities\n\n## Installation\n\n```bash\npip install kotadb-client\n```\n\n## Quick Start\n\n```python\nfrom kotadb import KotaDB\n\n# Connect to KotaDB\ndb = KotaDB(\"http://localhost:8080\")\n\n# Insert a document\ndoc_id = db.insert({\n \"path\": \"/notes/meeting.md\",\n \"title\": \"Team Meeting Notes\",\n \"content\": \"Discussed project roadmap and next steps...\",\n \"tags\": [\"work\", \"meeting\", \"planning\"]\n})\n\n# Search for documents\nresults = db.query(\"project roadmap\")\nfor result in results.results:\n print(f\"Found: {result.document.title} (score: {result.score})\")\n\n# Get a specific document\ndoc = db.get(doc_id)\nprint(f\"Document: {doc.title}\")\n\n# Update a document\nupdated_doc = db.update(doc_id, {\n \"content\": \"Updated meeting notes with action items...\"\n})\n\n# Delete a document\ndb.delete(doc_id)\n```\n\n## Type Safety & Builder Patterns\n\n### Validated Types\nPrevent errors at runtime with validated types that mirror the Rust implementation:\n\n```python\nfrom kotadb import ValidatedPath, ValidatedDocumentId, ValidatedTitle\n\n# These will raise ValidationError if invalid\npath = ValidatedPath(\"/notes/meeting.md\") # Validates: no null bytes, no parent dir refs, etc.\ndoc_id = ValidatedDocumentId.parse(\"123e4567-e89b-12d3-a456-426614174000\")\ntitle = ValidatedTitle(\"My Document Title\") # Validates: non-empty, length limits\n\n# Use in document operations\ndb.insert({\n \"path\": path.as_str(),\n \"title\": title.as_str(), \n \"content\": \"Document content...\"\n})\n```\n\n### Document Builder Pattern\nBuild documents safely with validation at each step:\n\n```python\nfrom kotadb import DocumentBuilder\n\n# Fluent API with validation\ndoc_id = db.insert_with_builder(\n DocumentBuilder()\n .path(\"/knowledge/python-guide.md\")\n .title(\"Python Best Practices\")\n .content(\"# Python Guide\\n\\nBest practices for Python development...\")\n .add_tag(\"python\")\n .add_tag(\"documentation\")\n .add_metadata(\"author\", \"user@example.com\")\n .add_metadata(\"priority\", \"high\")\n)\n```\n\n### Query Builder Pattern\nBuild complex queries with type safety:\n\n```python\nfrom kotadb import QueryBuilder\n\n# Text search with filters\nresults = db.query_with_builder(\n QueryBuilder()\n .text(\"machine learning algorithms\")\n .limit(20)\n .offset(10)\n .tag_filter(\"ai\")\n .path_filter(\"/research/*\")\n)\n\n# Semantic search\nresults = db.semantic_search_with_builder(\n QueryBuilder()\n .text(\"neural network architectures\")\n .limit(10)\n)\n\n# Hybrid search\nresults = db.hybrid_search_with_builder(\n QueryBuilder()\n .text(\"database optimization techniques\")\n .semantic_weight(0.8) # 80% semantic, 20% text\n .limit(15)\n)\n```\n\n### Update Builder Pattern\nSafely update documents with fine-grained control:\n\n```python\nfrom kotadb import UpdateBuilder\n\n# Update with builder pattern\nupdated_doc = db.update_with_builder(doc_id,\n UpdateBuilder()\n .title(\"Updated Python Guide\")\n .add_tag(\"updated\")\n .add_tag(\"2024\")\n .remove_tag(\"draft\")\n .add_metadata(\"last_modified_by\", \"user123\")\n .add_metadata(\"version\", \"2.0\")\n)\n```\n\n## Connection Options\n\n### Environment Variable\n```bash\nexport KOTADB_URL=\"http://localhost:8080\"\n```\n\n```python\n# Will use KOTADB_URL automatically\ndb = KotaDB()\n```\n\n### Connection String\n```python\n# PostgreSQL-style connection string\ndb = KotaDB(\"kotadb://localhost:8080/myapp\")\n\n# Direct HTTP URL\ndb = KotaDB(\"http://localhost:8080\")\n```\n\n### Context Manager\n```python\nwith KotaDB(\"http://localhost:8080\") as db:\n results = db.query(\"search term\")\n # Connection automatically closed\n```\n\n## Search Options\n\n### Text Search\n```python\nresults = db.query(\"rust programming patterns\", limit=10)\n```\n\n### Semantic Search\n```python\nresults = db.semantic_search(\"machine learning concepts\", limit=5)\n```\n\n### Hybrid Search\n```python\nresults = db.hybrid_search(\n \"database optimization\",\n limit=10,\n semantic_weight=0.7 # 70% semantic, 30% text\n)\n```\n\n## Document Operations\n\n### Create Document\n```python\n# Using dictionary\ndoc_id = db.insert({\n \"path\": \"/docs/guide.md\",\n \"title\": \"User Guide\",\n \"content\": \"How to use the system...\",\n \"tags\": [\"documentation\", \"guide\"],\n \"metadata\": {\"author\": \"jane@example.com\"}\n})\n\n# Using CreateDocumentRequest\nfrom kotadb.types import CreateDocumentRequest\n\ndoc_request = CreateDocumentRequest(\n path=\"/docs/api.md\",\n title=\"API Documentation\",\n content=\"API endpoints and usage...\",\n tags=[\"api\", \"docs\"]\n)\ndoc_id = db.insert(doc_request)\n```\n\n### List Documents\n```python\n# Get all documents\nall_docs = db.list_all()\n\n# With pagination\ndocs = db.list_all(limit=50, offset=100)\n```\n\n### Database Health\n```python\n# Check health\nhealth = db.health()\nprint(f\"Status: {health['status']}\")\n\n# Get statistics\nstats = db.stats()\nprint(f\"Document count: {stats['document_count']}\")\n```\n\n## Error Handling\n\n```python\nfrom kotadb.exceptions import KotaDBError, NotFoundError, ConnectionError\n\ntry:\n doc = db.get(\"non-existent-id\")\nexcept NotFoundError:\n print(\"Document not found\")\nexcept ConnectionError:\n print(\"Failed to connect to database\")\nexcept KotaDBError as e:\n print(f\"Database error: {e}\")\n```\n\n## Configuration\n\n```python\ndb = KotaDB(\n url=\"http://localhost:8080\",\n timeout=30, # Request timeout in seconds\n retries=3 # Number of retry attempts\n)\n```\n\n## Data Types\n\n### Core Types\n```python\n@dataclass\nclass Document:\n id: str\n path: str\n title: str\n content: str\n tags: List[str]\n created_at: datetime\n updated_at: datetime\n size: int\n metadata: Optional[Dict[str, Any]]\n\n@dataclass\nclass QueryResult:\n results: List[Document]\n total_count: int\n query_time_ms: Optional[int]\n```\n\n### Validated Types\n```python\nclass ValidatedPath:\n \"\"\"Path with validation for safety (no traversal, null bytes, etc.)\"\"\"\n def __init__(self, path: str) -> None: ...\n def as_str(self) -> str: ...\n\nclass ValidatedDocumentId:\n \"\"\"Document ID with UUID validation\"\"\"\n @classmethod\n def new(cls) -> 'ValidatedDocumentId': ...\n @classmethod\n def parse(cls, s: str) -> 'ValidatedDocumentId': ...\n def as_str(self) -> str: ...\n\nclass ValidatedTitle:\n \"\"\"Title with length and content validation\"\"\"\n def __init__(self, title: str) -> None: ...\n def as_str(self) -> str: ...\n\nclass ValidatedTimestamp:\n \"\"\"Timestamp with range validation\"\"\"\n @classmethod\n def now(cls) -> 'ValidatedTimestamp': ...\n def as_secs(self) -> int: ...\n\nclass NonZeroSize:\n \"\"\"Size value that must be positive\"\"\"\n def __init__(self, size: int) -> None: ...\n def get(self) -> int: ...\n```\n\n### Builder Types\n```python\nclass DocumentBuilder:\n \"\"\"Fluent API for safe document construction\"\"\"\n def path(self, path: Union[str, ValidatedPath]) -> 'DocumentBuilder': ...\n def title(self, title: Union[str, ValidatedTitle]) -> 'DocumentBuilder': ...\n def content(self, content: Union[str, bytes, List[int]]) -> 'DocumentBuilder': ...\n def add_tag(self, tag: str) -> 'DocumentBuilder': ...\n def add_metadata(self, key: str, value: Any) -> 'DocumentBuilder': ...\n def build(self) -> CreateDocumentRequest: ...\n\nclass QueryBuilder:\n \"\"\"Fluent API for building search queries\"\"\"\n def text(self, query: str) -> 'QueryBuilder': ...\n def limit(self, limit: int) -> 'QueryBuilder': ...\n def offset(self, offset: int) -> 'QueryBuilder': ...\n def tag_filter(self, tag: str) -> 'QueryBuilder': ...\n def build(self) -> Dict[str, Any]: ...\n\nclass UpdateBuilder:\n \"\"\"Fluent API for safe document updates\"\"\"\n def title(self, title: Union[str, ValidatedTitle]) -> 'UpdateBuilder': ...\n def content(self, content: Union[str, bytes, List[int]]) -> 'UpdateBuilder': ...\n def add_tag(self, tag: str) -> 'UpdateBuilder': ...\n def remove_tag(self, tag: str) -> 'UpdateBuilder': ...\n def add_metadata(self, key: str, value: Any) -> 'UpdateBuilder': ...\n def build(self) -> Dict[str, Any]: ...\n```\n\n## Development\n\nInstall development dependencies:\n```bash\npip install -e \".[dev]\"\n```\n\nRun tests:\n```bash\npytest\n```\n\nFormat code:\n```bash\nblack kotadb/\n```\n\nType checking:\n```bash\nmypy kotadb/\n```\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Contributing\n\nSee CONTRIBUTING.md for contribution guidelines.\n\n## Support\n\n- GitHub Issues: https://github.com/jayminwest/kota-db/issues\n- Documentation: https://github.com/jayminwest/kota-db/docs\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python client for KotaDB - PostgreSQL-level ease of use for document database",
"version": "0.5.0",
"project_urls": {
"Bug Reports": "https://github.com/jayminwest/kota-db/issues",
"Documentation": "https://github.com/jayminwest/kota-db/docs",
"Homepage": "https://github.com/jayminwest/kota-db",
"Repository": "https://github.com/jayminwest/kota-db"
},
"split_keywords": [
"database",
" document-store",
" search",
" semantic-search",
" kotadb"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "aa4b8ec573f5aad745c1127f21dd75e072c28dcf25ac16ba960450c821457861",
"md5": "3a6e1bef44843712b5b34163b17d2ba1",
"sha256": "f7916e27fbb26d09cfb1132254c99274dd506f00d4d3368fac21d14ab4fd7eec"
},
"downloads": -1,
"filename": "kotadb_client-0.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3a6e1bef44843712b5b34163b17d2ba1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 37497,
"upload_time": "2025-08-15T22:29:58",
"upload_time_iso_8601": "2025-08-15T22:29:58.628782Z",
"url": "https://files.pythonhosted.org/packages/aa/4b/8ec573f5aad745c1127f21dd75e072c28dcf25ac16ba960450c821457861/kotadb_client-0.5.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "3b95928da1209ef0c3efca5b3aef035f80de4aabecbb46aed458fffe5c54b9c8",
"md5": "7016a21d66b41e2f4814b582b9929f3d",
"sha256": "b1835ac058b410f027caec26338d9b5ed9f9cdfa9b5189575c618fdf5bbb9d67"
},
"downloads": -1,
"filename": "kotadb_client-0.5.0.tar.gz",
"has_sig": false,
"md5_digest": "7016a21d66b41e2f4814b582b9929f3d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 36474,
"upload_time": "2025-08-15T22:29:59",
"upload_time_iso_8601": "2025-08-15T22:29:59.676469Z",
"url": "https://files.pythonhosted.org/packages/3b/95/928da1209ef0c3efca5b3aef035f80de4aabecbb46aed458fffe5c54b9c8/kotadb_client-0.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-15 22:29:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jayminwest",
"github_project": "kota-db",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "kotadb-client"
}