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.0a2.tar.gz (53.1 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.0a2-cp312-cp312-win_amd64.whl (178.7 kB view details)

Uploaded CPython 3.12Windows x86-64

pypersistent-2.0.0a2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (278.5 kB view details)

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

pypersistent-2.0.0a2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (258.9 kB view details)

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

pypersistent-2.0.0a2-cp312-cp312-macosx_11_0_arm64.whl (245.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypersistent-2.0.0a2-cp312-cp312-macosx_10_9_x86_64.whl (255.2 kB view details)

Uploaded CPython 3.12macOS 10.9+ x86-64

pypersistent-2.0.0a2-cp311-cp311-win_amd64.whl (178.8 kB view details)

Uploaded CPython 3.11Windows x86-64

pypersistent-2.0.0a2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (281.1 kB view details)

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

pypersistent-2.0.0a2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (261.9 kB view details)

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

pypersistent-2.0.0a2-cp311-cp311-macosx_11_0_arm64.whl (244.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypersistent-2.0.0a2-cp311-cp311-macosx_10_9_x86_64.whl (250.6 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

pypersistent-2.0.0a2-cp310-cp310-win_amd64.whl (178.1 kB view details)

Uploaded CPython 3.10Windows x86-64

pypersistent-2.0.0a2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (277.7 kB view details)

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

pypersistent-2.0.0a2-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.0a2-cp310-cp310-macosx_11_0_arm64.whl (243.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypersistent-2.0.0a2-cp310-cp310-macosx_10_9_x86_64.whl (248.8 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: pypersistent-2.0.0a2.tar.gz
  • Upload date:
  • Size: 53.1 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.0a2.tar.gz
Algorithm Hash digest
SHA256 8be86fb5d8e92369eaf0b4db0685cdf279095b0a8b2541a1e2b37e5ab8affb81
MD5 af8bed8c8fafebde7fb3eebafb2191e3
BLAKE2b-256 07ee737703cfd8ea2c3ed54ed1259a2c9a2aadb27b218cb55920d70bdc37ad0a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2.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.0a2-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 5c177b871b5be49c29ecc3c894804de956055f62c078988890b06dbaffd4cdba
MD5 7c8c253860249f7f80d2a4d44571de76
BLAKE2b-256 ddda46e3db4100f495f10c6fb6953a9e4d046708e64693b56d6ff6d5f5c8e9c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0591e4d4bca0ed89d8f9d070a8d960694a4c0217c0181196ca575c5a5f1f2f6b
MD5 4005a60c6b71bad651c754e3b1c6e47d
BLAKE2b-256 4ddc895c999a938de6ef31f7169776d97994f8c21626e9ab435a5be9c5fe593f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 519b89f1dd97c739cc8c491b74141e9260f1e1b78752f9ddbedd4a71f251075b
MD5 f80d5994e91de95e73f85085416a101f
BLAKE2b-256 262aafe57fa1bb4522810280cedf14c90d62b960fe1e755cf33a3aa6916c4f44

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dce2eb01349f73e38f7e9a4713e08fe2d2acd59d4c9727f4c4ebd3ad1960756a
MD5 4da0d7c7cd41165bd083107bd97a9bd3
BLAKE2b-256 4080770960dea97bcfd14f73f7dd4aae5305d45f5f4dfd0ddb3623ad8168e3b9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7745958486630c42babbef1afca89d0834bacebd0ff21848ed20464b2505d812
MD5 b8fd85e95d32b39e77722780c15dda2a
BLAKE2b-256 3d1adfad6d7a20a71d3408a1a8fbea833022bddfbd994b80ddfcf592fad0982e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 45a636cb7269a0ce4aea42678bece9769dfabae7453f856f1c1e146a1e37d466
MD5 a4b30506403cdc7ed408e86bfc216586
BLAKE2b-256 16c27131c136f292cf4a7f4ec47404dc8e62eab4b7e02cee692b04e4dcc4f7a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 348808352c49af90344a9c4a48851a0a9f2e02e775366cb31a0d939b03b280d2
MD5 4f562abce5a519991e68eab31c19d229
BLAKE2b-256 9c5c27be9efb5306580fe5eff339b9dbb06471732453a5c3ec51dd3b744a0b36

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 08fbee112cb110f57a176b280b27ad90d84dfa0ab916439d841c1088bf8239db
MD5 85a147ed43aab8df540902a98a2c48f1
BLAKE2b-256 896b1a106b74f03599f20840087b75b2fee36c3c0a20d3b591e61c9726b23efe

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3b6594bcb7a496b5617c48a2727ae8e824cfe1e8bfc9bdb193e0a0184cb65b19
MD5 12543ff9995acf2a3be0dec35bcafa6e
BLAKE2b-256 566729ba566cdc6c402e526d3ef317edd06cd957b3fcdf0a9828842d1f5418ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d0b04f44d7936cb6c2f907ddace4b68787aaba1524473f479df1d2db8a72e1af
MD5 79d7e3738b543515a8c6663033da76de
BLAKE2b-256 234b5de2491ad3463a2c0180654c5d646e2fedbb2e99e31f6f79589daddba385

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 5c22a5f984c5bcf58709e44b8fded76fd782091b0d1e80699cb887e9a13051e4
MD5 b530883e060c8ab6ca353d5d1d3aa1d0
BLAKE2b-256 36cba2b37844d1d6d4091461524efb1442cb280d8cbcc09de7f7dec55f9a7d67

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e7ac69c8e181ac9b3f3e87f5216df11fe1bb095b955fac105bcc3831c0267fda
MD5 c7a72ebb046dd318c820dc46abfd438b
BLAKE2b-256 d94fc8280cb383ac40a9e30a8a5ee9696425e060b40338a686053e5fafc5c40a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8102530dbb04c219a929a633368357a5002e70bd230127259fcfe60d70bab900
MD5 78491843a2894a25d7408cb347f07f11
BLAKE2b-256 ce7bd7139e129fca3ef6c023bb5c905874ccdfec1f63d800d965baa8207a530e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6a9b63ab1d1dd7cc1a9bb92cf17552a91b3b9fe916fa5279f42a0ca58d936e07
MD5 1a47815f4d1d50623f7b8301efc9296a
BLAKE2b-256 ba19784f7fd266f900490feabcc606529bff1b855ffb4bc5e536e0d3e9a6ff22

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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.0a2-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for pypersistent-2.0.0a2-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d36a2d80b4fca669c28f989c8bb0840b42eb68f45d1088896e48c686be35c7dc
MD5 a0f9f8afb112983fc6c98c71c769261c
BLAKE2b-256 85db70c38be1ac5b1557b0f2c7b0593468e273b755705b31907c17de7ff9915f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypersistent-2.0.0a2-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