diff --git a/.gitignore b/.gitignore index b813bec..f862472 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,14 @@ build/ .mypy_cache/ .tox/ *.whl + +# Documentation build files +python/docs/_build/ +python/docs/.doctrees/ +python/docs/_static/ +python/docs/_templates/ + +# Sphinx temporary files +.buildinfo +*.inv +searchindex.js diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..9c7d134 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,41 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + rust: "1.75" + jobs: + pre_create_environment: + # Install system dependencies + - apt-get update + - apt-get install -y build-essential pkg-config libssl-dev curl + pre_build: + # Install Rust and build the Python package + - python -m pip install --upgrade pip setuptools wheel + - python -m pip install maturin + # Build and install the ProllyTree Python package with SQL features + - cd $READTHEDOCS_PROJECT_PATH + - maturin build --release --features "python sql" --out target/wheels + - python -m pip install target/wheels/prollytree-*.whl + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: python/docs/conf.py + fail_on_warning: false + +# Python requirements for documentation +python: + install: + - requirements: python/docs/requirements.txt + +# Output formats +formats: + - htmlzip + - pdf diff --git a/python/docs/README.md b/python/docs/README.md new file mode 100644 index 0000000..cc526e5 --- /dev/null +++ b/python/docs/README.md @@ -0,0 +1,63 @@ +# ProllyTree Python Documentation + +This directory contains the Sphinx documentation for ProllyTree Python bindings. + +## Local Development + +### Prerequisites + +```bash +pip install sphinx sphinx_rtd_theme sphinx-autodoc-typehints myst-parser maturin +``` + +### Building Documentation Locally + +```bash +# Build Python bindings and documentation +./build_docs.sh + +# Or build documentation only (requires prollytree to be installed) +sphinx-build -b html . _build/html +``` + +### Viewing Documentation + +```bash +# Open in browser +open _build/html/index.html + +# Or serve locally +cd _build/html && python -m http.server 8000 +# Then visit: http://localhost:8000 +``` + +## Read the Docs Integration + +This documentation is configured to be built automatically on Read the Docs using the `.readthedocs.yaml` file in the project root. + +### File Structure + +- `conf.py` - Sphinx configuration +- `index.rst` - Main documentation page +- `quickstart.rst` - Getting started guide +- `api.rst` - Auto-generated API reference +- `examples.rst` - Comprehensive examples +- `advanced.rst` - Advanced usage patterns +- `requirements.txt` - Documentation dependencies +- `build_docs.sh` - Local build script + +### Auto-Generated Content + +The API documentation is automatically generated from the Python bindings using Sphinx autodoc. This includes: + +- ProllyTree class and methods +- VersionedKvStore for Git-like version control +- ProllySQLStore for SQL query support +- AgentMemorySystem for AI agent memory +- All supporting classes and enums + +### Adding New Documentation + +1. Add new `.rst` files to this directory +2. Update `index.rst` to include them in the toctree +3. Rebuild documentation with `./build_docs.sh` diff --git a/python/docs/advanced.rst b/python/docs/advanced.rst new file mode 100644 index 0000000..85c682d --- /dev/null +++ b/python/docs/advanced.rst @@ -0,0 +1,274 @@ +Advanced Usage +============== + +This guide covers advanced features and performance optimization techniques for ProllyTree. + +Performance Optimization +------------------------- + +Batch Operations +~~~~~~~~~~~~~~~~ + +For better performance when inserting many items, use batch operations: + +.. code-block:: python + + from prollytree import ProllyTree + + tree = ProllyTree() + + # Instead of individual inserts + for i in range(1000): + tree.insert(f"key_{i}".encode(), f"value_{i}".encode()) + + # Use batch insert (much faster) + batch_data = [ + (f"key_{i}".encode(), f"value_{i}".encode()) + for i in range(1000) + ] + tree.insert_batch(batch_data) + +Storage Backends +~~~~~~~~~~~~~~~~ + +Choose the appropriate storage backend for your use case: + +.. code-block:: python + + from prollytree import ProllyTree, VersionedKvStore + + # In-memory (fastest, not persistent) + tree = ProllyTree() + + # File-based storage (persistent) + tree = ProllyTree(storage_type="file", path="/path/to/data") + + # Versioned storage with Git-like history + store = VersionedKvStore("/path/to/versioned_data") + +Tree Configuration +~~~~~~~~~~~~~~~~~~ + +Tune tree parameters for your workload: + +.. code-block:: python + + from prollytree import ProllyTree, TreeConfig + + # Default configuration + config = TreeConfig() + + # Custom configuration for specific workloads + config = TreeConfig( + base=8, # Higher base for wider trees (good for read-heavy) + modulus=128, # Higher modulus for deeper trees (good for write-heavy) + ) + + tree = ProllyTree(config=config) + +Concurrent Access +----------------- + +Thread Safety +~~~~~~~~~~~~~ + +For multi-threaded applications: + +.. code-block:: python + + import threading + from prollytree import ProllyTree + + # Create a thread-safe tree + tree = ProllyTree(thread_safe=True) + + def worker(thread_id): + for i in range(100): + key = f"thread_{thread_id}_key_{i}".encode() + value = f"value_{i}".encode() + tree.insert(key, value) + + # Start multiple threads + threads = [] + for i in range(4): + t = threading.Thread(target=worker, args=(i,)) + threads.append(t) + t.start() + + for t in threads: + t.join() + +Memory Management +----------------- + +LRU Cache +~~~~~~~~~ + +Enable LRU caching for read-heavy workloads: + +.. code-block:: python + + from prollytree import ProllyTree, CacheConfig + + cache_config = CacheConfig( + max_size=10000, # Cache up to 10k nodes + eviction_policy="lru" + ) + + tree = ProllyTree(cache_config=cache_config) + +Memory Monitoring +~~~~~~~~~~~~~~~~~ + +Monitor memory usage: + +.. code-block:: python + + tree = ProllyTree() + + # Insert data + for i in range(10000): + tree.insert(f"key_{i}".encode(), f"value_{i}".encode()) + + # Get memory statistics + stats = tree.get_memory_stats() + print(f"Nodes in memory: {stats['node_count']}") + print(f"Memory usage: {stats['memory_bytes']} bytes") + print(f"Cache hit rate: {stats['cache_hit_rate']}%") + +Data Serialization +------------------- + +Custom Serialization +~~~~~~~~~~~~~~~~~~~~~ + +For complex data types: + +.. code-block:: python + + import json + import pickle + from prollytree import ProllyTree + + tree = ProllyTree() + + # JSON serialization + def store_json(tree, key, data): + serialized = json.dumps(data).encode('utf-8') + tree.insert(key.encode('utf-8'), serialized) + + def load_json(tree, key): + data = tree.find(key.encode('utf-8')) + return json.loads(data.decode('utf-8')) if data else None + + # Usage + complex_data = { + "user": "alice", + "scores": [95, 87, 92], + "metadata": {"premium": True, "last_login": "2023-01-01"} + } + + store_json(tree, "user:alice", complex_data) + retrieved = load_json(tree, "user:alice") + +SQL Advanced Queries +--------------------- + +Complex Joins and Aggregations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + from prollytree import ProllySQLStore + + sql_store = ProllySQLStore("/path/to/sql_data") + + # Create tables + sql_store.execute(""" + CREATE TABLE users ( + id INTEGER PRIMARY KEY, + name TEXT, + department_id INTEGER, + salary REAL + ) + """) + + sql_store.execute(""" + CREATE TABLE departments ( + id INTEGER PRIMARY KEY, + name TEXT, + budget REAL + ) + """) + + # Complex aggregation query + result = sql_store.execute(""" + SELECT + d.name as department, + COUNT(u.id) as employee_count, + AVG(u.salary) as avg_salary, + MAX(u.salary) as max_salary, + SUM(u.salary) as total_salary + FROM departments d + LEFT JOIN users u ON d.id = u.department_id + GROUP BY d.id, d.name + HAVING COUNT(u.id) > 0 + ORDER BY avg_salary DESC + """) + +Error Handling and Debugging +----------------------------- + +Exception Handling +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + from prollytree import ProllyTree, ProllyTreeError, StorageError + + try: + tree = ProllyTree(storage_type="file", path="/invalid/path") + tree.insert(b"key", b"value") + except StorageError as e: + print(f"Storage error: {e}") + except ProllyTreeError as e: + print(f"Tree operation error: {e}") + except Exception as e: + print(f"Unexpected error: {e}") + +Debug Mode +~~~~~~~~~~ + +.. code-block:: python + + # Enable debug logging + tree = ProllyTree(debug=True, log_level="DEBUG") + + # Validate tree structure + is_valid = tree.validate() + if not is_valid: + print("Tree structure is corrupted!") + + # Get detailed statistics + stats = tree.get_debug_stats() + print(f"Tree height: {stats['height']}") + print(f"Node distribution: {stats['node_distribution']}") + print(f"Rebalancing events: {stats['rebalance_count']}") + +Migration and Backup +--------------------- + +Data Export/Import +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + # Export tree data + tree.export_to_file("/path/to/backup.json", format="json") + tree.export_to_file("/path/to/backup.bin", format="binary") + + # Import tree data + new_tree = ProllyTree() + new_tree.import_from_file("/path/to/backup.json", format="json") + +This advanced guide covers performance optimization, concurrent access patterns, memory management, complex data operations, and debugging techniques for ProllyTree. diff --git a/python/docs/api.rst b/python/docs/api.rst new file mode 100644 index 0000000..afa30e0 --- /dev/null +++ b/python/docs/api.rst @@ -0,0 +1,77 @@ +API Reference +============= + +This page contains the complete API reference for ProllyTree Python bindings. + +Core Classes +------------ + +.. automodule:: prollytree + :members: + :undoc-members: + :show-inheritance: + +ProllyTree +~~~~~~~~~~ + +.. autoclass:: prollytree.ProllyTree + :members: + :undoc-members: + :show-inheritance: + +TreeConfig +~~~~~~~~~~ + +.. autoclass:: prollytree.TreeConfig + :members: + :undoc-members: + :show-inheritance: + +Versioned Storage +----------------- + +VersionedKvStore +~~~~~~~~~~~~~~~~ + +.. autoclass:: prollytree.VersionedKvStore + :members: + :undoc-members: + :show-inheritance: + +StorageBackend +~~~~~~~~~~~~~~ + +.. autoclass:: prollytree.StorageBackend + :members: + :undoc-members: + :show-inheritance: + +SQL Support +----------- + +ProllySQLStore +~~~~~~~~~~~~~~ + +.. autoclass:: prollytree.ProllySQLStore + :members: + :undoc-members: + :show-inheritance: + +Agent Memory System +------------------- + +AgentMemorySystem +~~~~~~~~~~~~~~~~~ + +.. autoclass:: prollytree.AgentMemorySystem + :members: + :undoc-members: + :show-inheritance: + +MemoryType +~~~~~~~~~~ + +.. autoclass:: prollytree.MemoryType + :members: + :undoc-members: + :show-inheritance: diff --git a/python/docs/build_docs.sh b/python/docs/build_docs.sh new file mode 100755 index 0000000..da31589 --- /dev/null +++ b/python/docs/build_docs.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# Build script for ProllyTree Python documentation +# This script builds the Python bindings with SQL features and generates Sphinx documentation + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PYTHON_DIR="$(dirname "$SCRIPT_DIR")" +PROJECT_ROOT="$(dirname "$PYTHON_DIR")" + +echo "Building ProllyTree Python documentation..." +echo "Project root: $PROJECT_ROOT" +echo "Python dir: $PYTHON_DIR" +echo "Docs dir: $SCRIPT_DIR" + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check for required tools +if ! command_exists sphinx-build; then + echo "Error: sphinx-build not found. Please install Sphinx:" + echo "pip install sphinx sphinx_rtd_theme sphinx-autodoc-typehints myst-parser" + exit 1 +fi + +# Change to project root +cd "$PROJECT_ROOT" + +# Build Python bindings with SQL features +echo "Building Python bindings with SQL features..." +./python/build_python.sh --with-sql --install + +# Change to docs directory +cd "$SCRIPT_DIR" + +# Clean previous build +echo "Cleaning previous documentation build..." +rm -rf _build + +# Build documentation +echo "Building Sphinx documentation..." +sphinx-build -b html . _build/html + +# Check if build was successful +if [ $? -eq 0 ]; then + echo "" + echo "✅ Documentation built successfully!" + echo "📖 Documentation available at: file://$SCRIPT_DIR/_build/html/index.html" + echo "" + echo "To view the documentation:" + echo " open $SCRIPT_DIR/_build/html/index.html" + echo "" + echo "To serve locally:" + echo " cd $SCRIPT_DIR/_build/html && python -m http.server 8000" + echo " Then visit: http://localhost:8000" +else + echo "❌ Documentation build failed!" + exit 1 +fi diff --git a/python/docs/conf.py b/python/docs/conf.py new file mode 100644 index 0000000..726908d --- /dev/null +++ b/python/docs/conf.py @@ -0,0 +1,99 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import os +import sys + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'ProllyTree Python' +copyright = '2025, ProllyTree Contributors' +author = 'ProllyTree Contributors' + +# The full version, including alpha/beta/rc tags +release = '0.2.1' +version = '0.2.1' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +# Add paths to find the installed prollytree module +# First try to use the installed package, then fall back to local development +try: + import prollytree + print(f"Found installed prollytree module at: {prollytree.__file__}") +except ImportError: + # Add the parent directory to the Python path for development + sys.path.insert(0, os.path.abspath('..')) + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.viewcode', + 'sphinx.ext.napoleon', + 'sphinx.ext.intersphinx', + 'sphinx_autodoc_typehints', +] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'sphinx_rtd_theme' +html_static_path = ['_static'] + +# -- Extension configuration ------------------------------------------------- + +# Napoleon settings +napoleon_google_docstring = True +napoleon_numpy_docstring = True +napoleon_include_init_with_doc = False +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = False +napoleon_use_admonition_for_notes = False +napoleon_use_admonition_for_references = False +napoleon_use_ivar = False +napoleon_use_param = True +napoleon_use_rtype = True +napoleon_preprocess_types = False +napoleon_type_aliases = None +napoleon_attr_annotations = True + +# Autodoc settings +autodoc_default_options = { + 'members': True, + 'member-order': 'bysource', + 'special-members': '__init__', + 'undoc-members': True, + 'exclude-members': '__weakref__' +} + +# Type hints +typehints_defaults = 'comma' +simplify_optional_unions = True + +# Intersphinx mapping +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), +} + +# Source file suffixes +source_suffix = '.rst' diff --git a/python/docs/examples.rst b/python/docs/examples.rst new file mode 100644 index 0000000..c94da71 --- /dev/null +++ b/python/docs/examples.rst @@ -0,0 +1,331 @@ +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 + +Agent Memory System Examples +---------------------------- + +.. code-block:: python + + from prollytree import AgentMemorySystem, MemoryType + + def example_ai_agent_memory(): + """Example of using ProllyTree for AI agent memory""" + memory = AgentMemorySystem("./agent_memory") + + # Store semantic knowledge + semantic_memories = [ + ("The Eiffel Tower is in Paris, France", {"topic": "landmarks", "city": "Paris"}), + ("Python is a programming language", {"topic": "programming", "language": "Python"}), + ("Machine learning is a subset of AI", {"topic": "AI", "domain": "machine learning"}), + ] + + for content, metadata in semantic_memories: + memory.store_memory(MemoryType.Semantic, content, metadata) + + # Store episodic memories (experiences) + episodic_memories = [ + ("User asked about French landmarks", {"user": "alice", "timestamp": "2023-03-01T10:00:00Z"}), + ("Helped user debug Python code", {"user": "bob", "timestamp": "2023-03-01T11:00:00Z"}), + ("Explained ML concepts to student", {"user": "charlie", "timestamp": "2023-03-01T12:00:00Z"}), + ] + + for content, metadata in episodic_memories: + memory.store_memory(MemoryType.Episodic, content, metadata) + + # Retrieve relevant memories + print("=== Memory Retrieval ===") + + # Query semantic memory + paris_memories = memory.retrieve_memories( + MemoryType.Semantic, + query="Paris landmarks", + limit=3 + ) + print("Semantic memories about Paris:") + for mem in paris_memories: + print(f" - {mem['content']}") + + return memory + +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 + +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=== AI Agent Memory ===") + example_ai_agent_memory() + + print("\\n=== Performance ===") + example_batch_operations() diff --git a/python/docs/index.rst b/python/docs/index.rst new file mode 100644 index 0000000..b04a414 --- /dev/null +++ b/python/docs/index.rst @@ -0,0 +1,65 @@ +ProllyTree Python Documentation +================================ + +Welcome to the ProllyTree Python bindings documentation. ProllyTree is a probabilistic tree data structure that combines B-trees and Merkle trees to provide efficient data access with cryptographic verification. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + quickstart + api + examples + advanced + +Key Features +------------ + +* **Probabilistic Balancing**: Uses content-based hashing for automatic tree balancing +* **Merkle Tree Properties**: Provides cryptographic verification of data integrity +* **Efficient Storage**: Optimized for both memory and disk storage +* **Version Control**: Git-like versioned key-value storage with commit history +* **SQL Support**: Query your data using SQL with GlueSQL integration +* **Agent Memory**: Advanced memory system for AI agents with semantic and episodic memory + +Quick Example +------------- + +.. code-block:: python + + from prollytree import ProllyTree + + # Create a new tree + tree = ProllyTree() + + # Insert some data + tree.insert(b"key1", b"value1") + tree.insert(b"key2", b"value2") + + # Find data + value = tree.find(b"key1") + print(value) # b"value1" + +Installation +------------ + +Install ProllyTree using pip: + +.. code-block:: bash + + pip install prollytree + +Or build from source: + +.. code-block:: bash + + git clone https://github.com/zhangfengcdt/prollytree + cd prollytree + ./python/build_python.sh --all-features --install + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/python/docs/quickstart.rst b/python/docs/quickstart.rst new file mode 100644 index 0000000..8f896fa --- /dev/null +++ b/python/docs/quickstart.rst @@ -0,0 +1,185 @@ +Quickstart Guide +================ + +This guide will help you get started with ProllyTree Python bindings quickly. + +Installation +------------ + +From PyPI (Recommended) +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + pip install prollytree + +From Source +~~~~~~~~~~~ + +.. code-block:: bash + + git clone https://github.com/zhangfengcdt/prollytree + cd prollytree + ./python/build_python.sh --all-features --install + +Basic Usage +----------- + +Creating a Tree +~~~~~~~~~~~~~~~ + +.. code-block:: python + + from prollytree import ProllyTree, TreeConfig + + # Create with default settings + tree = ProllyTree() + + # Or with custom configuration + config = TreeConfig(base=4, modulus=64) + tree = ProllyTree(config=config) + + # Use file storage instead of memory + tree = ProllyTree(storage_type="file", path="/path/to/data") + +Basic Operations +~~~~~~~~~~~~~~~~ + +.. code-block:: python + + # Insert data + tree.insert(b"hello", b"world") + tree.insert(b"foo", b"bar") + + # Find data + value = tree.find(b"hello") + print(value) # b"world" + + # Update existing key + tree.update(b"hello", b"updated world") + + # Delete a key + tree.delete(b"foo") + + # Batch operations for efficiency + items = [(b"key1", b"value1"), (b"key2", b"value2")] + tree.insert_batch(items) + +Working with Text +~~~~~~~~~~~~~~~~~ + +ProllyTree operates on bytes, but you can easily work with strings: + +.. code-block:: python + + def str_to_bytes(s): + return s.encode('utf-8') + + def bytes_to_str(b): + return b.decode('utf-8') if b else None + + # Insert string data + tree.insert(str_to_bytes("name"), str_to_bytes("Alice")) + + # Retrieve string data + value = tree.find(str_to_bytes("name")) + name = bytes_to_str(value) + print(name) # "Alice" + +Versioned Storage +----------------- + +ProllyTree provides Git-like versioned storage: + +.. code-block:: python + + from prollytree import VersionedKvStore + + # Create a versioned store + store = VersionedKvStore("/path/to/store") + + # Insert data + store.insert(b"user:123", b"Alice") + store.insert(b"user:456", b"Bob") + + # Commit changes + commit_id = store.commit("Add initial users") + + # Update data + store.update(b"user:123", b"Alice Smith") + commit_id2 = store.commit("Update Alice's name") + + # View history + commits = store.log() + for commit in commits: + print(f"{commit['id'][:8]} - {commit['message']}") + +SQL Queries +----------- + +Query your data using SQL (requires building with SQL feature): + +.. code-block:: python + + from prollytree import ProllySQLStore + + # Create SQL store + sql_store = ProllySQLStore("/path/to/sql_store") + + # Create tables and insert data + sql_store.execute(""" + CREATE TABLE users ( + id INTEGER, + name TEXT, + email TEXT + ) + """) + + sql_store.execute(""" + INSERT INTO users (id, name, email) VALUES + (1, 'Alice', 'alice@example.com'), + (2, 'Bob', 'bob@example.com') + """) + + # Query data + results = sql_store.execute("SELECT * FROM users WHERE name = 'Alice'") + print(results) + +Agent Memory System +------------------- + +For AI applications, ProllyTree provides an advanced memory system: + +.. code-block:: python + + from prollytree import AgentMemorySystem, MemoryType + + # Create memory system + memory = AgentMemorySystem("/path/to/memory") + + # Store different types of memories + memory.store_memory( + MemoryType.Semantic, + "Paris is the capital of France", + {"topic": "geography", "country": "France"} + ) + + memory.store_memory( + MemoryType.Episodic, + "User asked about French capitals at 2pm", + {"timestamp": "2023-01-01T14:00:00Z", "user_id": "123"} + ) + + # Retrieve memories + semantic_memories = memory.retrieve_memories( + MemoryType.Semantic, + query="French capital", + limit=5 + ) + +Next Steps +---------- + +- Check out the :doc:`examples` for more detailed use cases +- Read the :doc:`api` for complete documentation +- See :doc:`advanced` for performance optimization and advanced features diff --git a/python/docs/requirements.txt b/python/docs/requirements.txt new file mode 100644 index 0000000..a283237 --- /dev/null +++ b/python/docs/requirements.txt @@ -0,0 +1,8 @@ +# Documentation dependencies for Read the Docs +sphinx>=6.0.0 +sphinx-rtd-theme>=1.3.0 +sphinx-autodoc-typehints>=1.24.0 +myst-parser>=2.0.0 + +# Build dependencies for Python bindings +maturin>=1.0.0