Metadata-Version: 2.4
Name: jsonlt-python
Version: 0.1.0
Summary: Reference implementation of the JSONLT (JSON Lines Table) specification for Python.
Keywords: append-only,data-format,database,json-lines,jsonl,jsonlines,jsonlt,version-control
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Free Threading :: 1 - Unstable
Classifier: Topic :: Database
Classifier: Topic :: File Formats :: JSON
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: typing-extensions>=4.15.0
Requires-Python: >=3.10
Project-URL: Changelog, https://github.com/jsonlt/jsonlt-python/blob/main/CHANGELOG.md
Project-URL: Documentation, https://jsonlt.org/docs
Project-URL: Homepage, https://jsonlt.org
Project-URL: Issues, https://github.com/jsonlt/jsonlt-python/issues
Project-URL: Repository, https://github.com/jsonlt/jsonlt-python
Description-Content-Type: text/markdown

# jsonlt

<!-- vale off -->
[![PyPI](https://img.shields.io/pypi/v/jsonlt-python)](https://pypi.org/project/jsonlt-python/)
[![CI](https://github.com/jsonlt/jsonlt-python/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jsonlt/jsonlt-python/actions/workflows/ci.yml)
[![Codecov](https://codecov.io/gh/jsonlt/jsonlt-python/branch/main/graph/badge.svg)](https://codecov.io/gh/jsonlt/jsonlt-python)
[![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/jsonlt/jsonlt-python)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
<!-- vale on -->

The Python reference implementation of [JSONLT (JSON Lines Table)](https://jsonlt.org), a data format for storing keyed records in append-only files. JSONLT builds on [JSON Lines](https://jsonlines.org/) and optimizes for version control. Modifications append new lines rather than rewriting existing content, producing clean and meaningful diffs.

> [!NOTE]
> This package is under active development. The API may change before the 1.0 release.

## Resources

- [Specification](https://spec.jsonlt.org): formal definition of the JSONLT format
- [Documentation](https://docs.jsonlt.org): guides, tutorials, and API reference
- [Conformance tests](https://github.com/jsonlt/jsonlt/tree/main/conformance): language-agnostic test suite

## Installation

```bash
pip install jsonlt-python

# Or

uv add jsonlt-python
```

Requires Python 3.10 or later.

## Quick start

```python
from jsonlt import Table

# Open or create a table
table = Table("users.jsonlt", key="id")

# Insert or update records
table.put({"id": "alice", "role": "admin", "email": "alice@example.com"})
table.put({"id": "bob", "role": "user", "email": "bob@example.com"})

# Read records
user = table.get("alice")  # Returns the record or None
exists = table.has("bob")  # Returns True

# Delete records (appends a tombstone)
table.delete("bob")

# Iterate over all records
for record in table.all():
    print(record)
```

The underlying file after these operations:

```jsonl
{"id": "alice", "role": "admin", "email": "alice@example.com"}
{"id": "bob", "role": "user", "email": "bob@example.com"}
{"id": "bob", "$deleted": true}
```

## When to use JSONLT

JSONLT works well for configuration, metadata, and small-to-medium datasets where you want human-readable files that play nicely with Git. It's a good fit when you need keyed record storage but don't want the overhead of a database, and when you want to see exactly what changed in a pull request.

JSONLT is not a database. For large datasets, high write throughput, query operations, or concurrent multi-process access, consider SQLite or a full-featured database.

## Compound keys

JSONLT supports multi-field compound keys for composite identifiers:

```python
orders = Table("orders.jsonlt", key=("customer_id", "order_id"))

orders.put({"customer_id": "alice", "order_id": 1, "total": 99.99})
orders.put({"customer_id": "alice", "order_id": 2, "total": 149.99})

order = orders.get(("alice", 1))
```

## Transactions

Transactions provide snapshot isolation and atomic writes with conflict detection:

```python
from jsonlt import Table, ConflictError

table = Table("counters.jsonlt", key="name")

with table.transaction() as tx:
    counter = tx.get("visits")
    new_count = (counter["count"] + 1) if counter else 1
    tx.put({"name": "visits", "count": new_count})
# Commits automatically; rolls back on exception

# Handle concurrent modification conflicts
try:
    with table.transaction() as tx:
        tx.put({"name": "counter", "value": 42})
except ConflictError as e:
    print(f"Conflict on key: {e.key}")
```

## Finding records

```python
# Find all records matching a predicate
expensive = table.find(lambda r: r.get("price", 0) > 100)

# Find with limit
top_3 = table.find(lambda r: r.get("in_stock"), limit=3)

# Find the first match
first = table.find_one(lambda r: r.get("category") == "electronics")
```

## Maintenance

```python
# Compact the file (removes tombstones and superseded records)
table.compact()

# Clear all records
table.clear()

# Force reload from disk
table.reload()
```

## API summary

### Table

| Method                        | Description                    |
|-------------------------------|--------------------------------|
| `Table(path, key)`            | Open or create a table         |
| `get(key)`                    | Get a record by key, or `None` |
| `has(key)`                    | Check if a key exists          |
| `put(record)`                 | Insert or update a record      |
| `delete(key)`                 | Delete a record                |
| `all()`                       | Iterate all records            |
| `keys()`                      | Iterate all keys               |
| `items()`                     | Iterate (key, record) pairs    |
| `count()`                     | Number of records              |
| `find(predicate, limit=None)` | Find matching records          |
| `find_one(predicate)`         | Find first match               |
| `transaction()`               | Start a transaction            |
| `compact()`                   | Remove historical entries      |
| `clear()`                     | Remove all records             |
| `reload()`                    | Reload from disk               |

The `Table` class also supports `len(table)`, `key in table`, and `for record in table`.

### Transaction

| Method        | Description       |
|---------------|-------------------|
| `get(key)`    | Get from snapshot |
| `has(key)`    | Check in snapshot |
| `put(record)` | Buffer a write    |
| `delete(key)` | Buffer a deletion |
| `commit()`    | Write to disk     |
| `abort()`     | Discard changes   |

### Exceptions

All exceptions inherit from `JSONLTError`:

| Exception          | Description               |
|--------------------|---------------------------|
| `ParseError`       | Invalid file format       |
| `InvalidKeyError`  | Invalid or missing key    |
| `FileError`        | I/O error                 |
| `LockError`        | Cannot get lock           |
| `LimitError`       | Size limit exceeded       |
| `TransactionError` | Invalid transaction state |
| `ConflictError`    | Write-write conflict      |

## Conformance

This library implements the [JSONLT 1.0 Specification](https://jsonlt.org/spec). It provides both Lenient and Strict Parser conformance profiles, and generates Strict-conformant output by default.

As the reference implementation, jsonlt-python passes the [JSONLT conformance test suite](https://github.com/jsonlt/jsonlt/tree/main/tests). Implementers of other JSONLT libraries can use these tests to verify compatibility.

## Acknowledgements

The JSONLT format draws from related work including [BEADS](https://github.com/steveyegge/beads), which uses JSONL for git-backed structured storage.

### AI disclosure

The development of this library involved AI language models, specifically Claude (Anthropic). AI tools contributed to drafting code, tests, and documentation. Human authors made all design decisions and final implementations, and they reviewed, edited, and validated AI-generated content. The authors take full responsibility for the correctness of this software.

This disclosure promotes transparency about modern software development practices.

## License

MIT License. See [LICENSE](LICENSE) for details.
