Skip to main content

Blazingly fast spatial database library

Project description

Spatio: Python Bindings for High-Performance Spatial Database

PyPI version Python 3.8+ License: MIT

Python bindings for Spatio, a high-performance, embedded spatio-temporal database written in Rust. Spatio brings spatial operations and geographic data management to Python with minimal overhead.

Features

  • High Performance: Built on Rust for maximum speed and memory efficiency
  • Spatial Operations: Geographic point storage with automatic spatial indexing
  • Trajectory Tracking: Store and query movement data over time
  • TTL Support: Automatic data expiration with time-to-live
  • Thread-Safe: Concurrent access (atomic operations coming soon for Python)
  • Persistent Storage: Optional file-based persistence

Installation

From PyPI (Recommended)

pip install spatio

📦 PyPI Repository: https://pypi.org/project/spatio

From Source

# Clone the repository
git clone https://github.com/pkvartsianyi/spatio.git
cd spatio/py-spatio

# Build and install
pip install maturin
maturin develop

Quick Start

import spatio

# Create an in-memory database
db = spatio.Spatio.memory()

# Store simple key-value data
db.insert(b"user:123", b"John Doe")
user = db.get(b"user:123")
print(f"User: {user.decode()}")  # User: John Doe

# Store geographic points with automatic spatial indexing
nyc = spatio.Point(40.7128, -74.0060)
london = spatio.Point(51.5074, -0.1278)

db.insert_point("cities", nyc, b"New York City")
db.insert_point("cities", london, b"London")

# Find nearby points within 6000km
nearby = db.find_nearby("cities", nyc, 6000000.0, 10)
for point, city_name, distance in nearby:
    print(f"{city_name.decode()}: {distance/1000:.0f}km away")

Core Classes

Spatio

The main database class for all operations.

# Create databases
db = spatio.Spatio.memory()                    # In-memory
db = spatio.Spatio.open("data.db")             # Persistent
db = spatio.Spatio.memory_with_config(config)  # With custom config

# Basic operations
db.insert(key, value, options=None)
value = db.get(key)
old_value = db.delete(key)

# Spatial operations
db.insert_point(prefix, point, value, options=None)
nearby = db.find_nearby(prefix, center, radius_meters, limit)
count = db.count_within_distance(prefix, center, radius_meters)

# Trajectory operations
db.insert_trajectory(object_id, trajectory, options=None)
path = db.query_trajectory(object_id, start_time, end_time)

Point

Represents a geographic coordinate.

# Create points
point = spatio.Point(latitude, longitude)
print(f"Location: {point.lat}, {point.lon}")

# Calculate distance
distance = point1.distance_to(point2)  # Returns meters

SetOptions

Configure data storage options.

# TTL (time-to-live)
opts = spatio.SetOptions.with_ttl(300.0)  # 5 minutes
db.insert(b"session", b"data", opts)

# Absolute expiration
import time
future = time.time() + 300
opts = spatio.SetOptions.with_expiration(future)

Config

Database configuration.

# Custom geohash precision (1-12, default: 8)
config = spatio.Config.with_geohash_precision(10)  # ~61cm accuracy
db = spatio.Spatio.memory_with_config(config)

# Manual configuration
config = spatio.Config()
config.geohash_precision = 6  # ~610m accuracy

Usage Examples

Basic Spatial Queries

import spatio

db = spatio.Spatio.memory()

# Insert city data
cities = [
    (spatio.Point(40.7128, -74.0060), b"New York"),
    (spatio.Point(51.5074, -0.1278), b"London"),
    (spatio.Point(35.6762, 139.6503), b"Tokyo"),
    (spatio.Point(48.8566, 2.3522), b"Paris"),
]

for point, name in cities:
    db.insert_point("cities", point, name)

# Find cities within 6000km of New York
nyc = spatio.Point(40.7128, -74.0060)
nearby = db.find_nearby("cities", nyc, 6000000.0, 10)

print(f"Cities within 6000km of NYC:")
for point, name, distance in nearby:
    print(f"  {name.decode()}: {distance/1000:.0f}km")

Trajectory Tracking

import spatio
import time

db = spatio.Spatio.memory()

# Create a trajectory (list of (Point, timestamp) tuples)
trajectory = [
    (spatio.Point(40.7128, -74.0060), 1640995200),  # NYC
    (spatio.Point(40.7580, -73.9855), 1640995800),  # Central Park
    (spatio.Point(40.6892, -74.0445), 1640996400),  # Brooklyn
]

# Store trajectory
db.insert_trajectory("vehicle:truck001", trajectory)

# Query trajectory for specific time range
path = db.query_trajectory("vehicle:truck001", 1640995200, 1640996400)

print(f"Vehicle path ({len(path)} points):")
for point, timestamp in path:
    print(f"  {timestamp}: ({point.lat:.4f}, {point.lon:.4f})")

TTL and Expiration

import spatio
import time

db = spatio.Spatio.memory()

# Data that expires in 5 seconds
opts = spatio.SetOptions.with_ttl(5.0)
db.insert(b"session:temp", b"temporary_data", opts)

print("Immediate:", db.get(b"session:temp"))  # b'temporary_data'
time.sleep(6)
print("After TTL:", db.get(b"session:temp"))  # None

Sequential Operations

import spatio

db = spatio.Spatio.memory()

# Sequential operations (atomic operations coming in future version)
db.insert(b"user:1", b"Alice")
db.insert(b"user:2", b"Bob")

point = spatio.Point(40.7128, -74.0060)
db.insert_point("locations", point, b"NYC Office")

print("Operations completed")

# Verify all operations were applied
print(db.get(b"user:1"))  # b'Alice'
nearby = db.find_nearby("locations", spatio.Point(40.7128, -74.0060), 1000, 10)
print(len(nearby))  # 1

Bounding Box Queries

import spatio

db = spatio.Spatio.memory()

# Insert points across different regions
points = [
    (spatio.Point(40.7128, -74.0060), b"NYC"),      # North America
    (spatio.Point(51.5074, -0.1278), b"London"),    # Europe
    (spatio.Point(35.6762, 139.6503), b"Tokyo"),    # Asia
]

for point, name in points:
    db.insert_point("cities", point, name)

# Find cities in Europe (rough bounding box)
european_cities = db.find_within_bounds(
    "cities",
    40.0, -10.0,  # min_lat, min_lon
    60.0, 10.0,   # max_lat, max_lon
    10            # limit
)

print("European cities:")
for point, name in european_cities:
    print(f"  {name.decode()} at ({point.lat:.2f}, {point.lon:.2f})")

Performance

Spatio-Py is built for high performance:

  • Fast spatial indexing using geohash and R-tree algorithms
  • Memory efficient storage with zero-copy operations where possible
  • Concurrent access with minimal locking overhead
  • Optimized distance calculations using efficient approximation algorithms

Benchmarks

Basic performance characteristics (your results may vary):

  • Key-value operations: ~1.6M ops/sec (600ns per operation)
  • Spatial insertions: ~1.9M points/sec (530ns per operation)
  • Spatial queries: ~225K queries/sec (4.4μs per operation)
  • Memory usage: Efficient in-memory storage with spatial indexing

Development

Development Tools

This project uses just as the primary task runner for all development workflows. Just provides a more powerful and expressive alternative to Make.

# Install just (if not already installed)
cargo install just

# See all available commands
just --list

# Common development tasks
just setup          # Set up development environment
just build           # Build the package
just test            # Run tests
just check           # Run all quality checks (lint, format, typecheck)
just ci              # Run full CI pipeline locally

Building from Source

# Prerequisites
pip install maturin pytest

# Clone and build
git clone https://github.com/pkvartsianyi/spatio.git
cd spatio/py-spatio

# Development build
maturin develop

# Run tests
just test

# Run examples
python examples/basic_usage.py

Building Multi-Platform Wheels

The project uses cibuildwheel to build wheels for all major platforms and Python versions (3.9-3.13):

Supported Platforms:

  • Linux: x86_64, aarch64 (manylinux)
  • macOS: x86_64 (Intel), arm64 (Apple Silicon)
  • Windows: AMD64

Automated Builds:

  • Wheels are automatically built on every release via GitHub Actions
  • All wheels are tested before publishing to PyPI
  • The workflow generates 40+ wheel files covering all platform/Python combinations

Manual Build:

# Install cibuildwheel
pip install cibuildwheel

# Build wheels for your platform
cibuildwheel --platform linux  # or macos, windows

# Build for specific Python versions
CIBW_BUILD="cp311-* cp312-*" cibuildwheel

# Output wheels will be in ./wheelhouse/

For more details, see .github/workflows/wheels.yml

Testing

# Run all tests
just test

# Run with coverage
just coverage

# Run performance tests
just bench

Code Formatting

# Format Python code
just fmt

# Type checking
just typecheck

# Run all checks
just check

API Reference

Database Operations

Method Description
Spatio.memory() Create in-memory database
Spatio.open(path) Open/create persistent database
insert(key, value, options=None) Store key-value pair
get(key) Retrieve value by key
delete(key) Remove key and return old value
(atomic operations coming soon) Execute operations atomically
sync() Force sync to disk
stats() Get database statistics

Spatial Operations

Method Description
insert_point(prefix, point, value, options=None) Store geographic point
find_nearby(prefix, center, radius_meters, limit) Find points within radius
contains_point(prefix, center, radius_meters) Check if any points exist in radius
count_within_distance(prefix, center, radius_meters) Count points within radius
intersects_bounds(prefix, min_lat, min_lon, max_lat, max_lon) Check if any points in bounding box
find_within_bounds(prefix, min_lat, min_lon, max_lat, max_lon, limit) Find points in bounding box

Trajectory Operations

Method Description
insert_trajectory(object_id, trajectory, options=None) Store trajectory data
query_trajectory(object_id, start_time, end_time) Query trajectory for time range

Error Handling

Spatio-Py uses standard Python exceptions:

import spatio

try:
    # Invalid coordinates
    point = spatio.Point(91.0, 0.0)  # Raises ValueError
except ValueError as e:
    print(f"Invalid point: {e}")

try:
    db = spatio.Spatio.open("/invalid/path/db.spatio")
except RuntimeError as e:
    print(f"Database error: {e}")

Project Status

Spatio-Python is in alpha development:

  • Core spatial operations implemented
  • Complete Python API via PyO3 bindings
  • TTL and persistence support
  • Multi-platform wheels (Linux, macOS, Windows)
  • Python 3.8-3.13 support

Current version: 0.1.0-alpha.10

Platform Support

Pre-built wheels are available for:

  • Linux: x86_64, aarch64 (manylinux)
  • macOS: x86_64 (Intel), arm64 (Apple Silicon)
  • Windows: AMD64
  • Python: 3.9, 3.10, 3.11, 3.12, 3.13

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

spatio-0.1.1a11-cp311-cp311-win_amd64.whl (214.8 kB view details)

Uploaded CPython 3.11Windows x86-64

spatio-0.1.1a11-cp311-cp311-manylinux_2_34_x86_64.whl (311.9 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.34+ x86-64

spatio-0.1.1a11-cp311-cp311-macosx_11_0_arm64.whl (268.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

spatio-0.1.1a11-cp311-cp311-macosx_10_12_x86_64.whl (296.4 kB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

File details

Details for the file spatio-0.1.1a11-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: spatio-0.1.1a11-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 214.8 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for spatio-0.1.1a11-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 f08eeddd6e4a48e5acaa088a3f67b354499988d57773fba12272d9143ef58bb0
MD5 77d0071851bf241c6cc41bc64eb28c57
BLAKE2b-256 827c1a8b0d5170603c9082c3c03f1c7b67d239649e74444f0ea34b1ac3b4d4cc

See more details on using hashes here.

File details

Details for the file spatio-0.1.1a11-cp311-cp311-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for spatio-0.1.1a11-cp311-cp311-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 6e8ead373c5fedfa74cc639c6f49906f48f545e1f27d79b1db3ac7fe57be99e3
MD5 68abc1ada2da5f2d09c82e35201c3b48
BLAKE2b-256 dfd8606ffb15ebaf450fdc7c81270c72b4e99aa89228f1d63d9b01c97f144f67

See more details on using hashes here.

File details

Details for the file spatio-0.1.1a11-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spatio-0.1.1a11-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dec31765e7c97b43aa14a521d5854b6d73d811f71451c75f9268bd472b7c336a
MD5 2ebcc20abdab678c01d80be73dab36e6
BLAKE2b-256 eca5b288fe5657c18d0b4c9b2a8a3e8a48017e570e260b94742adc9dcc0edfd8

See more details on using hashes here.

File details

Details for the file spatio-0.1.1a11-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for spatio-0.1.1a11-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 866ed0864760bf5dda17909b4a989075254acaad259ad29170940cbe99de08f6
MD5 af497fd3c475e45f5867dd79faa58c9a
BLAKE2b-256 a113505a245f7b4460000ac6553cae876f3026a9b01aafbebb6a45c6783f5d5a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page