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 collections, leaving originals unchanged
  • Structural Sharing: New versions share most structure (O(log n) changes instead of O(n) copies)
  • Fast: 3-5x faster than pyrsistent, with merge operations up to 176x faster
  • 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:

PersistentDict

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 PersistentDict
    
    m = PersistentDict.create(name='Alice', age=30)
    m2 = m.set('city', 'NYC')
    m3 = m | {'role': 'developer'}  # Merge
    

PersistentSortedDict

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 PersistentSortedDict
    
    m = PersistentSortedDict.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')
    

PersistentList

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 PersistentList
    
    v = PersistentList.create(1, 2, 3)
    v2 = v.conj(4)  # Append
    v3 = v2.assoc(0, 10)  # Update index 0
    v[1]  # 2 - indexed access
    

PersistentSet

Unordered set based on HAMT (same as PersistentDict).

  • 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 PersistentSet
    
    s = PersistentSet.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; PersistentDict automatically uses this for small maps

Choosing the Right Data Structure

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

Performance

Why Use Persistent Data Structures?

The key advantage of persistent data structures is structural sharing: when you create a modified version, the new and old versions share most of their internal structure rather than duplicating everything.

Example:

# Python dict - must copy everything
d1 = {i: f'val{i}' for i in range(10000)}
d2 = d1.copy()  # Copies all 10,000 entries
d2['new_key'] = 'new_value'

# PersistentDict - shares structure
from pypersistent import PersistentDict
m1 = PersistentDict.from_dict({i: f'val{i}' for i in range(10000)})
m2 = m1.set('new_key', 'new_value')  # Shares 99.99% of structure with m1

When to Use pypersistent

✅ Use pypersistent when:

  • Creating multiple versions - Undo/redo, snapshots, version history
  • Concurrent access - Multiple threads safely reading shared data without locks
  • Functional programming - Immutable data flow, pure functions
  • Building up collections incrementally - Each addition shares structure with previous version

❌ Use standard Python dict/list when:

  • You only need one mutable version
  • Maximum raw construction speed is critical
  • Extremely memory-constrained environments

Performance vs Python Standard Library

PersistentDict vs dict

Operation pypersistent Python dict Speedup
Structural Sharing (100 variants of 10K dict) 74µs 1.79ms 24x faster 🚀
Structural Sharing (100 variants of 1M dict) 158µs 517ms 3271x faster 🚀
Single lookup 776µs (1K ops) 427µs 1.8x slower
Construction (1M elements) 2.74s 299ms 9x slower

Key insight: Creating multiple versions through structural sharing is 24-3271x faster than copying dicts, with the advantage growing dramatically for larger collections.

PersistentList vs list

Operation pypersistent Python list Speedup
Structural Sharing (100 variants of 10K list) 74µs 1.79ms 24x faster 🚀
Append 100 elements 42µs 2.3µs 18x slower
Random access (100 ops) 13µs 2.7µs 5x slower

Key insight: If you need multiple versions (undo, history), PersistentList is dramatically faster.

Performance vs pyrsistent

pyrsistent is a mature pure-Python library with similar persistent data structures. pypersistent offers better performance through its C++ implementation, but with a smaller feature set.

PersistentDict Performance Comparison

Size Operation pypersistent (C++) pyrsistent (Python) Speedup
100K Merge (50K+50K) 563µs 98.9ms 176x faster 🚀
10K Merge (5K+5K) 155µs 9.12ms 59x faster 🚀
10K Lookup (1K ops) 157µs 476µs 3.0x faster
10K Update (100 ops) 64µs 287µs 4.5x faster
10K Construction 811µs 1.95ms 2.4x faster
10K Iteration 1.27ms 732µs 1.7x slower

Why the difference? pypersistent's C++ implementation provides:

  • Optimized tree traversal and node allocation
  • Cache-friendly memory layout
  • Specialized bulk merge algorithms
  • Direct memory manipulation without Python object overhead

Feature Comparison

Feature pypersistent pyrsistent
PersistentDict (pmap)
PersistentList (pvector)
PersistentSet (pset)
PersistentSortedDict ✅ (pbag)
PersistentArrayMap (small dicts)
PersistentBag (multiset)
PersistentDeque
PersistentRecord/Class
Evolvers (transient mutations)
Freeze/thaw (deep conversion)
Type checking integration

Summary: Choose pypersistent for performance-critical applications with the core data structures. Choose pyrsistent for a richer feature set and pure-Python portability.

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 dicts, use materialized list methods:

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

# Fast methods (1.7-3x faster for dicts < 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 dicts or early exit)
for k, v in m.items():   # Generator, O(log n) memory
    ...

Performance:

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

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

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:

PersistentDict - 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

PersistentSortedDict - 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

PersistentList - 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

PersistentSet - HAMT-based Set

Uses PersistentDict internally with:

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

PersistentArrayMap - Simple Array

Linear array for tiny dicts (< 8 entries):

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

Technical Details

Complexity:

  • PersistentDict/HashSet: O(log₃₂ n) ≈ 6 steps for 1M elements
  • PersistentSortedDict: O(log₂ n) for all operations
  • PersistentList: 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 PersistentDict

# Shared base dict
base_config = PersistentDict.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_dict.py -v
pytest test_persistent_sorted_dict.py -v
pytest test_persistent_list.py -v
pytest test_persistent_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.0b3.tar.gz (66.0 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.0b3-cp312-cp312-win_amd64.whl (180.4 kB view details)

Uploaded CPython 3.12Windows x86-64

pypersistent-2.0.0b3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (283.6 kB view details)

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

pypersistent-2.0.0b3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (262.1 kB view details)

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

pypersistent-2.0.0b3-cp312-cp312-macosx_11_0_arm64.whl (249.1 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypersistent-2.0.0b3-cp312-cp312-macosx_10_9_x86_64.whl (259.6 kB view details)

Uploaded CPython 3.12macOS 10.9+ x86-64

pypersistent-2.0.0b3-cp311-cp311-win_amd64.whl (180.2 kB view details)

Uploaded CPython 3.11Windows x86-64

pypersistent-2.0.0b3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (286.8 kB view details)

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

pypersistent-2.0.0b3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (266.2 kB view details)

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

pypersistent-2.0.0b3-cp311-cp311-macosx_11_0_arm64.whl (248.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypersistent-2.0.0b3-cp311-cp311-macosx_10_9_x86_64.whl (255.6 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

pypersistent-2.0.0b3-cp310-cp310-win_amd64.whl (179.6 kB view details)

Uploaded CPython 3.10Windows x86-64

pypersistent-2.0.0b3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (284.3 kB view details)

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

pypersistent-2.0.0b3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (263.9 kB view details)

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

pypersistent-2.0.0b3-cp310-cp310-macosx_11_0_arm64.whl (247.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypersistent-2.0.0b3-cp310-cp310-macosx_10_9_x86_64.whl (254.4 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: pypersistent-2.0.0b3.tar.gz
  • Upload date:
  • Size: 66.0 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.0b3.tar.gz
Algorithm Hash digest
SHA256 460109371b9de339b5a7f02b4e44861eb7df8dd7e08c4c762fdf56eeadb65743
MD5 25ec387c8ad27861d61e9e087d44cc4e
BLAKE2b-256 fd0cbff66a55f47428309bc745367d4beb24d9cbab5ac80ac8945e7f0e301e00

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 6c58d305d8a9c2aef0a9df11f9204d8a32b65675ff0d1894297829b94d3390ad
MD5 d09d0d3440be63063a12e62fe38b771b
BLAKE2b-256 f99abbff0154305aca1d91d6a95a8180a2d0a967a3cdc8f6cdaaa265f78fada6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8f11e3fd9e22dd4a6b67309bcae2f5234aec2d748d762a1385972a55546cda1e
MD5 166a43b876bea3f6b7589d71b25bc4c0
BLAKE2b-256 f7d3bba3e4a2e32bcf78a7ec3720fa994374ab73bcaae7d06e35657e037d4541

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 fcbda082cbb2bfd3664b808e962ac81de37d51443932c5f7283419016900fc2f
MD5 c8fcee1e4d7bfd1ce31e5e777cf6eebb
BLAKE2b-256 8d4b4445f94102ddbf7df4bdb615598249cc2cbb0a0934b6008e935f44845f75

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a469cc16c877a1c34891166c34d7613d1e41cab666d064236f5b41736e8a0929
MD5 57e211eb4ba05fe86f722941705422d4
BLAKE2b-256 759c813ee3cd84088da87652f10df720522b5da51ac653142e22869d12334fdb

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4fc9b8de57a2ea87d2f7e4be768f8b8a64e4a60ac461e1f171c25f8012899a70
MD5 3348c4283460bb09917b4bbacaac4fd4
BLAKE2b-256 4650b096a9107ea94d2265f76a9690682e3bad6e75586062e08b7d7a6fa7cc6d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 f497f9ed8eac8adbae40cb4547746a339031a9725c69878ce5f149bd3962e7b0
MD5 1c87b2be38af23fddd1aa8ddde21cd27
BLAKE2b-256 b566c76f33a2016483459f7deeed05dc8d405b4d3e9b826691377785349e706a

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 cd56866a84d41718a5ab5854db18d401ca07d3e1de52975a3ac452bb8e9d7c4d
MD5 236a949cbe76b7962f1170c6699a917b
BLAKE2b-256 2f188d5645ff1968dccd609cf1278379988dcfcfd439047e64f9aac1c15ef2c8

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c5ded25548c11f0a1bb1f76badefc72c9b902d795e2ae4e5a2cfbd03d51007d1
MD5 431ec5c97f9f14052bef011f583d9a1e
BLAKE2b-256 e2f53387cdea72e3b47c53aa953eca8656b59976519fb155be762f9950d88f8e

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 16f7ac9701b9537807c2e36e064b745a867988d6a10edfac91bb6e3deb27b203
MD5 6245e9ad0b6809d2b97cd8911d0521a8
BLAKE2b-256 d9188130fbb3f9f6ae6dc0fb0ff92206aece87075186b97e6a8d6132c36628f3

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 44031a00e43c59559f630d8cac8ce8b57b0f14b698520d144121efedffc6aed8
MD5 fb62a96fbca788a004c31de927dfc697
BLAKE2b-256 ccdc2be7132391a722cc59f24ad711f869f426d28fb7f5240964debe872a66a2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 c1fb7d0cb4fe904bd182a178978ec0beedb7663f4704cf3800d2acdfc3f218c2
MD5 4fecc9d2f0547837c7f9abb796ba4c90
BLAKE2b-256 28e03f1c67bf19a7454fd2026ff3439af0c5c9ea3f66e222e4318cf8bd0ee993

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 702c9e0698f26f48fa67c74d3400ece3ea3a357c6ef09ea2b2641ebf25657ddc
MD5 ce7370cb104207dd1cf78226ceda9e24
BLAKE2b-256 24991266b1449f7b477f8e7ce3aa52556313368aaceef4eef0b08029c1d0eedd

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 da1acb077dcd18a2717f22b4608dbf5127281284709e3cd19885ef3baeee7433
MD5 5a7b15546910840d3936516cf2ffe908
BLAKE2b-256 13cb296abe61b7269ce64866630ad3f1aac22c663dafbe57bcd08708423330e0

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 571c20d499611e16e5962585f5c7be84af55050fc523e8193815fa57d0564ff4
MD5 11b572bf58db127be31cbd83d4f64ce4
BLAKE2b-256 284e6ab29e7e0399e7b883da9a02342eebcaff10281fc06d1d82c32186005a77

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypersistent-2.0.0b3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3974ab9843f3081d58528f5c54df48449233842941c27cebc5fec17b44856b10
MD5 31d56caddc9e34c403f9f9fa966ba676
BLAKE2b-256 a4c83882e400a7ecc12b4582d7473652b2b0f420dfac2b3e16528efe52df72c2

See more details on using hashes here.

Provenance

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