Python client for Spore Drive
Project description
Spore Drive Python Client
A Python client library for the Spore Drive service, providing a pythonic interface to manage configuration, drives, and course operations.
Features
The client has been designed with modern Python best practices:
- Context Managers: Automatic resource cleanup with
async withstatements - Factory Methods: Easy object creation with descriptive class methods
- Dataclasses: Type-safe configuration with validation
- Async/Await: Full async support for all operations
- Type Hints: Comprehensive type annotations throughout
Structure
The client has been refactored into logical modules for better maintainability:
Core Modules
types.py- Dataclasses and type definitions (TauBinarySource,CourseConfig,ServiceConfig)clients.py- Low-level RPC client implementations (ConfigClient,DriveClient)operations.py- Configuration operation classes (BaseOperation,Cloud,Hosts,Auth,Shapes)config.py- Configuration management (Configclass)drive.py- Drive and course management (Drive,Courseclasses)utils.py- Utility functions for tau sources and service managementclient.py- Main client module with public API exports
Public API
The main entry point is through the spore_drive package:
from spore_drive import (
Config, Drive, Course,
tau_latest, tau_version, tau_url, tau_path,
start_spore_drive_service, stop_spore_drive_service
)
from spore_drive.types import CourseConfig, TauBinarySource
Usage
Context Managers (Recommended)
The most pythonic way to use the client is with context managers for automatic resource cleanup:
import asyncio
from spore_drive import Config, Drive, start_spore_drive_service, stop_spore_drive_service
from spore_drive.types import CourseConfig
async def main():
# Start service
port = start_spore_drive_service()
try:
# Using context managers - no manual cleanup needed!
async with Config.new() as config:
async with Drive.with_latest_tau(config) as drive:
# Create course configuration using dataclass
course_config = CourseConfig(
shapes=["web", "database", "function"],
concurrency=2,
timeout=300,
retries=3
)
# Plot course with context manager
async with await drive.plot(course_config) as course:
await course.displace()
# Monitor progress
async for progress in course.progress():
print(f"Progress: {progress.progress}%")
if progress.progress >= 100:
break
# All resources automatically cleaned up when context exits
finally:
stop_spore_drive_service()
asyncio.run(main())
Factory Methods
Factory methods provide easy object creation with descriptive names:
# Configuration factory methods
config = await Config.new() # New empty config
config = await Config.from_file("config.yaml") # From file
config = await Config.from_bytes(data) # From bytes
config = await Config.create(source="path") # Generic create
# Drive factory methods
drive = await Drive.with_latest_tau(config) # Latest version
drive = await Drive.with_version(config, "1.0.0") # Specific version
drive = await Drive.with_url(config, "https://...") # From URL
drive = await Drive.with_path(config, "/path/to/tau") # From local path
drive = await Drive.create(config, tau=source) # Generic create
Dataclass Configuration
Use dataclasses for type-safe configuration with validation:
from spore_drive.types import CourseConfig, TauBinarySource
# Course configuration with validation
course_config = CourseConfig(
shapes=["shape1", "shape2"],
concurrency=4, # Must be >= 1
timeout=600, # Optional timeout
retries=5 # Must be >= 0
)
# Tau binary sources
tau_latest = TauBinarySource.latest()
tau_version = TauBinarySource.version("1.0.0")
tau_url = TauBinarySource.url("https://example.com/tau.tar.gz")
tau_path = TauBinarySource.path("/local/path/to/tau.tar.gz")
# Validation errors
try:
invalid_config = CourseConfig(concurrency=0) # ValueError: must be >= 1
except ValueError as e:
print(f"Validation error: {e}")
Basic Configuration Management
import asyncio
from spore_drive import Config, start_spore_drive_service, stop_spore_drive_service
async def main():
# Start service
port = start_spore_drive_service()
# Create configuration using context manager
async with Config.new() as config:
# Access configuration sections
cloud = config.cloud
hosts = config.hosts
auth = config.auth
shapes = config.shapes
# Commit changes
await config.commit()
# Config automatically freed when context exits
stop_spore_drive_service()
asyncio.run(main())
Drive Operations
from spore_drive import Drive, tau_latest
async def drive_example():
async with Config.new() as config:
# Create drive with latest tau binary using context manager
async with Drive.with_latest_tau(config) as drive:
# Plot a course using dataclass
course_config = CourseConfig(
shapes=['shape1', 'shape2'],
concurrency=4,
timeout=300
)
async with await drive.plot(course_config) as course:
# Start displacement
await course.displace()
# Monitor progress
async for progress in course.progress():
print(f"Progress: {progress.progress}%")
# Course automatically aborted when context exits
Tau Binary Sources
The client supports multiple ways to specify tau binary sources:
# Using utility functions
drive = Drive(config, tau=tau_latest())
drive = Drive(config, tau=tau_version("1.0.0"))
drive = Drive(config, tau=tau_url("https://example.com/tau.tar.gz"))
drive = Drive(config, tau=tau_path("/path/to/tau.tar.gz"))
# Using dataclasses directly
drive = Drive(config, tau=TauBinarySource.latest())
drive = Drive(config, tau=TauBinarySource.version("1.0.0"))
drive = Drive(config, tau=TauBinarySource.url("https://example.com/tau.tar.gz"))
drive = Drive(config, tau=TauBinarySource.path("/path/to/tau.tar.gz"))
# Using factory methods
drive = await Drive.with_latest_tau(config)
drive = await Drive.with_version(config, "1.0.0")
drive = await Drive.with_url(config, "https://example.com/tau.tar.gz")
drive = await Drive.with_path(config, "/path/to/tau.tar.gz")
Service Management
The client includes utilities for managing the Spore Drive service:
from spore_drive import (
start_spore_drive_service,
stop_spore_drive_service,
get_spore_drive_service_port
)
# Start service and get port
port = start_spore_drive_service()
# Check if service is running
existing_port = get_spore_drive_service_port()
# Stop service
stop_spore_drive_service()
Testing
Integration Tests
The Python client includes comprehensive integration tests that use the same mock server technique as the TypeScript tests. These tests verify the complete functionality of the Config class and related operations.
Running Integration Tests
# Run all integration tests
python run_integration_tests.py
# Run pytest integration tests only
pytest test_config_pytest.py -v
# Run manual integration tests only
python test_config_integration.py
Test Files
test_config_integration.py: Manual integration tests with custom test runnertest_config_pytest.py: Pytest-compatible integration tests with fixturesrun_integration_tests.py: Test runner script that checks dependencies and runs all tests
Test Coverage
The integration tests cover:
- Cloud domain configuration (root, generated, validation keys)
- P2P swarm key generation and management
- Authentication signer management (add, list, delete)
- Host configuration and management
- Shape configuration and management
- Configuration bundle download and verification
- Configuration commit operations
- Comparison between different configuration creation methods
Mock Server
The tests use the same Go mock server (../mock/main.go) as the TypeScript tests, ensuring consistent behavior across language implementations.
Unit Tests
# Run unit tests
pytest tests/ -v
# Run specific test file
pytest tests/test_service_manager.py -v
Development
Module Responsibilities
types.py: Dataclasses and type definitions with validationclients.py: RPC communication layeroperations.py: Configuration operation interfacesconfig.py: High-level configuration management with factory methodsdrive.py: Drive and course operations with context managersutils.py: Helper functions and utilitiesclient.py: Public API exports
Adding New Features
- Add dataclasses to
types.pyif needed - Implement RPC calls in
clients.py - Create operation classes in
operations.pyfor configuration operations - Add high-level interfaces in
config.pyordrive.py - Export new functionality in
client.pyand__init__.py - Add corresponding integration tests
Test Requirements
To run the integration tests, you need:
- Go (for the mock server)
- Python packages:
pytest,pytest-asyncio,pyyaml
Install dependencies:
pip install pytest pytest-asyncio pyyaml
Examples
See the following example files for complete working examples:
example_pythonic.py: Demonstrates all new pythonic featuresexample_usage.py: Basic usage patternsexample.py: Original example with manual resource management
Migration Guide
From Legacy Usage
If you're upgrading from the previous version:
# Old way (still supported for backward compatibility)
config = Config()
await config.init()
drive = Drive(config, tau=True)
await drive.init()
await drive.free()
await config.free()
# New way (recommended)
async with Config.new() as config:
async with Drive.with_latest_tau(config) as drive:
# Use drive
pass # Resources automatically cleaned up
# Old way
course_config = {"shapes": ["web"], "concurrency": 2}
# New way
course_config = CourseConfig(shapes=["web"], concurrency=2)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spore_drive-0.1.1.tar.gz.
File metadata
- Download URL: spore_drive-0.1.1.tar.gz
- Upload date:
- Size: 48.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6ae5492875278a8fb0c61529c0839b79607dd49a0fd734c579e26df77870e27
|
|
| MD5 |
245bd87f36355fc9385183376a95206a
|
|
| BLAKE2b-256 |
9c71271604b873a7d89bbf99824791f8d724a7d96c162c7686431aaf6e282411
|
File details
Details for the file spore_drive-0.1.1-py3-none-any.whl.
File metadata
- Download URL: spore_drive-0.1.1-py3-none-any.whl
- Upload date:
- Size: 53.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb24a0249e1996d99a4419ca03503dcc6c165ae4e8522143b008969cb412a419
|
|
| MD5 |
2a6d04232ef4286adaa13d8d98209a26
|
|
| BLAKE2b-256 |
eb0ab1df127975230078794936d68eecb95fcfc2f2ca6266c0d435e606b76af9
|