# ChronoMap
<!-- ChronoMap Logo -->
<!-- ChronoMap Logo -->
<img src="https://raw.githubusercontent.com/Devansh-567/Chronomap/main/logo/logo.png" alt="ChronoMap Logo" width="300"/>
[](https://www.python.org/downloads/)
[](LICENSE)
[](tests/)
**ChronoMap** is a thread-safe, time-versioned key-value store for Python that maintains complete history of all changes. Perfect for configuration management, audit trails, time-series data, session stores, and any application requiring historical data tracking with **concurrency, async, and analytics.**
## β¨ Features
- **β±οΈ Time-Versioned Storage** - Every value change is timestamped and preserved
- **π Thread-Safe** - All operations are protected with locks for concurrent access
- **π Async Support** β Full AsyncChronoMap for asyncio applications
- **πΈ Snapshots & Rollback** - Create snapshots and rollback to any previous state
- **β° TTL Support** - Automatic key expiration with time-to-live
- **π Query & Analytics** β Filter, aggregate, count, and analyze your data
- **π§Ή History Pruning** β Garbage-collect old versions to manage memory
- **π Statistics Tracking** β Monitor reads, writes, deletes, and snapshots
- **π Event Hooks** β Register callbacks on every change (on_change)
- **π Batch Operations** - Efficient `put_many()` and `delete_many()` operations
- **π Advanced Queries** - Range queries, find latest keys, search by value
- **π€ Merge & Diff** - Merge multiple maps and track differences
- **π Context Manager** β Automatic rollback on exception with snapshot_context()
- **πΎ Persistence** - Save/load from JSON or Pickle
- **πΌ Pandas Export** β Export full history to DataFrame for analysis
- **π Pythonic API** - Dictionary-like interface with magic methods
- **π Comprehensive Testing** - 102 tests with >95% coverage
## π¦ Installation
```bash
pip install chronomap
```
> π‘ Optional: pip install pandas for to_dataframe() support
## π Quick Start
```python
from chronomap import ChronoMap
cm = ChronoMap()
cm['user'] = 'alice'
cm['status'] = 'active'
print(cm['user'])
# Query active users
active = cm.query(lambda k, v: v == 'active')
# Track changes
def log_change(key, old, new, ts):
print(f"{key}: {old} β {new}")
cm.on_change(log_change)
# Prune old history
cm.prune_all_history(keep_last=100)
```
## π Documentation
### Basic Operations
```python
cm.put('key', 'value')
value = cm.get('key')
cm.delete('key')
cm['key'] = 'value'
value = cm['key']
del cm['key']
if 'key' in cm:
print("Key exists")
value = cm.get('nonexistent', default='default_value')
try:
value = cm.get('nonexistent', strict=True)
except ChronoMapKeyError:
print("Key not found")
```
### Time Travel with Datetime
```python
# Use datetime strings or objects
cm.put('event', 'login', timestamp="2025-10-21T12:00:00")
cm.put('event', 'logout', timestamp=datetime(2025, 10, 21, 13, 0, 0))
# Query at specific time
value = cm.get('event', timestamp="2025-10-21T12:30:00")
```
### TTL and Auto-Expiry
```python
cm.put('session_token', 'abc123', ttl=3600)
print(cm.get('session_token'))
removed_count = cm.clean_expired_keys()
print(f"Removed {removed_count} expired keys")
```
### Snapshots and Context Manager
```python
cm['counter'] = 10
with cm.snapshot_context():
cm['counter'] = 100
cm['temp'] = 'data'
raise Exception("Rollback!") # Auto-rollback on exception
print(cm['counter']) # 10
print(cm.get('temp')) # None
```
### Event Hooks
```python
def audit_log(key, old, new, ts):
print(f"[AUDIT] {key}: {old} β {new} at {ts}")
cm.on_change(audit_log)
cm['config'] = 'new_value'
```
### Query & Aggregation
```python
cm.put_many({'score1': 85, 'score2': 92, 'score3': 78})
# Filter
high_scores = cm.query(lambda k, v: isinstance(v, int) and v > 80)
# Aggregate
avg = cm.aggregate(lambda vals: sum(vals) / len(vals))
total = cm.aggregate(sum, keys=['score1', 'score2'])
# Count
active_count = cm.count(lambda k, v: v == 'active')
```
### History Pruning
```python
# Keep only last 10 versions
cm.prune_history('sensor', keep_last=10)
# Remove versions older than date
cm.prune_history('log', older_than="2025-01-01")
# Prune all keys
cm.prune_all_history(keep_last=100)
```
### AsyncChronoMap
```python
import asyncio
from chronomap import AsyncChronoMap
async def main():
cm = AsyncChronoMap()
await cm.put('key', 'value')
value = await cm.get('key')
snap = await cm.snapshot()
keys = await cm.keys()
latest = await cm.latest()
asyncio.run(main())
```
### Pandas Export
```python
# Requires: pip install pandas
df = cm.to_dataframe()
print(df.head())
# key value timestamp datetime version
# 0 temp 20 100.0 1970-01-01 00:01:40 0
```
### Compression and Persistence
```python
# Save with compression
cm.save_pickle('state.pkl', compress=True)
# Load automatically detects compression
cm2 = ChronoMap.load_pickle('state.pkl')
```
### Statistics
```python
stats = cm.get_stats()
print(f"Writes: {stats['writes']}, Reads: {stats['reads']}")
cm.reset_stats()
```
### Batch Operations
```python
users = {
'user:1': {'name': 'Alice', 'role': 'admin'},
'user:2': {'name': 'Bob', 'role': 'user'},
'user:3': {'name': 'Charlie', 'role': 'user'}
}
cm.put_many(users)
cm.put_many(users, ttl=3600)
cm.put_many(users, timestamp=1609459200)
deleted_count = cm.delete_many(['user:2', 'user:3'])
print(f"Deleted {deleted_count} keys")
```
### Advanced Queries
```python
cm.put('sensor', 10, timestamp=100)
cm.put('sensor', 15, timestamp=200)
cm.put('sensor', 20, timestamp=300)
readings = cm.get_range('sensor', start_ts=150, end_ts=250)
latest = cm.get_latest_keys(2)
for key, timestamp, value in latest:
print(f"{key}: {value} (updated at {timestamp})")
cm.put_many({'user1': 'active', 'user2': 'active', 'user3': 'inactive'})
active_users = cm.get_keys_by_value('active')
```
### Merge and Diff
```python
cm1 = ChronoMap()
cm2 = ChronoMap()
cm1.put('shared', 'v1', timestamp=100)
cm2.put('shared', 'v2', timestamp=200)
cm2.put('unique', 'data')
cm1.merge(cm2, strategy='timestamp')
changed_keys = cm1.diff(cm2)
```
### Iteratons and Utilities
```python
for key in cm:
print(key)
latest = cm.latest()
history = cm.history('key')
print(len(cm))
cm.clear()
```
## π§ͺ Testing
```bash
# Run all tests
pytest tests/test_chronomap.py -v
# With coverage
pytest tests/test_chronomap.py --cov=chronomap --cov-report=html
# Run specific test class
pytest tests/test_chronomap.py::TestAsyncChronoMap -v
```
## Test coverage includes:
- β
Basic operations (put, get, delete)
- β
Batch operations
- β
TTL and expiry
- β
Advanced queries
- β
Snapshots, context manager, rollback
- β
Merge and diff
- β
Magic methods & iteration
- β
Persistence (JSON, Pickle, compression)
- β
Thread safety & RWLock
- β
AsyncChronoMap
- β
Query, aggregation, pruning
- β
Event hooks & statistics
- β
Pandas export
- β
Edge cases & integration scenarios
### Project Structure
```
chronomap/
βββ chronomap/
β βββ __init__.py
β βββ chronomap.py # Core implementation
β βββ cli.py
β βββ __main__.py # CLI interface
βββ tests/
β βββ test_chronomap.py # Test suite
βββ examples/
β βββ config_manager.py
β βββ session_store.py
β βββ metrics_store.py
βββ logo/
β βββ logo.png
βββ README.md
βββ setup.py
βββ pyproject.toml
βββ LICENSE
```
### Contributing
1. Fork the repository
2. Write tests for your changes
3. Ensure all tests pass (`pytest tests/ -v`)
4. Commit your changes (`git commit -m 'Add amazing feature'`)
5. Push to the branch (`git push origin feature/amazing-feature`)
6. Open a Pull Request
## π Requirements
- Python 3.8+
- No external dependencies for core functionality
- Optional: pandas for to_dataframe()
- Development dependencies: pytest, pytest-cov, pytest-asyncio
## πΊοΈ Roadmap
- [ ] Async/await support β
(v2.1.0)
- [ ] Read-write locks β
(v2.1.0)
- [ ] Query & aggregation β
(v2.1.0)
- [ ] History pruning β
(v2.1.0)
- [ ] Event hooks β
(v2.1.0)
- [ ] Compression β
(v2.1.0)
- [ ] Pandas export β
(v2.1.0)
- [ ] SQLite backend for persistence
- [ ] Web UI for visualization
- [ ] Export to various formats (CSV, Parquet)
- [ ] Query language for complex searches
- [ ] Integration with popular frameworks (Django, Flask)
## π Changelog
### v2.1.0 (2025)
- Added AsyncChronoMap for asyncio support
- Implemented read-write locks for better concurrency
- Added query filters, aggregations, and counting
- Added event hooks (on_change callbacks)
- Added history pruning (prune_history, prune_all_history)
- Added snapshot context manager (snapshot_context)
- Added operation statistics tracking
- Added compression support (zlib + pickle)
- Added Pandas DataFrame export
- Enhanced datetime string support ("2025-10-21T12:00:00")
- Improved CLI demo and error handling
### v2.0.0 (2025)
- Complete rewrite with enhanced features
- Added TTL/expiry support
- Added batch operations
- Added advanced queries (range, latest keys, search by value)
- Added merge and diff functionality
- Added comprehensive test suite (65 tests)
- Improved thread safety
- Enhanced documentation
### v1.0.0
- Initial release
- Basic time-versioned storage
- Snapshot and rollback
- Persistence support
## π‘ Tips and Best Practices
1. **Use TTL for temporary data** - Session tokens, cache entries, temporary flags
2. **Use snapshot_context()** - Risky operations β Auto-rollback on failure
3. **Prune history regularly** β Prevent memory bloat with prune_all_history()
4. **Use async for I/O-bound apps** β Web servers, data pipelines
5. **Monitor Stats** - Track usage patterns with get_stats()
6. **Enable compression** β For large persistent states
7. **Export to Pandas** β Analyze time-series data with familiar tools
8. **Take snapshots before risky operations** - Database migrations, bulk updates
9. **Use batch operations** - More efficient than individual operations
10. **Clean expired keys regularly** - Call `clean_expired_keys()` during maintenance
11. **Leverage history for auditing** - Track configuration changes, document versions
12. **Use descriptive key naming** - `user:123:profile` is better than `u123p`
13. **Persist regularly** - Save state periodically using `save_json()` or `save_pickle()`
14. **Monitor map size** - Large histories may need archiving or cleanup
## β FAQ
**Q: Is ChronoMap suitable for production use?**
A: Yes! ChronoMap is thread-safe, well-tested, and used in production environments.
**Q: How much memory does ChronoMap use?**
A: Memory usage depends on the number of keys and history size. Each value change is stored, so keys with frequent updates will use more memory.
**Q: Can I use ChronoMap as a database?**
A: ChronoMap is an in-memory store. For persistence, use `save_json()` or `save_pickle()`. For large-scale data, consider a proper database.
**Q: How do I limit history size?**
A: Currently, you need to manually manage history. Consider periodically archiving old data or implementing custom cleanup logic.
**Q: Is ChronoMap compatible with multiprocessing?**
A: ChronoMap is thread-safe but not process-safe. For multiprocessing, use separate instances or implement inter-process communication.
**Q: Can I use ChronoMap with Django/Flask?**
A: Yes! ChronoMap works well as a cache layer or session store in web applications.
**Q: How do I upgrade from v2.0.0?**
A: Fully backward-compatible! Just pip install chronomap==2.1.0.
---
## π License
## This project is licensed under the MIT License
Made with π by [Devansh Singh](https://github.com/Devasnh-567)
Raw data
{
"_id": null,
"home_page": null,
"name": "chronomap",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "chronomap, timestamp, key-value, time-series, snapshot, async, rwlock",
"author": null,
"author_email": "Devansh Singh <devansh.jay.singh@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/66/5a/59388fc94aa71ef4f885847212de6d56f9034a8228fa2bf4b8adf7dd2e2b/chronomap-2.1.1.tar.gz",
"platform": null,
"description": "# ChronoMap\r\n\r\n<!-- ChronoMap Logo -->\r\n<!-- ChronoMap Logo -->\r\n<img src=\"https://raw.githubusercontent.com/Devansh-567/Chronomap/main/logo/logo.png\" alt=\"ChronoMap Logo\" width=\"300\"/>\r\n\r\n[](https://www.python.org/downloads/)\r\n[](LICENSE)\r\n[](tests/)\r\n\r\n**ChronoMap** is a thread-safe, time-versioned key-value store for Python that maintains complete history of all changes. Perfect for configuration management, audit trails, time-series data, session stores, and any application requiring historical data tracking with **concurrency, async, and analytics.**\r\n\r\n## \u2728 Features\r\n\r\n- **\u23f1\ufe0f Time-Versioned Storage** - Every value change is timestamped and preserved\r\n- **\ud83d\udd12 Thread-Safe** - All operations are protected with locks for concurrent access\r\n- **\ud83c\udf19 Async Support** \u2013 Full AsyncChronoMap for asyncio applications\r\n- **\ud83d\udcf8 Snapshots & Rollback** - Create snapshots and rollback to any previous state\r\n- **\u23f0 TTL Support** - Automatic key expiration with time-to-live\r\n- **\ud83d\udcca Query & Analytics** \u2013 Filter, aggregate, count, and analyze your data\r\n- **\ud83e\uddf9 History Pruning** \u2013 Garbage-collect old versions to manage memory\r\n- **\ud83d\udcc8 Statistics Tracking** \u2013 Monitor reads, writes, deletes, and snapshots\r\n- **\ud83d\udd14 Event Hooks** \u2013 Register callbacks on every change (on_change)\r\n- **\ud83d\udd04 Batch Operations** - Efficient `put_many()` and `delete_many()` operations\r\n- **\ud83d\udd0d Advanced Queries** - Range queries, find latest keys, search by value\r\n- **\ud83e\udd1d Merge & Diff** - Merge multiple maps and track differences\r\n- **\ud83d\udd04 Context Manager** \u2013 Automatic rollback on exception with snapshot_context()\r\n- **\ud83d\udcbe Persistence** - Save/load from JSON or Pickle\r\n- **\ud83d\udc3c Pandas Export** \u2013 Export full history to DataFrame for analysis\r\n- **\ud83d\udc0d Pythonic API** - Dictionary-like interface with magic methods\r\n- **\ud83d\udcdd Comprehensive Testing** - 102 tests with >95% coverage\r\n\r\n## \ud83d\udce6 Installation\r\n\r\n```bash\r\npip install chronomap\r\n```\r\n\r\n> \ud83d\udca1 Optional: pip install pandas for to_dataframe() support\r\n\r\n## \ud83d\ude80 Quick Start\r\n\r\n```python\r\nfrom chronomap import ChronoMap\r\n\r\ncm = ChronoMap()\r\ncm['user'] = 'alice'\r\ncm['status'] = 'active'\r\nprint(cm['user'])\r\n\r\n# Query active users\r\nactive = cm.query(lambda k, v: v == 'active')\r\n\r\n# Track changes\r\ndef log_change(key, old, new, ts):\r\n print(f\"{key}: {old} \u2192 {new}\")\r\ncm.on_change(log_change)\r\n\r\n# Prune old history\r\ncm.prune_all_history(keep_last=100)\r\n```\r\n\r\n## \ud83d\udcda Documentation\r\n\r\n### Basic Operations\r\n\r\n```python\r\ncm.put('key', 'value')\r\nvalue = cm.get('key')\r\ncm.delete('key')\r\n\r\ncm['key'] = 'value'\r\nvalue = cm['key']\r\ndel cm['key']\r\n\r\nif 'key' in cm:\r\n print(\"Key exists\")\r\nvalue = cm.get('nonexistent', default='default_value')\r\n\r\ntry:\r\n value = cm.get('nonexistent', strict=True)\r\nexcept ChronoMapKeyError:\r\n print(\"Key not found\")\r\n```\r\n\r\n### Time Travel with Datetime\r\n\r\n```python\r\n# Use datetime strings or objects\r\ncm.put('event', 'login', timestamp=\"2025-10-21T12:00:00\")\r\ncm.put('event', 'logout', timestamp=datetime(2025, 10, 21, 13, 0, 0))\r\n\r\n# Query at specific time\r\nvalue = cm.get('event', timestamp=\"2025-10-21T12:30:00\")\r\n```\r\n\r\n### TTL and Auto-Expiry\r\n\r\n```python\r\ncm.put('session_token', 'abc123', ttl=3600)\r\nprint(cm.get('session_token'))\r\nremoved_count = cm.clean_expired_keys()\r\nprint(f\"Removed {removed_count} expired keys\")\r\n```\r\n\r\n### Snapshots and Context Manager\r\n\r\n```python\r\ncm['counter'] = 10\r\nwith cm.snapshot_context():\r\n cm['counter'] = 100\r\n cm['temp'] = 'data'\r\n raise Exception(\"Rollback!\") # Auto-rollback on exception\r\n\r\nprint(cm['counter']) # 10\r\nprint(cm.get('temp')) # None\r\n```\r\n\r\n### Event Hooks\r\n\r\n```python\r\ndef audit_log(key, old, new, ts):\r\n print(f\"[AUDIT] {key}: {old} \u2192 {new} at {ts}\")\r\n\r\ncm.on_change(audit_log)\r\ncm['config'] = 'new_value'\r\n```\r\n\r\n### Query & Aggregation\r\n\r\n```python\r\ncm.put_many({'score1': 85, 'score2': 92, 'score3': 78})\r\n\r\n# Filter\r\nhigh_scores = cm.query(lambda k, v: isinstance(v, int) and v > 80)\r\n\r\n# Aggregate\r\navg = cm.aggregate(lambda vals: sum(vals) / len(vals))\r\ntotal = cm.aggregate(sum, keys=['score1', 'score2'])\r\n\r\n# Count\r\nactive_count = cm.count(lambda k, v: v == 'active')\r\n```\r\n\r\n### History Pruning\r\n\r\n```python\r\n# Keep only last 10 versions\r\ncm.prune_history('sensor', keep_last=10)\r\n\r\n# Remove versions older than date\r\ncm.prune_history('log', older_than=\"2025-01-01\")\r\n\r\n# Prune all keys\r\ncm.prune_all_history(keep_last=100)\r\n```\r\n\r\n### AsyncChronoMap\r\n\r\n```python\r\nimport asyncio\r\nfrom chronomap import AsyncChronoMap\r\n\r\nasync def main():\r\n cm = AsyncChronoMap()\r\n await cm.put('key', 'value')\r\n value = await cm.get('key')\r\n snap = await cm.snapshot()\r\n keys = await cm.keys()\r\n latest = await cm.latest()\r\n\r\nasyncio.run(main())\r\n```\r\n\r\n### Pandas Export\r\n\r\n```python\r\n# Requires: pip install pandas\r\ndf = cm.to_dataframe()\r\nprint(df.head())\r\n# key value timestamp datetime version\r\n# 0 temp 20 100.0 1970-01-01 00:01:40 0\r\n```\r\n\r\n### Compression and Persistence\r\n\r\n```python\r\n# Save with compression\r\ncm.save_pickle('state.pkl', compress=True)\r\n\r\n# Load automatically detects compression\r\ncm2 = ChronoMap.load_pickle('state.pkl')\r\n```\r\n\r\n### Statistics\r\n\r\n```python\r\nstats = cm.get_stats()\r\nprint(f\"Writes: {stats['writes']}, Reads: {stats['reads']}\")\r\ncm.reset_stats()\r\n```\r\n\r\n### Batch Operations\r\n\r\n```python\r\nusers = {\r\n 'user:1': {'name': 'Alice', 'role': 'admin'},\r\n 'user:2': {'name': 'Bob', 'role': 'user'},\r\n 'user:3': {'name': 'Charlie', 'role': 'user'}\r\n}\r\ncm.put_many(users)\r\ncm.put_many(users, ttl=3600)\r\ncm.put_many(users, timestamp=1609459200)\r\ndeleted_count = cm.delete_many(['user:2', 'user:3'])\r\nprint(f\"Deleted {deleted_count} keys\")\r\n```\r\n\r\n### Advanced Queries\r\n\r\n```python\r\ncm.put('sensor', 10, timestamp=100)\r\ncm.put('sensor', 15, timestamp=200)\r\ncm.put('sensor', 20, timestamp=300)\r\nreadings = cm.get_range('sensor', start_ts=150, end_ts=250)\r\n\r\nlatest = cm.get_latest_keys(2)\r\nfor key, timestamp, value in latest:\r\n print(f\"{key}: {value} (updated at {timestamp})\")\r\n\r\ncm.put_many({'user1': 'active', 'user2': 'active', 'user3': 'inactive'})\r\nactive_users = cm.get_keys_by_value('active')\r\n```\r\n\r\n### Merge and Diff\r\n\r\n```python\r\ncm1 = ChronoMap()\r\ncm2 = ChronoMap()\r\ncm1.put('shared', 'v1', timestamp=100)\r\ncm2.put('shared', 'v2', timestamp=200)\r\ncm2.put('unique', 'data')\r\ncm1.merge(cm2, strategy='timestamp')\r\nchanged_keys = cm1.diff(cm2)\r\n```\r\n\r\n### Iteratons and Utilities\r\n\r\n```python\r\nfor key in cm:\r\n print(key)\r\n\r\nlatest = cm.latest()\r\nhistory = cm.history('key')\r\nprint(len(cm))\r\ncm.clear()\r\n```\r\n\r\n## \ud83e\uddea Testing\r\n\r\n```bash\r\n# Run all tests\r\npytest tests/test_chronomap.py -v\r\n\r\n# With coverage\r\npytest tests/test_chronomap.py --cov=chronomap --cov-report=html\r\n\r\n# Run specific test class\r\npytest tests/test_chronomap.py::TestAsyncChronoMap -v\r\n```\r\n\r\n## Test coverage includes:\r\n\r\n- \u2705 Basic operations (put, get, delete)\r\n- \u2705 Batch operations\r\n- \u2705 TTL and expiry\r\n- \u2705 Advanced queries\r\n- \u2705 Snapshots, context manager, rollback\r\n- \u2705 Merge and diff\r\n- \u2705 Magic methods & iteration\r\n- \u2705 Persistence (JSON, Pickle, compression)\r\n- \u2705 Thread safety & RWLock\r\n- \u2705 AsyncChronoMap\r\n- \u2705 Query, aggregation, pruning\r\n- \u2705 Event hooks & statistics\r\n- \u2705 Pandas export\r\n- \u2705 Edge cases & integration scenarios\r\n\r\n### Project Structure\r\n\r\n```\r\nchronomap/\r\n\u251c\u2500\u2500 chronomap/\r\n\u2502 \u251c\u2500\u2500 __init__.py\r\n\u2502 \u251c\u2500\u2500 chronomap.py # Core implementation\r\n\u2502 \u251c\u2500\u2500 cli.py\r\n\u2502 \u2514\u2500\u2500 __main__.py # CLI interface\r\n\u251c\u2500\u2500 tests/\r\n\u2502 \u2514\u2500\u2500 test_chronomap.py # Test suite\r\n\u251c\u2500\u2500 examples/\r\n\u2502 \u251c\u2500\u2500 config_manager.py\r\n\u2502 \u251c\u2500\u2500 session_store.py\r\n\u2502 \u2514\u2500\u2500 metrics_store.py\r\n\u251c\u2500\u2500 logo/\r\n\u2502 \u2514\u2500\u2500 logo.png\r\n\u251c\u2500\u2500 README.md\r\n\u251c\u2500\u2500 setup.py\r\n\u251c\u2500\u2500 pyproject.toml\r\n\u2514\u2500\u2500 LICENSE\r\n```\r\n\r\n### Contributing\r\n\r\n1. Fork the repository\r\n2. Write tests for your changes\r\n3. Ensure all tests pass (`pytest tests/ -v`)\r\n4. Commit your changes (`git commit -m 'Add amazing feature'`)\r\n5. Push to the branch (`git push origin feature/amazing-feature`)\r\n6. Open a Pull Request\r\n\r\n## \ud83d\udccb Requirements\r\n\r\n- Python 3.8+\r\n- No external dependencies for core functionality\r\n- Optional: pandas for to_dataframe()\r\n- Development dependencies: pytest, pytest-cov, pytest-asyncio\r\n\r\n## \ud83d\uddfa\ufe0f Roadmap\r\n\r\n- [ ] Async/await support \u2705 (v2.1.0)\r\n- [ ] Read-write locks \u2705 (v2.1.0)\r\n- [ ] Query & aggregation \u2705 (v2.1.0)\r\n- [ ] History pruning \u2705 (v2.1.0)\r\n- [ ] Event hooks \u2705 (v2.1.0)\r\n- [ ] Compression \u2705 (v2.1.0)\r\n- [ ] Pandas export \u2705 (v2.1.0)\r\n- [ ] SQLite backend for persistence\r\n- [ ] Web UI for visualization\r\n- [ ] Export to various formats (CSV, Parquet)\r\n- [ ] Query language for complex searches\r\n- [ ] Integration with popular frameworks (Django, Flask)\r\n\r\n## \ud83d\udcc8 Changelog\r\n\r\n### v2.1.0 (2025)\r\n\r\n- Added AsyncChronoMap for asyncio support\r\n- Implemented read-write locks for better concurrency\r\n- Added query filters, aggregations, and counting\r\n- Added event hooks (on_change callbacks)\r\n- Added history pruning (prune_history, prune_all_history)\r\n- Added snapshot context manager (snapshot_context)\r\n- Added operation statistics tracking\r\n- Added compression support (zlib + pickle)\r\n- Added Pandas DataFrame export\r\n- Enhanced datetime string support (\"2025-10-21T12:00:00\")\r\n- Improved CLI demo and error handling\r\n\r\n### v2.0.0 (2025)\r\n\r\n- Complete rewrite with enhanced features\r\n- Added TTL/expiry support\r\n- Added batch operations\r\n- Added advanced queries (range, latest keys, search by value)\r\n- Added merge and diff functionality\r\n- Added comprehensive test suite (65 tests)\r\n- Improved thread safety\r\n- Enhanced documentation\r\n\r\n### v1.0.0\r\n\r\n- Initial release\r\n- Basic time-versioned storage\r\n- Snapshot and rollback\r\n- Persistence support\r\n\r\n## \ud83d\udca1 Tips and Best Practices\r\n\r\n1. **Use TTL for temporary data** - Session tokens, cache entries, temporary flags\r\n2. **Use snapshot_context()** - Risky operations \u2013 Auto-rollback on failure\r\n3. **Prune history regularly** \u2013 Prevent memory bloat with prune_all_history()\r\n4. **Use async for I/O-bound apps** \u2013 Web servers, data pipelines\r\n5. **Monitor Stats** - Track usage patterns with get_stats()\r\n6. **Enable compression** \u2013 For large persistent states\r\n7. **Export to Pandas** \u2013 Analyze time-series data with familiar tools\r\n8. **Take snapshots before risky operations** - Database migrations, bulk updates\r\n9. **Use batch operations** - More efficient than individual operations\r\n10. **Clean expired keys regularly** - Call `clean_expired_keys()` during maintenance\r\n11. **Leverage history for auditing** - Track configuration changes, document versions\r\n12. **Use descriptive key naming** - `user:123:profile` is better than `u123p`\r\n13. **Persist regularly** - Save state periodically using `save_json()` or `save_pickle()`\r\n14. **Monitor map size** - Large histories may need archiving or cleanup\r\n\r\n## \u2753 FAQ\r\n\r\n**Q: Is ChronoMap suitable for production use?** \r\nA: Yes! ChronoMap is thread-safe, well-tested, and used in production environments.\r\n\r\n**Q: How much memory does ChronoMap use?** \r\nA: Memory usage depends on the number of keys and history size. Each value change is stored, so keys with frequent updates will use more memory.\r\n\r\n**Q: Can I use ChronoMap as a database?** \r\nA: ChronoMap is an in-memory store. For persistence, use `save_json()` or `save_pickle()`. For large-scale data, consider a proper database.\r\n\r\n**Q: How do I limit history size?** \r\nA: Currently, you need to manually manage history. Consider periodically archiving old data or implementing custom cleanup logic.\r\n\r\n**Q: Is ChronoMap compatible with multiprocessing?** \r\nA: ChronoMap is thread-safe but not process-safe. For multiprocessing, use separate instances or implement inter-process communication.\r\n\r\n**Q: Can I use ChronoMap with Django/Flask?** \r\nA: Yes! ChronoMap works well as a cache layer or session store in web applications.\r\n\r\n**Q: How do I upgrade from v2.0.0?** \r\nA: Fully backward-compatible! Just pip install chronomap==2.1.0.\r\n\r\n---\r\n\r\n## \ud83d\udcc4 License\r\n\r\n## This project is licensed under the MIT License\r\n\r\nMade with \ud83d\ude0e by [Devansh Singh](https://github.com/Devasnh-567)\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Enhanced thread-safe, time-versioned key-value store with snapshots, queries, async, and more.",
"version": "2.1.1",
"project_urls": {
"Homepage": "https://github.com/Devansh-567/chronomap",
"Icon": "https://raw.githubusercontent.com/Devansh-567/Chronomap/main/logo/logo.png"
},
"split_keywords": [
"chronomap",
" timestamp",
" key-value",
" time-series",
" snapshot",
" async",
" rwlock"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "cbe533095ca7f10538ca4e96759fe4a3f147bf1ce3d4704d9551d3f0427f93ea",
"md5": "61581c2b970260b9be51836e2c649ed5",
"sha256": "3283082433e5229c4e26e0501c35753db27727d730f0ef7e3187021e6cf380e2"
},
"downloads": -1,
"filename": "chronomap-2.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "61581c2b970260b9be51836e2c649ed5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 42320,
"upload_time": "2025-10-21T12:02:02",
"upload_time_iso_8601": "2025-10-21T12:02:02.320251Z",
"url": "https://files.pythonhosted.org/packages/cb/e5/33095ca7f10538ca4e96759fe4a3f147bf1ce3d4704d9551d3f0427f93ea/chronomap-2.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "665a59388fc94aa71ef4f885847212de6d56f9034a8228fa2bf4b8adf7dd2e2b",
"md5": "90ec488470f1c2cc28e371dc08b18ab0",
"sha256": "feeb083712b00523d1eb1e873b3630c15bc32f4ee49a6955529ed021b92fbb19"
},
"downloads": -1,
"filename": "chronomap-2.1.1.tar.gz",
"has_sig": false,
"md5_digest": "90ec488470f1c2cc28e371dc08b18ab0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 47928,
"upload_time": "2025-10-21T12:02:03",
"upload_time_iso_8601": "2025-10-21T12:02:03.997177Z",
"url": "https://files.pythonhosted.org/packages/66/5a/59388fc94aa71ef4f885847212de6d56f9034a8228fa2bf4b8adf7dd2e2b/chronomap-2.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-21 12:02:03",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Devansh-567",
"github_project": "chronomap",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "chronomap"
}