Nitro DataStore
A flexible, schema-free data store for JSON in Python. Access nested data with dot notation, dictionary style, or path strings.
from nitro_datastore import NitroDataStore
data = NitroDataStore({'site': {'name': 'Nitro', 'url': 'https://nitro.sh'}})
data.site.name # Dot notation
data['site']['name'] # Dictionary style
data.get('site.name') # Path-based with defaults
No more config.get('site', {}).get('theme', {}).get('color', '#000'). Just config.get('site.theme.color', '#000').
Installation
pip install nitro-datastore
For AI coding assistants (Claude Code, etc.):
npx skills add nitrosh/nitro-datastore
Quick Start
Creating a DataStore
# From a dictionary
data = NitroDataStore({'title': 'Hello', 'settings': {'theme': 'dark'}})
# From a JSON file
data = NitroDataStore.from_file('config.json')
# From a directory (auto-merges all JSON files alphabetically)
data = NitroDataStore.from_directory('data/')
Reading & Writing
# Get with defaults
name = data.get('user.name', 'Anonymous')
# Set (creates intermediate dicts automatically)
data.set('config.cache.ttl', 3600)
# Check existence
if data.has('user.email'):
email = data.get('user.email')
# Delete
data.delete('user.temp_token')
# Merge another datastore
data.merge(other_data)
Saving
data.save('output.json', indent=2)
plain_dict = data.to_dict()
Query Builder
Filter and transform collections with a chainable API:
data = NitroDataStore({
'posts': [
{'title': 'Python Tips', 'views': 150, 'published': True},
{'title': 'Web Dev', 'views': 200, 'published': True},
{'title': 'Draft', 'views': 0, 'published': False}
]
})
# Filter, sort, limit
results = (data.query('posts')
.where(lambda p: p.get('published'))
.sort(key=lambda p: p.get('views'), reverse=True)
.limit(10)
.execute())
# Utilities
count = data.query('posts').where(lambda p: p.get('published')).count()
titles = data.query('posts').pluck('title')
by_category = data.query('posts').group_by('category')
first = data.query('posts').first()
Path Discovery
Explore unknown data structures:
# List all paths
paths = data.list_paths()
# Glob patterns (* = single segment, ** = any depth)
titles = data.find_paths('posts.*.title')
urls = data.find_paths('**.url')
# Find all occurrences of a key
all_urls = data.find_all_keys('url')
# Find values by predicate
emails = data.find_values(lambda v: isinstance(v, str) and '@' in v)
Bulk Operations
# Update all matching values
count = data.update_where(
condition=lambda path, value: 'http://' in str(value),
transform=lambda value: value.replace('http://', 'https://')
)
# Clean up
data.remove_nulls()
data.remove_empty()
Transformations
Transformations return new instances (immutable):
# Transform all values
upper = data.transform_all(lambda path, v: v.upper() if isinstance(v, str) else v)
# Transform all keys (e.g., kebab-case to snake_case)
snake = data.transform_keys(lambda k: k.replace('-', '_'))
Comparison
data1.equals(data2) # True/False
diff = old.diff(new)
# {'added': {...}, 'removed': {...}, 'changed': {...}}
Security
Built-in protections for file operations:
# Path traversal protection
data = NitroDataStore.from_file(user_path, base_dir='/safe/directory')
# File size limits
data = NitroDataStore.from_file(path, max_size=10*1024*1024)
Also includes: path validation, circular reference detection.
Common Gotchas
| Issue | Solution |
|---|---|
Kebab-case keys (user-name) |
Use data['user-name'] instead of dot notation |
Keys with dots (key.name) |
Use data['key.name'] - path methods treat dots as separators |
| Transform doesn't mutate | Assign the result: data = data.transform_keys(...) |
Examples
See the examples/ directory for comprehensive demos:
01_basic_operations.py- Access patterns and CRUD02_file_operations.py- Load, save, directory merging03_querying.py- Query builder usage04_path_operations.py- Path discovery and patterns05_bulk_operations.py- Batch updates and cleanup06_data_introspection.py- describe(), stats(), flatten()07_comparison.py- diff() and equals()08_comprehensive_example.py- Real-world workflow09_security_features.py- Security protections
Ecosystem
- nitro-ui - Build HTML with Python, not strings
- nitro-cli - Static site generator powered by nitro-ui
- nitro-dispatch - Framework-agnostic plugin system
- nitro-image - Fast, friendly image processing for the web
- nitro-validate - Dependency-free data validation
License
MIT License. See LICENSE for details.
Metadata
Release files for nitro-datastore 1.0.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nitro_datastore-1.0.5.tar.gz | 30.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nitro_datastore-1.0.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 46.4 kB
Release files / nitro_datastore-1.0.5.tar.gz
| Download URL | nitro_datastore-1.0.5.tar.gz |
|---|---|
| Size | 30.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
205713c318fb99c8587f54081616ff7efa5cb08e7bd018431c06f05a2b319bea
|
|
BLAKE2b-256 checksum How to use checksums |
0ea62a3151d58331024951c756ac081a2ece97e0792fd274cac1b1490c8341c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / nitro_datastore-1.0.5-py3-none-any.whl
| Download URL | nitro_datastore-1.0.5-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
68904d1cb35fb1e6328d84053d4339937018f7fc8d044099a51d5d838b370722
|
|
BLAKE2b-256 checksum How to use checksums |
8d8b401b19632cc26a968fcfb8a83b04be2e1f3bc7bae24b9711e751d99fcee3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|