Skip to main content

High-performance persistent (immutable) data structures for Python

Project description

PyPersistent

A high-performance collection of persistent (immutable) data structures for Python, written in C++.

Features

  • Immutable: All operations return new maps, leaving originals unchanged
  • Structural Sharing: New versions share most structure with old versions (O(log n) copies instead of O(n))
  • Fast: 38% faster than pure Python implementation for insertions, ~10x slower than mutable dict
  • Thread-Safe: Immutability makes concurrent access safe without locks
  • Python 3.13+ Free-Threading Ready: Lock-free design with atomic reference counting for true parallelism
  • Memory Efficient: Structural sharing minimizes memory overhead
  • Dual Interface: Both functional (Clojure-style) and Pythonic APIs

Data Structures

PyPersistent provides five core persistent data structures:

PersistentMap

Unordered key-value map based on Hash Array Mapped Trie (HAMT).

  • Use for: General-purpose dictionary needs with immutability
  • Time complexity: O(log₃₂ n) ≈ 6 steps for 1M elements
  • Features: Fast lookups, structural sharing, bulk merge operations
  • Example:
    from pypersistent import PersistentMap
    
    m = PersistentMap.create(name='Alice', age=30)
    m2 = m.set('city', 'NYC')
    m3 = m | {'role': 'developer'}  # Merge
    

PersistentTreeMap

Sorted key-value map based on Left-Leaning Red-Black Tree.

  • Use for: Ordered data, range queries, min/max operations
  • Time complexity: O(log₂ n) for all operations
  • Features: Sorted iteration, range queries (subseq/rsubseq), first/last
  • Example:
    from pypersistent import PersistentTreeMap
    
    m = PersistentTreeMap.from_dict({3: 'c', 1: 'a', 2: 'b'})
    list(m.keys())  # [1, 2, 3] - always sorted
    
    # Range queries
    sub = m.subseq(start=1, end=2, start_inclusive=True, end_inclusive=False)
    list(sub.keys())  # [1]
    
    # Min/max
    m.first()  # (1, 'a')
    m.last()   # (3, 'c')
    

PersistentVector

Indexed sequence based on bit-partitioned vector trie (RRB-Tree variant).

  • Use for: Ordered sequences with efficient random access and append
  • Time complexity: O(log₃₂ n) for get/set, O(1) for append
  • Features: Fast indexed access, efficient append, slicing
  • Example:
    from pypersistent import PersistentVector
    
    v = PersistentVector.create(1, 2, 3)
    v2 = v.conj(4)  # Append
    v3 = v2.assoc(0, 10)  # Update index 0
    v[1]  # 2 - indexed access
    

PersistentHashSet

Unordered set based on HAMT (same as PersistentMap).

  • Use for: Unique collection of items, set operations
  • Time complexity: O(log₃₂ n) for add/remove/contains
  • Features: Fast membership testing, set operations (union, intersection, difference)
  • Example:
    from pypersistent import PersistentHashSet
    
    s = PersistentHashSet.create(1, 2, 3)
    s2 = s.conj(4)  # Add
    s3 = s.disj(2)  # Remove
    2 in s  # True
    

PersistentArrayMap

Small map optimization using array of key-value pairs.

  • Use for: Maps with < 8 entries (automatic optimization)
  • Time complexity: O(n) linear scan, but faster than HAMT for tiny maps
  • Features: Lower memory overhead, faster for very small maps
  • Note: Typically used internally; PersistentMap automatically uses this for small maps

Choosing the Right Data Structure

Need Use Why
General key-value storage PersistentMap Fastest for unordered data
Sorted keys / range queries PersistentTreeMap Maintains sort order, supports ranges
Indexed sequence PersistentVector Fast random access and append
Unique items / set operations PersistentHashSet Membership testing, set algebra
Very small maps (< 8 items) PersistentArrayMap Lower overhead for tiny maps

Performance

Quick Summary

pypersistent provides 6-8% faster bulk operations compared to baseline and is 3-150x faster than pure Python pyrsistent for most operations. The real value is structural sharing: creating variants is 3000x faster than copying dicts.

Benchmark Results

vs Python dict (1M elements)

Operation pypersistent dict Notes
Construction 2.74s 299ms 9x slower (immutability cost)
Lookup (1K ops) 776ms 427ms 1.8x slower
Update (single) 147µs ~80ns Comparable for single ops
Structural Sharing (100 variants) 0.48ms 1.57s 3000x FASTER

Key insight: For creating multiple versions, pypersistent is orders of magnitude faster.

vs pyrsistent (pure Python) - Apples-to-Apples

Size Operation pypersistent pyrsistent Speedup
1M Merge (500K+500K) 11.5ms 1.60s 139x faster
1M Construction 185ms 813ms 4.4x faster
1M Lookup (1M ops) 726ms 796ms 1.1x faster
1M Iteration 452ms 167ms 2.7x slower
1K Merge (500+500) 8.7µs 1.22ms 141x faster
1K Construction 76µs 192µs 2.5x faster
100 Merge (50+50) 17.8µs 120µs 6.7x faster
100 Construction 30µs 18.5µs 1.6x slower

Iteration note: Using items_list() instead of items() makes iteration 1.7-3x faster for maps < 100K

Performance by Map Size

Size Construction Lookup (1K ops) Sharing (100 variants)
100 73µs 19µs 77µs
1K 765µs 205µs 95µs
10K 9.7ms 228µs 108µs
100K 110ms 255µs 133µs
1M 2.74s 776ms 158µs

Fast Iteration Methods

For complete iteration over small-medium maps, use materialized list methods:

m = PersistentMap.from_dict({...})

# Fast methods (1.7-3x faster for maps < 100K)
items = m.items_list()   # Returns list of (key, value) tuples
keys = m.keys_list()     # Returns list of keys
values = m.values_list() # Returns list of values

# Lazy iterators (better for very large maps or early exit)
for k, v in m.items():   # Generator, O(log n) memory
    ...

Performance:

  • Maps ≤ 10K: 3x faster with items_list()
  • Maps ≤ 100K: 1.7x faster with items_list()
  • Maps > 100K: Use iterator (lazy, memory-efficient)

When to Use pypersistent

Use pypersistent when:

  • Creating multiple versions of data (undo/redo, time-travel)
  • Concurrent access across threads (lock-free reads)
  • Functional programming patterns
  • Merging large maps frequently

Use dict when:

  • Single mutable map is sufficient
  • Maximum raw construction speed is critical
  • Memory per entry is constrained

Technical Details

Implementation: C++ HAMT (Hash Array Mapped Trie) with:

  • Bottom-up bulk construction for from_dict()
  • Arena allocator for fast node allocation
  • Structural tree merging for merge()
  • COW semantics for collision nodes
  • Fast iteration with pre-allocated lists

Time Complexity: O(log₃₂ n) ≈ 6 steps for 1M elements Space Complexity: O(n) with structural sharing across versions

For detailed performance analysis and benchmarking methodology, see docs/.

Installation

pip install pypersistent

Or build from source:

git clone https://github.com/cmarschner/pypersistent.git
cd pypersistent
python setup.py install

Usage

PersistentMap - Hash Map

from pypersistent import PersistentMap

# Create
m = PersistentMap.create(name='Alice', age=30)
m = PersistentMap.from_dict({'name': 'Alice', 'age': 30})

# Add/update (functional style)
m2 = m.assoc('city', 'NYC')

# Add/update (Pythonic style)
m2 = m.set('city', 'NYC')
m3 = m | {'role': 'developer'}  # Merge

# Get
name = m['name']  # Raises KeyError if missing
name = m.get('name', 'default')

# Remove
m4 = m.dissoc('age')  # Functional
m4 = m.delete('age')  # Pythonic

# Check membership
'name' in m  # True

# Iterate
for key, value in m.items():
    print(key, value)

PersistentTreeMap - Sorted Map

from pypersistent import PersistentTreeMap

# Create (automatically sorted by keys)
m = PersistentTreeMap.from_dict({3: 'c', 1: 'a', 2: 'b'})
list(m.keys())  # [1, 2, 3]

# Same API as PersistentMap
m2 = m.assoc(4, 'd')
m3 = m.dissoc(1)

# Sorted-specific operations
first_entry = m.first()  # (1, 'a')
last_entry = m.last()    # (3, 'c')

# Range queries
sub = m.subseq(start=1, end=3)  # Keys 1-2 (end exclusive)
list(sub.keys())  # [1, 2]

rsub = m.rsubseq(start=3, end=1)  # Reverse order
list(rsub.keys())  # [3, 2]

PersistentVector - Indexed Sequence

from pypersistent import PersistentVector

# Create
v = PersistentVector.create(1, 2, 3)
v = PersistentVector.from_list([1, 2, 3])

# Append (functional)
v2 = v.conj(4)  # [1, 2, 3, 4]

# Update by index
v3 = v.assoc(0, 10)  # [10, 2, 3]

# Access by index
first = v[0]  # 1
last = v[-1]  # 3

# Slice
sub = v[1:3]  # PersistentVector([2, 3])

# Iterate
for item in v:
    print(item)

# Length
len(v)  # 3

PersistentHashSet - Set

from pypersistent import PersistentHashSet

# Create
s = PersistentHashSet.create(1, 2, 3)
s = PersistentHashSet.from_set({1, 2, 3})

# Add
s2 = s.conj(4)  # {1, 2, 3, 4}

# Remove
s3 = s.disj(2)  # {1, 3}

# Membership
2 in s  # True

# Set operations
s1 = PersistentHashSet.create(1, 2, 3)
s2 = PersistentHashSet.create(3, 4, 5)

union = s1 | s2  # {1, 2, 3, 4, 5}
intersection = s1 & s2  # {3}
difference = s1 - s2  # {1, 2}

# Iterate
for item in s:
    print(item)

API Summary

Common operations (all data structures):

  • create(*args) - Create from elements
  • from_X(...) - Create from Python collection
  • Immutability - all operations return new instances
  • Thread-safe reads - safe to share across threads

PersistentMap / PersistentTreeMap:

  • assoc(k, v) / set(k, v) - Add/update
  • dissoc(k) / delete(k) - Remove
  • get(k, default=None) - Get value
  • m[k] - Get (raises KeyError)
  • k in m - Membership
  • keys(), values(), items() - Iterators
  • m1 | m2 - Merge

PersistentTreeMap only:

  • first() - Min entry
  • last() - Max entry
  • subseq(start, end) - Range query
  • rsubseq(start, end) - Reverse range

PersistentVector:

  • conj(item) - Append
  • assoc(idx, val) - Update by index
  • v[idx] - Get by index
  • v[start:end] - Slice
  • len(v) - Length

PersistentHashSet:

  • conj(item) - Add
  • disj(item) - Remove
  • item in s - Membership
  • s1 | s2 - Union
  • s1 & s2 - Intersection
  • s1 - s2 - Difference

Use Cases

Use persistent data structures when:

  • Creating multiple versions of data (undo/redo, time-travel, version history)
  • Sharing data across threads without locks or defensive copying
  • Functional programming patterns (immutability, pure functions)
  • Creating modified copies is frequent (structural sharing makes this fast)
  • Python 3.13+ free-threading for true parallelism

Use mutable collections when:

  • Single mutable instance is sufficient
  • Maximum raw construction speed is critical
  • Memory per entry is highly constrained

Specific use cases:

  • Config management: Share base config, each thread creates customized version
  • Event sourcing: Maintain history of all states efficiently
  • Reactive programming: Pass immutable state between components
  • Concurrent caching: Multiple threads read/update cache without locks
  • Functional data pipelines: Transform data through pipeline stages

How It Works

PyPersistent implements multiple classic persistent data structures:

PersistentMap - Hash Array Mapped Trie (HAMT)

Based on the HAMT data structure used by Clojure, Scala, and Haskell:

  • 32-way branching tree indexed by hash bits
  • Path copying for immutability
  • Structural sharing between versions
  • std::shared_ptr for entry sharing (44x fewer INCREF/DECREF)
  • Inline storage with std::variant for cache-friendly access

PersistentTreeMap - Left-Leaning Red-Black Tree

Self-balancing binary search tree with:

  • Path copying for immutability
  • Sorted order maintenance (O(log₂ n))
  • Atomic reference counting for node sharing
  • Range query support via tree traversal

PersistentVector - Bit-Partitioned Trie

32-way branching tree for indexed access:

  • Path copying for updates
  • Tail optimization for fast append
  • O(log₃₂ n) random access (~6 steps for 1M elements)
  • Efficient slicing via structural sharing

PersistentHashSet - HAMT-based Set

Uses PersistentMap internally with:

  • Keys as set elements
  • Same O(log₃₂ n) complexity
  • Set algebra operations

PersistentArrayMap - Simple Array

Linear array for tiny maps (< 8 entries):

  • Lower overhead than HAMT for small sizes
  • O(n) operations but faster than tree for n < 8
  • Automatically used by PersistentMap when beneficial

Technical Details

Complexity:

  • PersistentMap/HashSet: O(log₃₂ n) ≈ 6 steps for 1M elements
  • PersistentTreeMap: O(log₂ n) for all operations
  • PersistentVector: O(log₃₂ n) get/set, O(1) append
  • PersistentArrayMap: O(n) but fast for n < 8

Implementation:

  • C++ with pybind11 bindings
  • Atomic reference counting (std::atomic<int>)
  • Structural sharing for memory efficiency
  • Thread-safe reads (fully immutable)

Python 3.13+ Free-Threading Support

PyPersistent is fully compatible with Python 3.13's experimental free-threading mode (nogil), making it ideal for parallel workloads:

Why It Works

  1. Lock-Free Reads: Immutable data structure allows concurrent reads without synchronization
  2. Atomic Reference Counting: Internal C++ reference counting uses std::atomic operations
  3. Thread-Safe Entry Storage: Uses std::shared_ptr with built-in thread-safe reference counting
  4. Independent Updates: Each thread can create new versions without blocking others

Usage with Free-Threading

# Python 3.13+ with --disable-gil or PYTHON_GIL=0
import threading
from pypersistent import PersistentMap

# Shared base map
base_config = PersistentMap.create(
    api_url='https://api.example.com',
    timeout=30,
    retries=3
)

def process_request(thread_id, data):
    # Each thread creates its own version - no locks needed!
    my_config = base_config.set('thread_id', thread_id)
    my_config = my_config.set('request_data', data)

    # Concurrent reads are completely lock-free
    url = my_config['api_url']
    timeout = my_config['timeout']

    # Do work...
    return my_config

# Spawn threads - true parallelism without GIL!
threads = []
for i in range(100):
    t = threading.Thread(target=process_request, args=(i, f'data_{i}'))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

Performance Benefits

Without the GIL:

  • Parallel reads: Multiple threads read simultaneously without contention
  • Parallel updates: Each thread creates new versions independently
  • No lock overhead: Zero synchronization cost for immutable operations
  • Structural sharing shines: Creating 100 thread-local variants is 3000x faster than copying dicts

Enable Free-Threading

# Python 3.13+
python3.13 --disable-gil your_script.py

# Or set environment variable
export PYTHON_GIL=0
python3.13 your_script.py

Note: Free-threading is experimental in Python 3.13. Some packages may not be compatible yet.

Development

# Install development dependencies
pip install pytest pybind11

# Build extension
python setup.py build_ext --inplace

# Run all tests
pytest -v

# Run specific data structure tests
pytest test_persistent_map.py -v
pytest test_persistent_tree_map.py -v
pytest test_persistent_vector.py -v
pytest test_persistent_hash_set.py -v

# Run performance benchmarks
python performance_test.py
python performance_vector.py

License

MIT License - see LICENSE file for details

Credits

Inspired by Clojure's persistent data structures and the HAMT paper by Bagwell (2001).

Implementation by Clemens Marschner.

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

pypersistent-2.0.0a3.tar.gz (68.4 kB view details)

Uploaded Source

Built Distributions

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

pypersistent-2.0.0a3-cp312-cp312-win_amd64.whl (178.9 kB view details)

Uploaded CPython 3.12Windows x86-64

pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (279.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (258.6 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

pypersistent-2.0.0a3-cp312-cp312-macosx_11_0_arm64.whl (245.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypersistent-2.0.0a3-cp312-cp312-macosx_10_9_x86_64.whl (255.3 kB view details)

Uploaded CPython 3.12macOS 10.9+ x86-64

pypersistent-2.0.0a3-cp311-cp311-win_amd64.whl (179.0 kB view details)

Uploaded CPython 3.11Windows x86-64

pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (281.6 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (262.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

pypersistent-2.0.0a3-cp311-cp311-macosx_11_0_arm64.whl (244.4 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypersistent-2.0.0a3-cp311-cp311-macosx_10_9_x86_64.whl (250.9 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

pypersistent-2.0.0a3-cp310-cp310-win_amd64.whl (178.3 kB view details)

Uploaded CPython 3.10Windows x86-64

pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (277.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (259.9 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

pypersistent-2.0.0a3-cp310-cp310-macosx_11_0_arm64.whl (243.2 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypersistent-2.0.0a3-cp310-cp310-macosx_10_9_x86_64.whl (249.1 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

File details

Details for the file pypersistent-2.0.0a3.tar.gz.

File metadata

  • Download URL: pypersistent-2.0.0a3.tar.gz
  • Upload date:
  • Size: 68.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pypersistent-2.0.0a3.tar.gz
Algorithm Hash digest
SHA256 cd9fbe3eb7d50f3f67326a2259258997db392bd4807ad4e8ccdb6d4deaa9046d
MD5 a181bbd7f9098da00121e37eeecf7f3b
BLAKE2b-256 1702f38874b23078851e0e0658fd4a1fea666a32ba77b7ce1d2a583814b8c5ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3.tar.gz:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 9afa3742568eace20f89f3f3f46f3f8b0ad64746a7bd21349eee82dbb4fffa64
MD5 4d7b6b272243e617bb226bbf98b43fed
BLAKE2b-256 087b1f33452b3d568bf932c95e2591a8c55c548d5a8804f5305e1c6d3c2e8a2e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp312-cp312-win_amd64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b3358b5a9e0ac76d4383bca836a27a290283b1a193e11c33e66bd94d9ed15206
MD5 c27e806856381ebbb9f2867653183b5f
BLAKE2b-256 b0aa33ae7aa71e1e5f736c49d54adbcbfd32b3adaf4e50d705d8c867093d12c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a438a8d9bb39131071a42eb6a04b3ac95e4f7ad0b1f7c3776a35cc2363e20dc6
MD5 153b9698c045fa1252dbb5eed0966046
BLAKE2b-256 3678d43464a010bca659cc5b8354d49170f3e17ad6b2b78d421f60125c0b3bcf

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 02e7b97fe1503e24a4f198685e9db16eb5391c353e50f0807a6f37c45bd601f5
MD5 8243c7273c53d74c3fd83470915d268a
BLAKE2b-256 701f53ce8a9190c603fe1fefd5d32033916ef51e783d883f0f268391c1826d31

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d7a97c4be4a3e175fb3f50b8309c12d813418c4197f4d461178d1a3fa4bc5249
MD5 b9db18b219be1cf485f2987650642b9f
BLAKE2b-256 10ea4dd0f7f8ede03b4323c337e251f110e477380a8665addf263de656399cb5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp312-cp312-macosx_10_9_x86_64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 c78c0f6e8115c96e3969d2443a396213f8b02ee7bd8f216ab53b0c329210ef2f
MD5 be2e50eaea160ca6cd14e4b826eaad25
BLAKE2b-256 6bf2d013e1f919c526355b8a6294b53fe9e1553119cdbe2b5f0e53f0fc875374

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp311-cp311-win_amd64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c2e657c0f8a2c9d5961f91fcca0e7e8193604d49a74d7ed80a5abd389cbd2587
MD5 aa01f53258c31d6ff8178dc9ede8df98
BLAKE2b-256 a5f2ed99903c18207a41af99ec5062f36224873ba1a50f2b4c1d6312f019c7fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1879c23ff6f5500eee640f38033ce75c81dd738ce0a828dde7a5a7a766388933
MD5 4ec1689fd16b5fe2bd23abcf9c500172
BLAKE2b-256 867c0d49b11cf3ec49822e53b954e859ecbaec746e4304fb853779104f031424

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f6aae223f09ebd9c8fea93a49eb2a860fbb5b742db4aead4d1ea65208281395c
MD5 5e1782a71b23f97571c34c12df2f8085
BLAKE2b-256 64a8f92107ff57877f17c429a46bc6bb9f616fa6d9bbb91254819c3306fded43

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 bb9bac2615f59c325b2939810370b56fc1291f5a5ab5964d3988f9926de13ebf
MD5 af7e2b5c50ffa8ebd583e8d06fa15ed9
BLAKE2b-256 32adbd2fc4cadf43e47a6a3ef99cf26f4098949d38be89af53f4bf4858e7f9f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp311-cp311-macosx_10_9_x86_64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 a7ba44e21280b8675f8ca44b045f90266bc5c976802b56c10440e17bbd293788
MD5 0692b233ce1d344139c61ac486a782c7
BLAKE2b-256 c19624e14d753a39a4b0ab9cdb5a28117869b9f70b5547bbf91487095c04c2d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp310-cp310-win_amd64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1ae269cf5a734a03b0668bfe2f564dc61e4abddbcb33f8ed218df0c8300afacb
MD5 50c3884872e1fa29c418fde5ee3b3366
BLAKE2b-256 a48eb54e2b104712853fc674e397a1221b2494f85bbbc20245322fe8346f5298

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0694eae01ffc59b3512778657d09657c32fa8f68b063d27e9a72a0a4e73d5ba1
MD5 1b047035e2d58b900d092f72ad613e10
BLAKE2b-256 12ddeb8e76f9173520c66cb09f87124f70bcda45c31a06ae0316ec421dff379c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f05133f9e1f78ef4d9c651e53d23de5b40dfc49482906bc8cae558af45b2c3e8
MD5 3465e7418e9d3b4d347a932cca337b21
BLAKE2b-256 364af461c1a171de802fb5649ad4d9aca68c0bcd3f32ecf596eb0b6e74a67c99

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

File details

Details for the file pypersistent-2.0.0a3-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0c99e4ba07ac381a00ef6f573b10a228651a299aabfdaec5855857ba20036a09
MD5 e7e7e480c188ab1ec2fbd42befe424e5
BLAKE2b-256 b3b61e9cc37b8fa69e5943f832c3c9ba69792a9ca475e17fb7f0657ff34509fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a3-cp310-cp310-macosx_10_9_x86_64.whl:

Publisher: build-wheels.yml on cmarschner/pypersistent

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

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