prollytree 0.4.0

A prolly (probabilistic) tree for efficient storage, retrieval, and modification of ordered data.
Documentation
Examples
========

This page contains comprehensive examples showing how to use ProllyTree in different scenarios.

Basic Tree Operations
---------------------

Simple Key-Value Store
~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   from prollytree import ProllyTree

   def example_basic_kv_store():
       """Basic key-value store example"""
       tree = ProllyTree()

       # Store user data
       users = {
           "alice": {"name": "Alice Smith", "age": 30},
           "bob": {"name": "Bob Jones", "age": 25},
           "charlie": {"name": "Charlie Brown", "age": 35}
       }

       # Insert users
       import json
       for user_id, user_data in users.items():
           key = f"user:{user_id}".encode('utf-8')
           value = json.dumps(user_data).encode('utf-8')
           tree.insert(key, value)

       # Retrieve a user
       alice_data = tree.find(b"user:alice")
       if alice_data:
           alice = json.loads(alice_data.decode('utf-8'))
           print(f"Alice: {alice['name']}, age {alice['age']}")

       return tree

Working with Different Data Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   import json
   import pickle
   from datetime import datetime

   def example_data_types():
       """Examples of storing different data types"""
       tree = ProllyTree()

       # String data
       tree.insert(b"string_key", "Hello, World!".encode('utf-8'))

       # JSON data
       data = {"name": "Alice", "scores": [95, 87, 92]}
       tree.insert(b"json_key", json.dumps(data).encode('utf-8'))

       # Binary data (using pickle)
       complex_data = {
           "timestamp": datetime.now(),
           "nested": {"list": [1, 2, 3], "dict": {"a": 1}}
       }
       tree.insert(b"pickle_key", pickle.dumps(complex_data))

       # Retrieve and decode
       string_val = tree.find(b"string_key").decode('utf-8')
       json_val = json.loads(tree.find(b"json_key").decode('utf-8'))
       pickle_val = pickle.loads(tree.find(b"pickle_key"))

       print(f"String: {string_val}")
       print(f"JSON: {json_val}")
       print(f"Pickle: {pickle_val}")

Versioned Storage Examples
--------------------------

Document Version Control
~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   from prollytree import VersionedKvStore
   import json
   from datetime import datetime

   def example_document_versioning():
       """Example of version controlling documents"""
       store = VersionedKvStore("./document_store")

       # Create initial document
       doc = {
           "title": "My Document",
           "content": "Initial content",
           "author": "Alice",
           "created": datetime.now().isoformat()
       }

       store.insert(b"doc:readme", json.dumps(doc).encode('utf-8'))
       commit1 = store.commit("Initial document creation")
       print(f"Initial commit: {commit1[:8]}")

       # Update document
       doc["content"] = "Updated content with more details"
       doc["modified"] = datetime.now().isoformat()
       store.update(b"doc:readme", json.dumps(doc).encode('utf-8'))
       commit2 = store.commit("Add more content details")
       print(f"Update commit: {commit2[:8]}")

       # View commit history
       print("\\nCommit History:")
       commits = store.log()
       for commit in commits:
           timestamp = datetime.fromtimestamp(commit['timestamp'])
           print(f"  {commit['id'][:8]} - {commit['message']} ({timestamp})")

       return store

Configuration Management
~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   def example_config_management():
       """Example of managing application configuration with versions"""
       store = VersionedKvStore("./config_store")

       # Production config
       prod_config = {
           "database": {
               "host": "prod-db.example.com",
               "port": 5432,
               "ssl": True
           },
           "api": {
               "rate_limit": 1000,
               "timeout": 30
           }
       }

       store.insert(b"config:production", json.dumps(prod_config).encode('utf-8'))
       store.commit("Initial production configuration")

       # Development config
       dev_config = prod_config.copy()
       dev_config["database"]["host"] = "localhost"
       dev_config["database"]["ssl"] = False
       dev_config["api"]["rate_limit"] = 10000  # Higher for dev

       store.insert(b"config:development", json.dumps(dev_config).encode('utf-8'))
       store.commit("Add development configuration")

       # Update production config
       prod_config["api"]["rate_limit"] = 2000  # Increase rate limit
       store.update(b"config:production", json.dumps(prod_config).encode('utf-8'))
       store.commit("Increase production rate limit")

       # Retrieve current configs
       current_prod = json.loads(store.get(b"config:production").decode('utf-8'))
       print(f"Production rate limit: {current_prod['api']['rate_limit']}")

       return store

SQL Query Examples
------------------

.. code-block:: python

   from prollytree import ProllySQLStore

   def example_sql_analytics():
       """Example using SQL for data analytics"""
       sql_store = ProllySQLStore("./analytics_store")

       # Create tables
       sql_store.execute("""
           CREATE TABLE users (
               id INTEGER,
               name TEXT,
               email TEXT,
               signup_date TEXT,
               plan TEXT
           )
       """)

       sql_store.execute("""
           CREATE TABLE events (
               id INTEGER,
               user_id INTEGER,
               event_type TEXT,
               timestamp TEXT,
               metadata TEXT
           )
       """)

       # Insert sample data
       users_data = [
           (1, 'Alice Smith', 'alice@example.com', '2023-01-15', 'premium'),
           (2, 'Bob Jones', 'bob@example.com', '2023-02-01', 'basic'),
           (3, 'Charlie Brown', 'charlie@example.com', '2023-02-15', 'premium'),
       ]

       for user in users_data:
           sql_store.execute(
               "INSERT INTO users (id, name, email, signup_date, plan) VALUES (?, ?, ?, ?, ?)",
               user
           )

       # Analytics queries
       print("=== User Analytics ===")

       # Premium users
       premium_users = sql_store.execute(
           "SELECT name, email FROM users WHERE plan = 'premium'"
       )
       print(f"Premium users: {len(premium_users)}")
       for user in premium_users:
           print(f"  - {user[0]} ({user[1]})")

       return sql_store

Performance Examples
--------------------

.. code-block:: python

   def example_batch_operations():
       """Example showing efficient batch operations"""
       tree = ProllyTree()

       # Generate test data
       import time

       # Single inserts (slower)
       start_time = time.time()
       for i in range(1000):
           key = f"single:{i:04d}".encode('utf-8')
           value = f"value_{i}".encode('utf-8')
           tree.insert(key, value)
       single_time = time.time() - start_time

       # Batch insert (faster)
       start_time = time.time()
       batch_data = []
       for i in range(1000):
           key = f"batch:{i:04d}".encode('utf-8')
           value = f"value_{i}".encode('utf-8')
           batch_data.append((key, value))

       tree.insert_batch(batch_data)
       batch_time = time.time() - start_time

       print(f"Single inserts: {single_time:.3f}s")
       print(f"Batch insert: {batch_time:.3f}s")
       print(f"Speedup: {single_time/batch_time:.1f}x")

       return tree

Branch Merging and Conflict Resolution
---------------------------------------

.. code-block:: python

   from prollytree import VersionedKvStore, ConflictResolution, MergeConflict
   import tempfile
   import os
   import subprocess

   def example_merge_operations():
       """Comprehensive example of branch merging with conflict resolution"""

       # Create temporary directory for the example
       with tempfile.TemporaryDirectory() as tmpdir:
           # Initialize git repository
           subprocess.run(['git', 'init'], cwd=tmpdir, check=True, capture_output=True)
           subprocess.run(['git', 'config', 'user.name', 'Example'], cwd=tmpdir, check=True, capture_output=True)
           subprocess.run(['git', 'config', 'user.email', 'example@test.com'], cwd=tmpdir, check=True, capture_output=True)

           # Create data subdirectory
           data_dir = os.path.join(tmpdir, 'data')
           os.makedirs(data_dir)

           store = VersionedKvStore(data_dir)

           print("=== Basic Merge Without Conflicts ===")

           # Initial data
           store.insert(b"users:alice", b"Alice Smith")
           store.insert(b"users:bob", b"Bob Jones")
           store.insert(b"config:theme", b"light")
           store.commit("Initial data")

           # Create feature branch
           store.create_branch("add-user-feature")

           # Changes on feature branch
           store.insert(b"users:charlie", b"Charlie Brown")
           store.update(b"config:theme", b"dark")
           store.commit("Add Charlie and dark theme")

           # Switch back to main and make different changes
           store.checkout("main")
           store.insert(b"users:diana", b"Diana Prince")
           store.commit("Add Diana")

           # Merge feature branch
           merge_commit = store.merge("add-user-feature", ConflictResolution.TakeSource)
           print(f"Merge successful: {merge_commit[:8]}")

           # Show final state
           print("Final users:")
           for key in [b"users:alice", b"users:bob", b"users:charlie", b"users:diana"]:
               value = store.get(key)
               if value:
                   print(f"  {key.decode()}: {value.decode()}")

           print(f"Theme: {store.get(b'config:theme').decode()}")

           print("\\n=== Conflict Detection ===")

           # Create another scenario with conflicts
           store.create_branch("conflicting-feature")
           store.update(b"config:theme", b"blue")
           store.commit("Change theme to blue")

           store.checkout("main")
           store.update(b"config:theme", b"red")
           store.commit("Change theme to red")

           # Check for conflicts without applying
           success, conflicts = store.try_merge("conflicting-feature")
           if not success:
               print(f"Detected {len(conflicts)} conflicts:")
               for conflict in conflicts:
                   print(f"  Key: {conflict.key.decode()}")
                   print(f"    Source: {conflict.source_value.decode()}")
                   print(f"    Destination: {conflict.destination_value.decode()}")

           print("\\n=== Conflict Resolution Strategies ===")

           # Demonstrate different resolution strategies
           strategies = [
               ("IgnoreAll", ConflictResolution.IgnoreAll),
               ("TakeSource", ConflictResolution.TakeSource),
               ("TakeDestination", ConflictResolution.TakeDestination)
           ]

           for name, strategy in strategies:
               # Create test branch for each strategy
               branch_name = f"test-{name.lower()}"
               store.checkout("main")
               store.create_branch(branch_name)

               store.update(b"config:theme", b"feature-theme")
               store.commit(f"Feature theme on {branch_name}")

               store.checkout("main")

               # Apply merge with strategy
               merge_commit = store.merge(branch_name, strategy)
               final_theme = store.get(b"config:theme").decode()
               print(f"{name:15} -> Theme: {final_theme}")

               # Reset main for next test
               store.checkout("main")

Running Examples
----------------

.. code-block:: python

   if __name__ == "__main__":
       # Run examples
       print("=== Basic Key-Value Store ===")
       example_basic_kv_store()

       print("\\n=== Data Types ===")
       example_data_types()

       print("\\n=== Document Versioning ===")
       example_document_versioning()

       print("\\n=== SQL Analytics ===")
       example_sql_analytics()

       print("\\n=== Branch Merging ===")
       example_merge_operations()

       print("\\n=== Performance ===")
       example_batch_operations()