Skip to main content

High-performance adaptive radix tree (ART) for Python with prefix queries and fuzzy search

Project description

blart-py

A high-performance Python wrapper for the blart Rust library, providing a fast and memory-efficient adaptive radix tree (ART) implementation.

Features

  • Dictionary-like Interface: Familiar Python dict operations ([], get, in, etc.)
  • Ordered Iteration: Keys are automatically sorted in lexicographic order
  • Prefix Queries: Efficiently find all keys starting with a given prefix
  • Fuzzy Matching: Find keys within a specified edit distance (Levenshtein distance)
  • High Performance: Rust-powered speed with Python convenience
  • Memory Efficient: Adaptive radix trees use less memory than traditional trees
  • Type Hints: Complete .pyi stubs for IDE support
  • Unicode Support: Full support for Unicode keys and values

Installation

pip install blart-py

Build from Source

Requirements:

  • Python 3.8+
  • Rust toolchain
  • maturin
# Clone the repository
git clone https://github.com/axelv/blart-py.git
cd blart-py

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install maturin
pip install maturin

# Build and install
maturin develop --release

Quick Start

from blart import TreeMap

# Create a TreeMap
tree = TreeMap()
tree["hello"] = "world"
tree["python"] = "awesome"

# Access values
print(tree["hello"])  # Output: world
print(tree.get("missing", "default"))  # Output: default

# Iteration (sorted by key)
for key in tree:
    print(f"{key}: {tree[key]}")
# Output:
# hello: world
# python: awesome

# Prefix queries
tree["apple"] = 1
tree["application"] = 2
tree["apply"] = 3

for key, value in tree.prefix_iter("app"):
    print(f"{key}: {value}")
# Output:
# apple: 1
# application: 2
# apply: 3

# Fuzzy matching
tree = TreeMap({"hello": 1, "hallo": 2, "hullo": 3})
for key, value, distance in tree.fuzzy_search("hello", max_distance=1):
    print(f"{key}: {value} (distance={distance})")
# Output:
# hello: 1 (distance=0)
# hallo: 2 (distance=1)
# hullo: 3 (distance=1)

API Reference

Constructor

TreeMap()                          # Empty tree
TreeMap({"key": "value"})          # From dict
TreeMap([("key", "value")])        # From list of tuples

Basic Operations

tree[key] = value                  # Insert or update
value = tree[key]                  # Get value (raises KeyError if missing)
value = tree.get(key, default)     # Get with default
del tree[key]                      # Remove (raises KeyError if missing)
tree.remove(key)                   # Remove and return value
tree.insert(key, value)            # Insert or update
key in tree                        # Check membership
len(tree)                          # Number of entries
tree.clear()                       # Remove all entries
tree.is_empty()                    # Check if empty

Iteration

for key in tree:                   # Iterate over keys
    ...

for key in tree.keys():            # Explicit key iteration
    ...

for value in tree.values():        # Iterate over values
    ...

for key, value in tree.items():    # Iterate over (key, value) pairs
    ...

Boundary Operations

key, value = tree.first()          # Get first (min) entry
key, value = tree.last()           # Get last (max) entry
key, value = tree.pop_first()      # Remove and return first entry
key, value = tree.pop_last()       # Remove and return last entry

Prefix Queries

# Get first match
result = tree.get_prefix("prefix")
if result:
    key, value = result

# Get all matches
for key, value in tree.prefix_iter("prefix"):
    print(f"{key}: {value}")

Fuzzy Matching

# Find keys within edit distance
for key, value, distance in tree.fuzzy_search("search", max_distance=2):
    print(f"{key}: {value} (distance={distance})")

Performance

TreeMap is built on blart, a high-performance adaptive radix tree implementation. Operations have the following complexity:

  • Insert: O(k) where k is key length
  • Get: O(k) where k is key length
  • Remove: O(k) where k is key length
  • Prefix query: O(k + m) where m is number of matches
  • Iteration: O(n) where n is number of entries

Benchmarks

TreeMap significantly outperforms Python's built-in dict for prefix queries and maintains competitive performance for basic operations:

Operation TreeMap Python dict Speedup
Insert (10k) 2.1 ms 1.8 ms 0.9x
Get (10k) 1.9 ms 1.5 ms 0.8x
Prefix query (100 matches) 0.05 ms 5.2 ms* 104x
Fuzzy search (distance=2) 1.2 ms N/A N/A

*Python dict requires O(n) linear scan for prefix queries

See tests/test_performance.py for detailed benchmarks.

Use Cases

Command-line Autocomplete

commands = TreeMap({
    "list": "List items",
    "list-users": "List users",
    "load": "Load file",
    "save": "Save file"
})

# User types "li"
for cmd, desc in commands.prefix_iter("li"):
    print(f"{cmd}: {desc}")

Spell Checking

dictionary = TreeMap({"python": 1, "program": 2, "function": 3})

# User types "phyton" (typo)
suggestions = list(dictionary.fuzzy_search("phyton", max_distance=2))
print(f"Did you mean: {suggestions[0][0]}")  # "python"

URL Routing

routes = TreeMap({
    "/api/users": handler1,
    "/api/users/create": handler2,
    "/api/products": handler3
})

# Find all /api/users routes
for route, handler in routes.prefix_iter("/api/users"):
    print(f"{route} -> {handler}")

File System Navigation

filesystem = TreeMap({
    "/home/user/documents/file1.txt": 1024,
    "/home/user/documents/file2.txt": 2048,
    "/home/user/downloads/image.png": 512
})

# List all files in /home/user/documents/
for path, size in filesystem.prefix_iter("/home/user/documents/"):
    print(f"{path}: {size} bytes")

Examples

Comprehensive examples are available in the examples/ directory:

Run any example:

python examples/basic_usage.py
python examples/prefix_queries.py
python examples/fuzzy_matching.py

Important Notes

Prefix Key Removal

Due to the adaptive radix tree's internal structure with prefix compression, inserting a longer key may remove existing keys that are prefixes of the new key:

tree = TreeMap()
tree["key"] = 1
tree["key123"] = 2  # This removes "key"

print("key" in tree)      # False
print("key123" in tree)   # True

This is intentional behavior for maintaining tree efficiency. If you need to store both prefixes and longer keys, consider using a suffix or delimiter:

tree["key_"] = 1      # Add suffix
tree["key123"] = 2    # Both keys coexist

Development

Running Tests

# Install development dependencies
pip install pytest pytest-cov

# Run tests
pytest tests/

# Run with coverage
pytest --cov=blart-py tests/

Code Quality

# Format Rust code
cargo fmt

# Lint Rust code
cargo clippy

# Format Python code
black examples/ tests/

# Type check Python code
mypy python/

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for your changes
  4. Ensure all tests pass (pytest tests/)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

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

Acknowledgments

  • Built on top of blart by Declan Kelly
  • Uses PyO3 for Rust-Python interop
  • Built with maturin

Related Projects

  • blart - The underlying Rust implementation
  • art-tree - Original C implementation of adaptive radix trees
  • pygtrie - Pure Python trie implementation

Project details


Download files

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

Source Distribution

blart_py-0.1.0.tar.gz (52.6 kB view details)

Uploaded Source

Built Distributions

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

blart_py-0.1.0-cp314-cp314-macosx_11_0_arm64.whl (285.4 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

blart_py-0.1.0-cp313-cp313-macosx_11_0_arm64.whl (287.4 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

blart_py-0.1.0-cp312-cp312-macosx_11_0_arm64.whl (287.4 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

blart_py-0.1.0-cp311-cp311-macosx_11_0_arm64.whl (286.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

blart_py-0.1.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (585.6 kB view details)

Uploaded CPython 3.11macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

blart_py-0.1.0-cp310-cp310-win_amd64.whl (183.9 kB view details)

Uploaded CPython 3.10Windows x86-64

blart_py-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (337.1 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

blart_py-0.1.0-cp310-cp310-macosx_11_0_arm64.whl (286.5 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

blart_py-0.1.0-cp39-cp39-macosx_11_0_arm64.whl (288.3 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

blart_py-0.1.0-cp38-cp38-macosx_11_0_arm64.whl (287.9 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

File details

Details for the file blart_py-0.1.0.tar.gz.

File metadata

  • Download URL: blart_py-0.1.0.tar.gz
  • Upload date:
  • Size: 52.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.21

File hashes

Hashes for blart_py-0.1.0.tar.gz
Algorithm Hash digest
SHA256 97a5bf37eaa2651c5e58ec842fae3e63db778a8e6e64f79e4ce0754b1ff7f702
MD5 26a7ddff6fe8bb7da4e16c6ca0a581b6
BLAKE2b-256 614711b4c0ae95a8c4f9771628714345293c47e93176c6e093647f6026c18917

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2587ced9c224c51df763036b4a5028e815557cbf7002dacfb1821da21c421975
MD5 ac4fdb4d3c747a4a36906bd8b33b0b58
BLAKE2b-256 89b6d111ae85f70cb7f0fa1ebc80ab233812959be1483bea9c1907d8e27e2ccc

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 087a1ec2437014ff862566abbe50f0a5200b26e6e36c6e385fb7a585dfd4a6e3
MD5 d7bee7e1a382788eef5a3c0c345a6287
BLAKE2b-256 0bc1e79839ab09e52b2905041208f30e2cd4a4fdab4d6d37c576ca7527d57fc7

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4d51831c27e5f39cde0bacccd716089ae9a4650484c5761c664365e78374b682
MD5 fc0e5b9f6933d6d478cee8352f77bbdb
BLAKE2b-256 17a7ccfe5dbc44819d84c811b148de6f60ba407f06ab9a0b2d7387754eedd622

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 311df5a9a9b0367d464e67ef1cb2775338a6dee7d1bb7405e8f559c075b6f7af
MD5 9d25c11cbe78edc932ce7232e4d8a968
BLAKE2b-256 4bf6ad97b866aa4ad93b4470f345621a92d3561cca7a1d7660d5ac7635738d6b

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 f4c973951d9aebe099e6afacc7bb1fc8346a42d19b2ff4340e5f404c826a63c4
MD5 6b53860c26d3601b5250676d7abfbf33
BLAKE2b-256 fe4715fba8ac43d4e4cd2de991b60776eefec26133a9d959626bd562f5383cc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for blart_py-0.1.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: build.yml on axelv/blart-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file blart_py-0.1.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: blart_py-0.1.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 183.9 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for blart_py-0.1.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 0ae105f5514e91abd5f5aea91ff6c5f70375c18da82763feb0ca7ec1b4497cbc
MD5 34def29d76a0b005a675e0ba163fff73
BLAKE2b-256 c21dfc280b395ee1b63df37edc25c23a2209df4acdf6f9b8a364bc1485eb31b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for blart_py-0.1.0-cp310-cp310-win_amd64.whl:

Publisher: build.yml on axelv/blart-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file blart_py-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b48e4682895e8131dfc0ae4b381afa2dd02f8c6292d91ae3d0e31c1831e25f80
MD5 95def63c3d0fdb50ea115f96b0d465a8
BLAKE2b-256 1bd2233f242f8877bd1fe7f3156ddd14ac1a41c2c4691c539a0caa0652526b94

See more details on using hashes here.

Provenance

The following attestation bundles were made for blart_py-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build.yml on axelv/blart-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file blart_py-0.1.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b4b9e302f8a73bda7e8eef49f8e0cca38d1680c08cdaa21824bc889e0bfb0f07
MD5 b5da5b8fabf3c1a2c79aba37f9f80aaf
BLAKE2b-256 9b434a4f41e8884730587751bd567255f8d583c6cdde2d4e20b1e0c25b5728a1

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b2ef92c861dd9f0e7fe104564827405e95507e8f865c8d2c7a646b52d11d1b7a
MD5 a8af0b50de6f2ae6a27a35b2ded60c80
BLAKE2b-256 c8b44162e6a2b26429cf49363fcdea48b9060ca72df762de106563dab3dfc343

See more details on using hashes here.

File details

Details for the file blart_py-0.1.0-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for blart_py-0.1.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 767d07933aed2cdb46abe4f52608bbc9e267d41561d48b49af4b829973eb2471
MD5 e6b2d6017dc9dbd84aa26b0cf497e9f0
BLAKE2b-256 0f2f1fb69f391731ab87fd8fbba889c2550faf85069b6322b7ea3672afa22ee1

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