chronomap


Namechronomap JSON
Version 2.1.1 PyPI version JSON
download
home_pageNone
SummaryEnhanced thread-safe, time-versioned key-value store with snapshots, queries, async, and more.
upload_time2025-10-21 12:02:03
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords chronomap timestamp key-value time-series snapshot async rwlock
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ChronoMap

<!-- ChronoMap Logo -->
<!-- ChronoMap Logo -->
<img src="https://raw.githubusercontent.com/Devansh-567/Chronomap/main/logo/logo.png" alt="ChronoMap Logo" width="300"/>

[![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Tests](https://img.shields.io/badge/tests-102%20passed-brightgreen.svg)](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[![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\r\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\r\n[![Tests](https://img.shields.io/badge/tests-102%20passed-brightgreen.svg)](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"
}
        
Elapsed time: 1.55141s