wtinydb 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.
wtinydb-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 William Rodriguez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
wtinydb-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: wtinydb
3
+ Version: 0.1.0
4
+ Summary: Pydantic-powered document database abstraction layer on top of TinyDB
5
+ Author-email: "WILLIAM R." <william@ecapturedtech.com>
6
+ License: MIT
7
+ Keywords: tinydb,pydantic,nosql,document-database,orm,database
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: tinydb>=4.8.0
12
+ Requires-Dist: pydantic>=2.0.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
15
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
16
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
17
+ Dynamic: license-file
18
+
19
+ # WTinyDB: Lightweight Pydantic Document Database Engine
20
+
21
+ `wtinydb` is a high-level, document-oriented NoSQL database abstraction built on top of **TinyDB** and **Pydantic**. It provides schema-validated CRUD operations, fluent query builders, async support, audit mixins, and command-line management for embedded Python applications.
22
+
23
+ ## Key Technologies & Libraries
24
+
25
+ - **[TinyDB](https://tinydb.readthedocs.io/)**: Pure Python document-oriented database storing records as JSON.
26
+ - **[Pydantic v2](https://docs.pydantic.dev/)**: Data validation, settings management, and JSON-schema document serialization.
27
+ - **[Pytest](https://docs.pytest.org/)**: Modern Python testing framework.
28
+ - **[Pytest-Cov](https://pytest-cov.readthedocs.io/)**: Code coverage measurement for pytest.
29
+ - **[Docker](https://www.docker.com/)**: Containerization for reproducible testing environments.
30
+
31
+ ---
32
+
33
+ ## Features
34
+
35
+ - **Pydantic Model Mapping**: Automatic serialization, deserialization, and schema validation.
36
+ - **Fluent Query Builder (`Q`)**: Intuitive query building with comparison operators, regex matching, and text search.
37
+ - **Async Support (`AsyncWTinyDB`)**: Non-blocking thread-pool execution for FastAPI and Starlette apps.
38
+ - **Soft Delete & Audit Mixins**: Built-in support for `created_at`, `updated_at`, `is_deleted`, and `deleted_at`.
39
+ - **Thread Safety**: Integrated reentrant locks for safe multi-threaded access.
40
+ - **CLI Utility**: Command-line tool `wtinydb` to inspect, count, and export JSON tables.
41
+
42
+ ---
43
+
44
+ ## Quickstart Example
45
+
46
+ ```python
47
+ from pydantic import BaseModel, Field
48
+ from wtinydb import WTinyDB, Q, SoftDeleteMixin
49
+
50
+ # Define document schema
51
+ class User(SoftDeleteMixin, BaseModel):
52
+ name: str
53
+ email: str = Field(description="User email")
54
+ age: int = 18
55
+
56
+ # Initialize WTinyDB repository (in-memory or file-backed)
57
+ db = WTinyDB(User, in_memory=True)
58
+
59
+ # 1. Insert
60
+ user = db.insert(User(name="Alice", email="alice@example.com", age=30))
61
+
62
+ # 2. Query
63
+ results = db.find(Q("age").gte("age", 25))
64
+
65
+ # 3. Soft Delete & Restore
66
+ db.delete(1, hard=False)
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Running Unit Tests & Coverage
72
+
73
+ ### Local Pytest Execution
74
+
75
+ ```bash
76
+ # Run pytest test suite
77
+ pytest tests/
78
+
79
+ # Calculate code coverage
80
+ ./scripts/run_coverage.sh
81
+ ```
82
+
83
+ ### Docker Containerized Test Execution
84
+
85
+ All unit tests can be executed inside an isolated Docker container:
86
+
87
+ ```bash
88
+ ./scripts/run_tests_docker.sh
89
+ ```
90
+
91
+ ---
92
+
93
+ *Part of the wisrovi SUITE ecosystem.*
@@ -0,0 +1,75 @@
1
+ # WTinyDB: Lightweight Pydantic Document Database Engine
2
+
3
+ `wtinydb` is a high-level, document-oriented NoSQL database abstraction built on top of **TinyDB** and **Pydantic**. It provides schema-validated CRUD operations, fluent query builders, async support, audit mixins, and command-line management for embedded Python applications.
4
+
5
+ ## Key Technologies & Libraries
6
+
7
+ - **[TinyDB](https://tinydb.readthedocs.io/)**: Pure Python document-oriented database storing records as JSON.
8
+ - **[Pydantic v2](https://docs.pydantic.dev/)**: Data validation, settings management, and JSON-schema document serialization.
9
+ - **[Pytest](https://docs.pytest.org/)**: Modern Python testing framework.
10
+ - **[Pytest-Cov](https://pytest-cov.readthedocs.io/)**: Code coverage measurement for pytest.
11
+ - **[Docker](https://www.docker.com/)**: Containerization for reproducible testing environments.
12
+
13
+ ---
14
+
15
+ ## Features
16
+
17
+ - **Pydantic Model Mapping**: Automatic serialization, deserialization, and schema validation.
18
+ - **Fluent Query Builder (`Q`)**: Intuitive query building with comparison operators, regex matching, and text search.
19
+ - **Async Support (`AsyncWTinyDB`)**: Non-blocking thread-pool execution for FastAPI and Starlette apps.
20
+ - **Soft Delete & Audit Mixins**: Built-in support for `created_at`, `updated_at`, `is_deleted`, and `deleted_at`.
21
+ - **Thread Safety**: Integrated reentrant locks for safe multi-threaded access.
22
+ - **CLI Utility**: Command-line tool `wtinydb` to inspect, count, and export JSON tables.
23
+
24
+ ---
25
+
26
+ ## Quickstart Example
27
+
28
+ ```python
29
+ from pydantic import BaseModel, Field
30
+ from wtinydb import WTinyDB, Q, SoftDeleteMixin
31
+
32
+ # Define document schema
33
+ class User(SoftDeleteMixin, BaseModel):
34
+ name: str
35
+ email: str = Field(description="User email")
36
+ age: int = 18
37
+
38
+ # Initialize WTinyDB repository (in-memory or file-backed)
39
+ db = WTinyDB(User, in_memory=True)
40
+
41
+ # 1. Insert
42
+ user = db.insert(User(name="Alice", email="alice@example.com", age=30))
43
+
44
+ # 2. Query
45
+ results = db.find(Q("age").gte("age", 25))
46
+
47
+ # 3. Soft Delete & Restore
48
+ db.delete(1, hard=False)
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Running Unit Tests & Coverage
54
+
55
+ ### Local Pytest Execution
56
+
57
+ ```bash
58
+ # Run pytest test suite
59
+ pytest tests/
60
+
61
+ # Calculate code coverage
62
+ ./scripts/run_coverage.sh
63
+ ```
64
+
65
+ ### Docker Containerized Test Execution
66
+
67
+ All unit tests can be executed inside an isolated Docker container:
68
+
69
+ ```bash
70
+ ./scripts/run_tests_docker.sh
71
+ ```
72
+
73
+ ---
74
+
75
+ *Part of the wisrovi SUITE ecosystem.*
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "wtinydb"
7
+ version = "0.1.0"
8
+ description = "Pydantic-powered document database abstraction layer on top of TinyDB"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "WILLIAM R.", email = "william@ecapturedtech.com"}
14
+ ]
15
+ keywords = ["tinydb", "pydantic", "nosql", "document-database", "orm", "database"]
16
+ dependencies = [
17
+ "tinydb>=4.8.0",
18
+ "pydantic>=2.0.0",
19
+ ]
20
+
21
+ [project.optional-dependencies]
22
+ dev = [
23
+ "pytest>=7.0.0",
24
+ "pytest-cov>=4.0.0",
25
+ "pytest-asyncio>=0.21.0",
26
+ ]
27
+
28
+ [project.scripts]
29
+ wtinydb = "wtinydb.cli.main:main"
30
+
31
+ [tool.pytest.ini_options]
32
+ testpaths = ["tests"]
33
+ python_files = ["test_*.py"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,50 @@
1
+ """Unit tests for AsyncWTinyDB async database wrapper.
2
+
3
+ Validates non-blocking async CRUD operations.
4
+ """
5
+
6
+ from pydantic import BaseModel
7
+ import pytest
8
+
9
+ from wtinydb import AsyncWTinyDB, WTinyDB
10
+
11
+
12
+ class Item(BaseModel):
13
+ """Pydantic model for async testing."""
14
+
15
+ name: str
16
+ quantity: int
17
+
18
+
19
+ @pytest.mark.asyncio
20
+ async def test_async_crud_operations():
21
+ """Validates asynchronous insert, get, update, count, and delete operations."""
22
+ sync_db = WTinyDB(Item, in_memory=True)
23
+ async_db = AsyncWTinyDB(sync_db)
24
+
25
+ # Async insert
26
+ inserted = await async_db.insert(Item(name="Widget", quantity=10))
27
+ assert inserted.name == "Widget"
28
+
29
+ # Async count
30
+ cnt = await async_db.count()
31
+ assert cnt == 1
32
+
33
+ # Async get
34
+ retrieved = await async_db.get(1)
35
+ assert retrieved.quantity == 10
36
+
37
+ # Async update
38
+ updated = await async_db.update(1, {"quantity": 15})
39
+ assert updated.quantity == 15
40
+
41
+ # Async get_all
42
+ all_items = await async_db.get_all()
43
+ assert len(all_items) == 1
44
+
45
+ # Async delete
46
+ deleted = await async_db.delete(1)
47
+ assert deleted is True
48
+ assert await async_db.count() == 0
49
+
50
+ await async_db.close()
@@ -0,0 +1,32 @@
1
+ """Unit tests for WTinyDB command-line interface (CLI)."""
2
+
3
+ import sys
4
+ from unittest.mock import patch
5
+ from pydantic import BaseModel
6
+ from wtinydb import WTinyDB
7
+ from wtinydb.cli.main import main
8
+
9
+
10
+ class Task(BaseModel):
11
+ """Task model for CLI test."""
12
+
13
+ title: str
14
+
15
+
16
+ def test_cli_inspect_and_count(tmp_path):
17
+ """Validates CLI inspect and count subcommands on a temporary JSON database file."""
18
+ db_file = str(tmp_path / "test_cli.json")
19
+ db = WTinyDB(Task, db_path=db_file)
20
+ db.insert(Task(title="Do homework"))
21
+ db.insert(Task(title="Buy milk"))
22
+ db.close()
23
+
24
+ # Test CLI inspect command
25
+ test_args = ["wtinydb", "inspect", db_file]
26
+ with patch.object(sys, "argv", test_args):
27
+ main()
28
+
29
+ # Test CLI count command
30
+ test_args_count = ["wtinydb", "count", db_file, "--table", "task"]
31
+ with patch.object(sys, "argv", test_args_count):
32
+ main()
@@ -0,0 +1,140 @@
1
+ """Unit tests for WTinyDB synchronous operations.
2
+
3
+ This test file validates CRUD operations, soft-deletion handling,
4
+ batch inserts, document lookups, exceptions, and WMongo-compatible collection operations.
5
+ """
6
+
7
+ from typing import Optional
8
+ from pydantic import BaseModel, Field
9
+ import pytest
10
+
11
+ from wtinydb import WTinyDB, DocumentNotFoundError, SoftDeleteMixin
12
+
13
+
14
+ class User(BaseModel):
15
+ """Pydantic model representing a User document."""
16
+
17
+ name: str = Field(description="User full name")
18
+ email: str = Field(description="User email address")
19
+ age: int = Field(default=18, description="User age")
20
+
21
+
22
+ class SoftUser(SoftDeleteMixin, BaseModel):
23
+ """Pydantic model representing a User document with soft-delete capabilities."""
24
+
25
+ name: str
26
+ role: str = "member"
27
+
28
+
29
+ def test_insert_and_get():
30
+ """Validates model insertion and retrieval by doc_id."""
31
+ db = WTinyDB(User, in_memory=True)
32
+ user_data = User(name="Alice", email="alice@example.com", age=30)
33
+ inserted_user = db.insert(user_data)
34
+
35
+ assert inserted_user.name == "Alice"
36
+ assert inserted_user.email == "alice@example.com"
37
+ assert getattr(inserted_user, "_doc_id") == 1
38
+
39
+ retrieved_user = db.get(1)
40
+ assert retrieved_user.name == "Alice"
41
+ assert retrieved_user.age == 30
42
+ db.close()
43
+
44
+
45
+ def test_wmongo_collection_crud():
46
+ """Validates WMongo-compatible collection CRUD operations (insert, find, update, delete)."""
47
+ db = WTinyDB(in_memory=True)
48
+
49
+ # Collection insert
50
+ doc_id = db.insert("customers", {"name": "John Doe", "status": "active"})
51
+ assert doc_id == 1
52
+
53
+ # Collection find
54
+ found = db.find("customers", {"status": "active"})
55
+ assert len(found) == 1
56
+ assert found[0]["name"] == "John Doe"
57
+
58
+ # Collection update
59
+ updated_count = db.update("customers", {"name": "John Doe"}, {"status": "inactive"})
60
+ assert updated_count == 1
61
+
62
+ # Collection delete
63
+ deleted_count = db.delete("customers", {"status": "inactive"})
64
+ assert deleted_count == 1
65
+
66
+ db.close()
67
+
68
+
69
+ def test_insert_many_and_get_all():
70
+ """Validates batch insertion of multiple documents."""
71
+ db = WTinyDB(User, in_memory=True)
72
+ users = [
73
+ User(name="Bob", email="bob@example.com", age=25),
74
+ User(name="Charlie", email="charlie@example.com", age=35),
75
+ ]
76
+ inserted = db.insert_many(users)
77
+
78
+ assert len(inserted) == 2
79
+ assert db.count() == 2
80
+
81
+ all_users = db.get_all()
82
+ assert len(all_users) == 2
83
+ assert all_users[0].name == "Bob"
84
+ assert all_users[1].name == "Charlie"
85
+ db.close()
86
+
87
+
88
+ def test_get_by_field():
89
+ """Validates document lookup by specific field name and value."""
90
+ db = WTinyDB(User, in_memory=True)
91
+ db.insert(User(name="David", email="david@example.com", age=40))
92
+
93
+ user = db.get_by_field("email", "david@example.com")
94
+ assert user is not None
95
+ assert user.name == "David"
96
+
97
+ missing_user = db.get_by_field("email", "nonexistent@example.com")
98
+ assert missing_user is None
99
+ db.close()
100
+
101
+
102
+ def test_update_document():
103
+ """Validates document modification using dictionary update data."""
104
+ db = WTinyDB(User, in_memory=True)
105
+ inserted = db.insert(User(name="Eve", email="eve@example.com", age=22))
106
+
107
+ updated = db.update(1, {"age": 23})
108
+ assert updated.age == 23
109
+
110
+ retrieved = db.get(1)
111
+ assert retrieved.age == 23
112
+ db.close()
113
+
114
+
115
+ def test_soft_delete():
116
+ """Validates soft-delete functionality using SoftDeleteMixin."""
117
+ db = WTinyDB(SoftUser, in_memory=True)
118
+ user = db.insert(SoftUser(name="Frank", role="admin"))
119
+
120
+ db.delete(1, hard=False)
121
+
122
+ with pytest.raises(DocumentNotFoundError):
123
+ db.get(1)
124
+
125
+ assert len(db.get_all(include_deleted=False)) == 0
126
+
127
+ all_docs = db.get_all(include_deleted=True)
128
+ assert len(all_docs) == 1
129
+ assert all_docs[0].is_deleted is True
130
+ db.close()
131
+
132
+
133
+ def test_document_not_found_exception():
134
+ """Validates that accessing a non-existent document ID raises DocumentNotFoundError."""
135
+ db = WTinyDB(User, in_memory=True)
136
+
137
+ with pytest.raises(DocumentNotFoundError):
138
+ db.get(999)
139
+
140
+ db.close()
@@ -0,0 +1,42 @@
1
+ """Unit tests for TimestampMixin, SoftDeleteMixin, and AuditMixin."""
2
+
3
+ from pydantic import BaseModel
4
+ from wtinydb.models import AuditMixin, SoftDeleteMixin, TimestampMixin
5
+
6
+
7
+ class SampleTimestampDoc(TimestampMixin, BaseModel):
8
+ """Model using TimestampMixin."""
9
+
10
+ name: str
11
+
12
+
13
+ class SampleAuditDoc(AuditMixin, BaseModel):
14
+ """Model using AuditMixin."""
15
+
16
+ title: str
17
+
18
+
19
+ def test_timestamp_mixin():
20
+ """Validates default timestamp creation and touch functionality."""
21
+ doc = SampleTimestampDoc(name="test")
22
+ assert doc.created_at is not None
23
+ assert doc.updated_at is not None
24
+
25
+ initial_updated = doc.updated_at
26
+ doc.touch()
27
+ assert doc.updated_at >= initial_updated
28
+
29
+
30
+ def test_audit_mixin():
31
+ """Validates soft deletion and restoration capabilities in AuditMixin."""
32
+ doc = SampleAuditDoc(title="audit test")
33
+ assert doc.is_deleted is False
34
+ assert doc.deleted_at is None
35
+
36
+ doc.soft_delete()
37
+ assert doc.is_deleted is True
38
+ assert doc.deleted_at is not None
39
+
40
+ doc.restore()
41
+ assert doc.is_deleted is False
42
+ assert doc.deleted_at is None
@@ -0,0 +1,90 @@
1
+ """Unit tests for QueryBuilder and Q helper functionality.
2
+
3
+ This file validates fluent query construction, comparison operators,
4
+ regex matching, nested dotted path querying, and list containment queries.
5
+ """
6
+
7
+ from pydantic import BaseModel
8
+ from wtinydb import Q, QueryBuilder, WTinyDB
9
+
10
+
11
+ class Product(BaseModel):
12
+ """Pydantic model representing a product in inventory."""
13
+
14
+ title: str
15
+ price: float
16
+ category: str
17
+
18
+
19
+ class Geo(BaseModel):
20
+ lat: float
21
+ lon: float
22
+
23
+
24
+ class Address(BaseModel):
25
+ city: str
26
+ geo: Geo
27
+
28
+
29
+ class Organization(BaseModel):
30
+ name: str
31
+ address: Address
32
+
33
+
34
+ def test_query_builder_operators():
35
+ """Validates equality, greater-than, and list comparison operators with QueryBuilder."""
36
+ db = WTinyDB(Product, in_memory=True)
37
+
38
+ db.insert(Product(title="Laptop", price=999.99, category="electronics"))
39
+ db.insert(Product(title="Mouse", price=25.00, category="electronics"))
40
+ db.insert(Product(title="Book", price=15.00, category="books"))
41
+
42
+ books = db.find(Q("category").eq("category", "books"))
43
+ assert len(books) == 1
44
+ assert books[0].title == "Book"
45
+
46
+ expensive = db.find(Q("price").gte("price", 100.00))
47
+ assert len(expensive) == 1
48
+ assert expensive[0].title == "Laptop"
49
+
50
+ items = db.find(Q("category").in_list("category", ["electronics", "books"]))
51
+ assert len(items) == 3
52
+
53
+ db.close()
54
+
55
+
56
+ def test_query_regex_and_text_search():
57
+ """Validates regex pattern matching and text search functionality."""
58
+ db = WTinyDB(Product, in_memory=True)
59
+ db.insert(Product(title="Wireless Keyboard", price=45.00, category="electronics"))
60
+ db.insert(Product(title="Mechanical Keyboard", price=85.00, category="electronics"))
61
+
62
+ keyboards = db.find(Q("title").search_text("title", "keyboard"))
63
+ assert len(keyboards) == 2
64
+
65
+ wireless = db.find(Q("title").matches("title", r"^Wireless"))
66
+ assert len(wireless) == 1
67
+ assert wireless[0].title == "Wireless Keyboard"
68
+
69
+ db.close()
70
+
71
+
72
+ def test_nested_dotted_path_query():
73
+ """Validates querying N-level nested JSON fields using dotted notation paths."""
74
+ db = WTinyDB(Organization, in_memory=True)
75
+ org = Organization(
76
+ name="Acme",
77
+ address=Address(city="Madrid", geo=Geo(lat=40.4168, lon=-3.7038)),
78
+ )
79
+ db.insert(org)
80
+
81
+ # Query 3-level deep nested field
82
+ found_city = db.find(Q("address.city").eq("address.city", "Madrid"))
83
+ assert len(found_city) == 1
84
+ assert found_city[0].name == "Acme"
85
+
86
+ # Query 4-level deep nested numeric field
87
+ found_geo = db.find(Q("address.geo.lat").gte("address.geo.lat", 40.0))
88
+ assert len(found_geo) == 1
89
+
90
+ db.close()
@@ -0,0 +1,23 @@
1
+ """WTinyDB package initialization."""
2
+
3
+ from wtinydb.core.async_db import AsyncWTinyDB
4
+ from wtinydb.core.database import WTinyDB
5
+ from wtinydb.core.query import Q, QueryBuilder
6
+ from wtinydb.exceptions import DocumentNotFoundError, StorageError, ValidationError, WTinyDBError
7
+ from wtinydb.models import AuditMixin, SoftDeleteMixin, TimestampMixin
8
+
9
+ __version__ = "0.1.0"
10
+
11
+ __all__ = [
12
+ "WTinyDB",
13
+ "AsyncWTinyDB",
14
+ "QueryBuilder",
15
+ "Q",
16
+ "TimestampMixin",
17
+ "SoftDeleteMixin",
18
+ "AuditMixin",
19
+ "WTinyDBError",
20
+ "DocumentNotFoundError",
21
+ "ValidationError",
22
+ "StorageError",
23
+ ]
@@ -0,0 +1 @@
1
+ """CLI package for WTinyDB."""
@@ -0,0 +1,60 @@
1
+ """WTinyDB Command Line Interface (CLI)."""
2
+
3
+ import argparse
4
+ import json
5
+ import sys
6
+ from tinydb import TinyDB
7
+
8
+
9
+ def main():
10
+ """Main CLI entrypoint for WTinyDB commands."""
11
+ parser = argparse.ArgumentParser(description="WTinyDB CLI Manager")
12
+ subparsers = parser.add_subparsers(dest="command", help="Subcommand to run")
13
+
14
+ # Command: inspect
15
+ inspect_parser = subparsers.add_parser("inspect", help="Inspect tables in a TinyDB JSON database file")
16
+ inspect_parser.add_argument("db_path", help="Path to TinyDB JSON file")
17
+
18
+ # Command: count
19
+ count_parser = subparsers.add_parser("count", help="Count documents in a table")
20
+ count_parser.add_argument("db_path", help="Path to TinyDB JSON file")
21
+ count_parser.add_argument("--table", default="_default", help="Table name (default: _default)")
22
+
23
+ # Command: export
24
+ export_parser = subparsers.add_parser("export", help="Export table content as formatted JSON")
25
+ export_parser.add_argument("db_path", help="Path to TinyDB JSON file")
26
+ export_parser.add_argument("--table", default="_default", help="Table name")
27
+
28
+ args = parser.parse_args()
29
+
30
+ if not args.command:
31
+ parser.print_help()
32
+ sys.exit(0)
33
+
34
+ try:
35
+ db = TinyDB(args.db_path)
36
+ if args.command == "inspect":
37
+ tables = list(db.tables())
38
+ print(f"Database: {args.db_path}")
39
+ print(f"Tables found: {len(tables)}")
40
+ for t in tables:
41
+ table_obj = db.table(t)
42
+ print(f" - Table '{t}': {len(table_obj)} document(s)")
43
+
44
+ elif args.command == "count":
45
+ table_obj = db.table(args.table)
46
+ print(f"Table '{args.table}' contains {len(table_obj)} document(s).")
47
+
48
+ elif args.command == "export":
49
+ table_obj = db.table(args.table)
50
+ docs = table_obj.all()
51
+ print(json.dumps(docs, indent=2))
52
+
53
+ db.close()
54
+ except Exception as e:
55
+ print(f"Error: {e}", file=sys.stderr)
56
+ sys.exit(1)
57
+
58
+
59
+ if __name__ == "__main__":
60
+ main()
@@ -0,0 +1 @@
1
+ """Core modules for WTinyDB."""