Skip to main content

lazily

Lazy reactive primitives for Python — the Cell kernel (Source / Computed cells, plus Effect) with automatic dependency tracking and cache invalidation, plus the language-agnostic lazily-spec wire protocol for mirroring graph state across processes and languages.

PyPI

Overview

lazily is the Python port of the Cell kernel (#lzcellkernel): two value kinds — Source and Computed — plus the value-less Effect sink. Cell is the value-node concept; Source is its native writable handle.

  • Source — a value written from outside (set / merge); the writable kind. Construct with source / cell (native class Source, slot SourceSlot; Cell / CellSlot remain identity-preserving migration aliases). A MergeCell is a Source whose write folds under a non-KeepLatest policy (Cell ≡ Source(KeepLatest)).
  • Computed — a value computed from upstream, via a compute function. Construct with computed(ctx, f). Guarded by default and lazy by default.
  • Effect — a value-less sink outside the hierarchy; nothing can depend on it.

A Computed is lazy by default: dependents are marked dirty on invalidation but only recompute when accessed. When you need eager push-style semantics — recompute immediately, observe v1 → v2 with no unset window — make it eager: computed(ctx, f).eager(). Going eager attaches a scheduled puller Effect over the backing memo (eagerness is graph state — an _eager bit plus a side table — not a distinct type), so N writes inside one batch re-materialize the computed once, at the flush. Every cell is guarded — an equal recompute is suppressed by the PartialEq guard (matching TC39 Signal.Computed), so unchanged values never cascade downstream work. There is no unguarded derived mode: computed is the guarded derived constructor, and the former separate memo construction is retired.

Migration note (v2 Cell kernel, #lzcellkernel). The v1 value vocabulary is removed: Signal / signal / signal_def, formula / formula_def / FormulaCell, SourceCell / SourceCellSlot, and the .drive() / .undrive() / is_driven / is_active methods are gone. Use the v2 spelling instead — an eager Computed is computed(ctx, f).eager(); the lifecycle is .eager() / .lazy() / .is_eager(). The construction sugar cell / cell_def is deprecated in favour of source / source_def, and the derived-value slot decorator is deprecated in favour of the guarded computed (slot_def remains as the storage-sense factory). Python has no compile-time read/write split (see the design's §4): the split is a convention — a Source has set / merge, a Computed does not — not a runtime gate.

There is no dedicated Context class — a plain dict is the context, so the Rust reference's ctx.computed(f) is spelled computed(ctx, f) here. Slot is retained as the storage position that holds a node: a Slot uses itself as the dictionary key that caches its value, so any dict works as the reactive "world" (lazily-spec §5.0 "Slot-as-storage"). It is the Python analog of lazily-rs's surviving storage-sense Slot; construct it directly with Slot(callable=…) when a raw storage node is genuinely needed.

Feature coverage

The full lazily capability set across every binding. Legend: ✅ shipped · ~ partial · absent or not applicable. The canonical matrix with per-cell notes and platform carve-outs lives in lazily-spec § Cross-Language Coverage.

Feature Rust Python Kotlin JS Dart Zig Go C++ C#
Reactive graph — two cell kinds (nodes SourceCell / ComputedCell; handles Source<T, M> / Computed<T>) + Effect sink + eager Computed (computed().eager()) / all cells guarded / batch
Keyed-map materialization (ComputedMap) — mint-on-access derived slots: transparency + deferral (#lzmatmode)
Thread-safe keyed map (ThreadSafeComputedMap) — Send + Sync + materialization confluence (#lzmatmode)
Async keyed map (AsyncComputedMap) — eventual transparency (#lzmatmode)
Keyed-map sync — membership propagation + materialize-on-ingest + derived-aggregate transparency (#lzfamilysync)
Thread-safe context (lock-backed)
Async reactive context
Flat state machine
Harel state charts
Keyed reactive maps (ReactiveMap: SourceMap / ComputedMap) + SourceTree + reconcile
ReactiveMap Core surface — single-threaded flavor (cell-model.md § Core surface vs. binding extensions) ~
ReactiveMap Core surface — thread-safe flavor (ordering + membership reactivity)
ReactiveMap Core surface — async flavor (ordering + membership reactivity)
Atomic ordered move replayed against all three flavors (cellmap_atomic_move + cellmap_independence)
Memoized semantic tree (SemTree)
Stable-id alignment (manufactured identity)
Reactive queue (QueueCell SPSC/MPSC + QueueStorage adapter) Core surface — single-threaded flavor ~ ~
Reactive queue (QueueCell SPSC/MPSC + QueueStorage adapter) Core surface — thread-safe flavor (reader kinds + closure lifecycle)
Reactive queue (QueueCell SPSC/MPSC + QueueStorage adapter) Core surface — async flavor (reader kinds + eventual transparency)
Broadcast topic (TopicCell) Core surface — single-threaded flavor — independent cursors + durable replay + safe GC (#lztopiccell) ~ ~
Broadcast topic (TopicCell) Core surface — thread-safe flavor (reader kinds + closure lifecycle)
Broadcast topic (TopicCell) Core surface — async flavor (reader kinds + eventual transparency)
Competing-consumer work queue (WorkQueueCell) Core surface — single-threaded flavor — exclusive leases + ack/nack + redelivery + DLQ (#lzworkqueue) ~ ~
Competing-consumer work queue (WorkQueueCell) Core surface — thread-safe flavor (reader kinds + closure lifecycle)
Competing-consumer work queue (WorkQueueCell) Core surface — async flavor (reader kinds + eventual transparency)
Merge algebra + Source<T, M> — associative MergePolicy (KeepLatest/Sum/Max/SetUnion/RawFifo), Cell ≡ Source<KeepLatest>, read-any-cell/write-Source split (#relaycell)
RelayCell — conflating relay + BackpressurePolicy + SpillStore + Transport + Inbox/Outbox + Rate/Window/Expiry/Priority/keyed policies (#relaycell)
Free-text character CRDT (TextCrdt)
TextCrdt delta sync (version_vector / delta_since / apply_delta)
CrdtTree lossless document contract (#lzcrdttree)
Move-aware sequence CRDT (SeqCrdt)
Lossless tree CRDT core (LosslessTreeCrdt, M1)
Lossless tree — dotted-frontier anti-entropy
Lossless tree — concurrent merge convergence
Registers (LWW / MV) + PnCounter + CellCrdt
IPC wire — Snapshot + Delta + CrdtSync
Shared-memory blob path (ShmBlobArena)
Cross-process zero-copy transport (BlobBackend / shm / arrow)
Distributed CRDT plane (CrdtPlaneRuntime / anti-entropy)
Reliable sync — resync coordinator + at-least-once durable outbox + OR-set/LWW liveness (#lzsync)
Storage-independent durable outbox (OutboxStore + shared outbox protocol; SQLite/Room/IndexedDB/file adapters)
Reliable-sync transport seam + full-duplex SyncDriver loop (IpcSink/IpcSource, #sync-driver)
Distributed plane — WebRTC transport + signaling
State projection / mirror
Causal receipts (CausalReceipts outcome projection)
Message-passing + RPC command plane (command-plane-v1)
C-ABI FFI boundary
Permission boundary (PeerPermissions / RemoteOp)
Capability negotiation (SessionHandshake)
Instrumentation / benchmarks
Temporal sources — TimerCell / IntervalCell / CronCell / DeadlineCell over a logical clock (#lztime)
Rate-shaping operators — DebounceCell / ThrottleCell / SampleCell / ProbabilisticSampleCell (#lzrateshape)
Membership + failure detection — MembershipCell (SWIM + Phi-accrual) / PeerSet / PeerChangeEvent (#lzmemb)
Distributed coordination — LeaseCell / LeaderCell / LockCell / SemaphoreCell / BarrierCell+QuorumCell (#lzcoord)
Presence + ephemeral plane — PresenceCell / AwarenessCell / EphemeralCell + Ephemeral/Durable markers (#lzpresence)
Stream windowing — TumblingWindow / SlidingWindow / SessionWindow over the merge algebra (#lzwindow)
Fault tolerance — CircuitBreakerCell / RetryPolicyCell / BulkheadCell / TimeoutCell (#lzresilience)
Portable stdlib Timer (stdlib_timer_v1) — canonical fixture + mutation-gate verified
Portable stdlib caller-driven Timeout<T> (stdlib_timeout_v1) — distinct from reactive TimeoutCell
Portable stdlib RevisionBarrier (stdlib_revision_barrier_v1) — register/recheck lost-wakeup guard
Embedded-service plane — HealthCell / ReadinessCell / DiscoveryCell / ServiceRegistry (#lzservice)

Installation

pip install lazily

Example usage

from lazily import SourceSlot, source, slot

# Sources hold a value that can be updated.
name = SourceSlot[dict, dict, str]()


# Slots are functions that depend on sources and other slots.
@slot
def greeting(ctx: dict) -> str:
    print("Calculating greeting...")
    return f"Hello, {name(ctx).value}!"


# A SourceSlot can also have a default value.
@source
def response(ctx: dict) -> str:
    return "How are you?"


@slot
def greeting_and_response(ctx: dict) -> str:
    print("Calculating greeting_and_response...")
    return f"{greeting(ctx)} {response(ctx).value}"


ctx = {}

name(ctx).value = "World"

# First access: runs the function
print(greeting(ctx))
# Calculating greeting...
# 'Hello, World!'

# Second access: uses cache (no print)
print(greeting(ctx))
# 'Hello, World!'

# Dependencies also access cached values
print(greeting_and_response(ctx))
# Calculating greeting_and_response...
# 'Hello, World! How are you?'

# Dependencies also cached
print(greeting_and_response(ctx))
# 'Hello, World! How are you?'

# Update cell: invalidates cache
name(ctx).value = "Lazily"

# Access again: re-runs the function
print(greeting_and_response(ctx))
# Calculating greeting_and_response...
# Calculating greeting...
# 'Hello, Lazily! How are you?'

# Another access: uses cache
print(greeting_and_response(ctx))
# 'Hello, Lazily! How are you?'

Core Concepts

Context

A plain dict is the context. It owns all cached Slot values; Slots store their cache under themselves as keys. The current implementation is single-threaded — create one dict per reactive graph.

Slot

A Slot wraps a compute function (ctx) -> T; the result is cached after first access. Dependencies are discovered automatically via a global slot_stack — any Slot or Cell read during computation becomes a dependency and re-subscribes on every recompute, so conditional branches update the dependency graph with no manual cleanup. When a dependency invalidates, the Slot only marks its cache dirty; it does not recompute until called again.

Type Purpose
BaseSlot[C_in, C_ctx, T] Base slot without subscriber support
Slot[C_in, C_ctx, T] Storage-sense slot with dependency tracking and invalidation
slot Deprecated — use computed (guarded) or Slot(callable=…) (storage)
slot_def(resolve_ctx) Storage-sense decorator factory for a custom context resolver

Source cell

A Source cell holds a mutable value. Reading cell.value inside a Computed or Effect auto-subscribes that reader; assigning cell.value = x (or cell.set(x)) compares old and new via != and, only if changed, cascades invalidation to dependents. Construct with source (the v1 cell name is deprecated).

Type Purpose
Source[T] (Cell[T] migration alias) Mutable source value with subscription support
SourceSlot[C_in, C_ctx, T] (CellSlot migration alias) Slot that returns a Source cell
source Decorator: SourceSlot with an identity resolver (canonical)
source_def(resolve_ctx) Decorator factory for a custom context resolver
cell / cell_def Deprecated v1 aliases of source / source_def

Eager Computed

An eager Computedcomputed(ctx, f).eager() — is the counterpart to a lazy Computed. Where a lazy cell marks itself dirty on invalidation and recomputes on the next read, an eager one recomputes the instant a dependency is invalidated, before the mutating call returns. The value is always materialized, so observers never see an intermediate unset value.

from lazily import SourceSlot, computed

n = SourceSlot[dict, dict, int]()

ctx: dict = {}
n(ctx).value = 1

doubled = computed(ctx, lambda c: n(c).value * 2).eager()  # eager: materialized now
print(doubled.value)   # 2

n(ctx).value = 5       # doubled recomputes immediately
print(doubled.value)   # 10 — already current, no lazy read needed

An eager Computed is composed from existing primitives, not a parallel engine: a memoized backing Slot supplies glitch-free, guarded recomputation, and a small puller Effect re-materializes it after every invalidation to supply the eagerness. It inherits the guard (an equal recompute suppresses the downstream cascade). .lazy() (or .dispose()) removes the eager puller — the value stays readable but reverts to lazy (recompute-on-read) behavior.

Method Purpose
computed(ctx, f) Lazy, guarded derived value bound to a context
computed(ctx, f).eager() The eager form (idempotent; returns the same handle)
.lazy() / .is_eager() Revert to lazy / query eagerness
computed_def(resolve_ctx) Decorator factory for a context-cached lazy Computed

StateMachine

StateMachine[S, E] is a finite state machine backed by a reactive Cell, so its state participates in dependency tracking like any other reactive value. Construct it with StateMachine(ctx, initial, transition) where transition is a pure (state, event) -> next_state | None (returning None rejects the event). send(event) returns whether the transition was accepted; a self-transition to an equal state is accepted but suppressed by the Cell's PartialEq guard.

Reactive collections, async, and thread-safe contexts

lazily-py also implements the lazily-spec compute-layer MUSTs, each ported from its Lean formal model in lazily-formal:

  • ReactiveMap / SourceMap / ComputedMap / SourceTree — keyed reactive collections (#reactivemap) with independent value/membership/order signals and atomic move. One generic ReactiveMap over a handle kind; SourceMap (input cells, adds set + eager entry) and ComputedMap (derived slots, lazy get_or_insert_with + eager materialize_all) are its specializations.
  • QueueCell — a reactive FIFO queue (SPSC primitive with an MPSC-via-batch usage rule) with a pluggable QueueStorage backend. Reader-kind invalidation (head/len/is_empty/is_full/closed), bounded reactive backpressure via is_full, and the closure lifecycle (drain / Closed-distinct-from-Empty / idempotent).
  • reconcile_ops — move-minimized keyed reconciliation (LIS kernel).
  • AsyncSlot / AsyncEffect — the async slot lifecycle with stale-completion discard, and cleanup-before-body effect scheduling.
  • ThreadSafeContext — a lock-serialized batch boundary that coalesces writes into one invalidation pass.
  • lazily.ffi — the C-ABI FFI boundary (LazilyFfiStatus, LazilyFfiMessageKind incl. CrdtSync = 3, LazilyFfiBytes).

The test suite gates on lazily-formal's lake build (every theorem checks) and mirrors the named Lean theorems as property tests. See SPEC.md for the full compliance surface.

Reactive queue — lazily.queue

QueueCell is a FIFO collection composed of reactive cells — not a new cell kind — that adds queue semantics (push to tail, pop from head) to the reactive graph. ThreadSafeQueueCell and AsyncQueueCell carry the same Core surface; the topic and work-queue families likewise ship ThreadSafe* and Async* shells. Nothing in the async family is async-coloured: storage reads, cursor advances, and lease decisions return plain values.

The reactive shell wraps a pluggable QueueStorage backend (default VecDequeStorage) and owns demand-driven reader-kind handles. It invalidates exactly the handles whose values changed — a push to a non-empty queue does NOT invalidate the head reader, while a pop does. Thread-safe shells serialize their whole public operation through a ThreadSafeContext; the same canonical fixture corpus and invalidation matrices replay against all three flavors.

from lazily import QueueCell, QueuePopError, batch

ctx = {}
q: QueueCell[str] = QueueCell(ctx)

q.try_push("a")
q.try_push("b")
assert q.head() == "a"
assert q.len() == 2
assert q.try_pop() == "a"

# Bounded queue → reactive backpressure via is_full.
bq = QueueCell[int].with_capacity(ctx, 2)
bq.try_push(1)
bq.try_push(2)
assert bq.is_full()
assert bq.try_push(3).label == "Full"   # reject at capacity
assert bq.try_pop() == 1
assert not bq.is_full()                  # pop freed a slot → is_full reader invalidated

# MPSC: multiple producers push inside one batch → one invalidation pass.
batch(lambda: (q.try_push("p1"), q.try_push("p2")))

# Closure: pop on closed+empty returns Closed (distinct from Empty).
q.close()
assert q.is_closed()
assert q.try_push("x").label == "Closed"

Competing-consumer work queue

WorkQueueCell provides exclusive FIFO claims with visibility deadlines, worker-scoped acknowledgements, tail retries, and bounded dead-letter handling. Item ids survive retries while each claim gets a fresh delivery id.

from lazily import WorkQueueCell

work = WorkQueueCell[str](ctx, visibility_timeout=10, max_deliveries=3)
work.push("job")
delivery = work.claim("worker-a", 100)
assert delivery is not None
assert work.ack("worker-a", delivery.delivery_id)

The reader-kind independence law is explicit: every successful operation derives its changed-reader set from the before/after state and resets those memoized handles in one batch. Unchanged reader kinds remain warm.

IPC — the lazily-spec wire protocol

lazily.ipc implements the language-agnostic lazily-spec wire protocol, so a Python graph's state can be mirrored to remote observers across processes and languages. The JSON encoding is byte-compatible with the Rust (lazily-rs), Zig (lazily-zig), and TypeScript (@lazily/signaling) bindings, and is validated against the canonical lazily-spec/conformance fixtures (vendored under tests/conformance/).

Two message kinds flow over any transport (WebSocket text, WebRTC data, FFI buffer):

  • Snapshot — the full graph state at an epoch (nodes, edges, roots).
  • Delta — an ordered batch of the 7 DeltaOp variants (CellSet, SlotValue, Invalidate, NodeAdd, NodeRemove, EdgeAdd, EdgeRemove) applied with epoch sequencing and fail-closed resync.
from lazily import (
    Snapshot, NodeSnapshot, EdgeSnapshot, ShmBlobRef,
    Delta, DeltaOp, IpcMessage,
)

# Build and serialize a snapshot — encode_json() returns transport-agnostic bytes.
snap = Snapshot(
    epoch=7,
    nodes=[
        NodeSnapshot.payload(1, "i32", bytes([1, 2, 3])),
        NodeSnapshot.opaque(2, "opaque-type"),
        NodeSnapshot.shared_blob(3, "text/plain", ShmBlobRef(0, 16, 1, 7, 999)),
    ],
    edges=[EdgeSnapshot(2, 1), EdgeSnapshot(3, 1)],
    roots=[1, 2],
)
wire = IpcMessage.of_snapshot(snap).encode_json()
assert IpcMessage.decode_json(wire).snapshot == snap

# An incremental delta carrying mutations.
delta = Delta.next(40, [
    DeltaOp.cell_set(1, bytes([10])),
    DeltaOp.invalidate(3),
])
IpcMessage.of_delta(delta).encode_json()

A PeerPermissions boundary gates what is shared: it is default-deny, so only nodes a peer is explicitly allowed to read are serialized into a snapshot or delta — non-allowlisted nodes are omitted entirely.

Shared-memory blobs — ShmBlobArena

ShmBlobArena lets a Python process host blob payloads (not just carry ShmBlobRef descriptors). It is a bytearray-backed, append-only arena with a 40-byte header (LZSH magic + FNV-1a-64 checksum) and wraparound, ported from the lazily-rs ShmBlobArena<B> and byte-compatible with the Rust and Zig arenas. The module exports ShmBlobArena, ShmBlobArenaError (with its variant subclasses), and SHM_BLOB_HEADER_LEN.

Lossless tree CRDT — lazily.lossless_tree_crdt

LosslessTreeCrdt (#lzlosstree) is a single rooted concrete-syntax tree whose leaves own every rendered byterender(tree) == source_text for valid, invalid, and unknown source alike. Where TextCrdt is a flat lossless floor, this is the structured tree that can itself be the wire authority. Element nodes own structure only; all text lives in leaf nodes tagged Token / Trivia / Raw / Error, so unknown/invalid spans round-trip exactly as Raw/Error leaves rather than being discarded.

from lazily import LeafKind, LosslessTreeCrdt, SeedElement, SeedLeaf
from lazily.lossless_tree_crdt import ROOT

tree = LosslessTreeCrdt(peer=1)
heading = tree.create_node(ROOT, None, SeedElement("heading"))
tree.create_node(heading, None, SeedLeaf(LeafKind.TOKEN, "# "))
title = tree.create_node(heading, None, SeedLeaf(LeafKind.RAW, "Título"))
assert tree.render() == "# Título"

# Op-based delta sync: fork, diverge, converge through a dotted frontier.
other = tree.fork(peer=2)
other.edit_leaf(title, 0, 0, "X")
tree.apply_update(other.diff(tree.frontier()))
assert tree.render() == other.render()

Leaf text embeds TextCrdt wholesale; child order is a fractional index (key_between); the clock is a Lamport TreeOpId. Anti-entropy is op-based over a dotted, non-contiguous version frontier (TreeVersionFrontier) — a dot set (contiguous prefix + sparse holes), never a per-peer max, so a missing interior op stays representable and re-requestable. Leaf-local wire offsets are UTF-8 bytes (byte_to_char). The wire codec (tree_update_to_wire / tree_update_from_wire) validates against lazily-spec's lossless-tree-delta.json, and all nine conformance/lossless-tree/ fixtures replay.

Command / RPC message plane — lazily.command

command-plane-v1 is an additive sibling to Snapshot / Delta / CrdtSync: four evented frames (CommandSubmit / CommandCancel / CommandEvents / CommandProjection) that carry command traffic, not cell state. lazily owns the envelope; the namespace owns the IpcValue payload, which lazily never decodes.

The single hard rule: terminal authority is the causal receipt. A command is terminal only when a terminal CausalReceipt for its command_id folds in (applied, or rejected — including the cancelled / superseded / timed_out reasons). observed / accepted / started events are progress only; a transport ACK is never terminal.

from lazily import (
    CommandPolicy, CommandRpcClient, CommandSubmit, DedupePolicy,
    applied_receipt,
)
from lazily.ipc import IpcValue

class Transport:
    def __init__(self):
        self.sent = []

    def send(self, message):
        self.sent.append(message)

client = CommandRpcClient(Transport())
cmd_id = client.submit(CommandSubmit(
    command_id="cmd-1", causation_id="cmd-1", source="plugin",
    target="controller", namespace="agent-doc", name="editor_route",
    authority_generation=1, idempotency_key="doc:run", deadline_ms=0,
    policy=CommandPolicy(DedupePolicy.SAME_IDEMPOTENCY_KEY, False, True),
    payload_type="agent-doc.editor_route.v1", payload_hash="sha256:…",
    payload=IpcValue.of(b"{…}"),
    required_features=["command-plane-v1"],
))
# `call` resolves ONLY on a terminal receipt — never an ACK or `accepted`.
client.ingest_receipt(applied_receipt("rcpt-1", cmd_id, "controller", 1))
assert client.poll_call(cmd_id).kind.value == "resolved"

CommandProjection is the pure reducer (generation guards, idempotency, cancel-before-terminal-only, terminal-conflict-fails-closed, reconnect equivalence); CommandRpcClient is the derived RPC facade. The wire codec validates against lazily-spec's message-passing.json, and all eight conformance/message-passing/ fixtures replay.

Benchmarks

Wall-clock benchmarks live in BENCHMARKS.md, covering both the in-library micro-suite (reactive core, keyed reconciliation, SourceMap, TextCrdt, CRDT plane) and a large spreadsheet-shaped scale suite that mirrors the lazily-rs / lazily-go scale groups (N input cells + N formula slots, formula[i] = input[i] + input[i-1]). The scale suite is measured up to a full 10,000,000-cell Google Sheets workbook (N = 5,000,000); a one-cell edit plus a 1,000-cell viewport read stays in the ~75 µs range regardless of sheet size, because the lazy pull model recomputes only the ~2 formulas that read the edited input.

make bench          # micro-suite
make bench-scale    # scale suite (default N = 1,000,000)

# or directly, with a custom size:
uv run python -m lazily.benchmarks
LAZILY_SCALE_N=5000000 uv run python -m lazily.scale_bench   # 10M-cell workbook

See BENCHMARKS.md for the full results, hardware, and honest notes on CPython's per-node overhead.

The lazily family

lazily-py is one binding in a cross-language reactive family that shares the lazily-spec wire protocol:

Binding Language Package
lazily-rs Rust lazily (crates.io)
lazily-py Python lazily (PyPI)
lazily-zig Zig GitHub
@lazily/signaling TypeScript / Cloudflare Worker npm
lazily-spec wire protocol + conformance fixtures
lazily-formal Lean 4 formal model (FSM kernel + Harel state chart)

See lazily-spec for the canonical Snapshot/Delta schemas, the IPC Lean proofs of the epoch/memo/batch invariants, and the conformance fixtures every IPC-capable binding validates against. The language-agnostic formal model — the flat FSM kernel and the full Harel state chart — lives in lazily-formal.

Development

This project uses uv. Run the local CI-equivalent suite — type-check (ty), lint (ruff), the runnable README example, and the test suite — with:

uv run poe precommit

SPEC.md is the authoritative specification for the Python primitives and the lazily-spec compliance notes.

Download files

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

Source Distribution

lazily-0.39.0.tar.gz (368.2 kB view details)

Uploaded Source

Built Distributions

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

lazily-0.39.0-cp314-cp314-win_amd64.whl (351.2 kB view details)

Uploaded CPython 3.14Windows x86-64

lazily-0.39.0-cp314-cp314-musllinux_1_2_x86_64.whl (536.9 kB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

lazily-0.39.0-cp314-cp314-musllinux_1_2_aarch64.whl (540.1 kB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ ARM64

lazily-0.39.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (538.7 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

lazily-0.39.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (533.5 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

lazily-0.39.0-cp314-cp314-macosx_11_0_arm64.whl (388.4 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

lazily-0.39.0-cp314-cp314-macosx_10_15_x86_64.whl (395.6 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

lazily-0.39.0-cp313-cp313-win_amd64.whl (350.2 kB view details)

Uploaded CPython 3.13Windows x86-64

lazily-0.39.0-cp313-cp313-musllinux_1_2_x86_64.whl (536.2 kB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

lazily-0.39.0-cp313-cp313-musllinux_1_2_aarch64.whl (538.8 kB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ ARM64

lazily-0.39.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (537.9 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

lazily-0.39.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (531.4 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

lazily-0.39.0-cp313-cp313-macosx_11_0_arm64.whl (388.6 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

lazily-0.39.0-cp313-cp313-macosx_10_13_x86_64.whl (396.6 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

lazily-0.39.0-cp312-cp312-win_amd64.whl (349.6 kB view details)

Uploaded CPython 3.12Windows x86-64

lazily-0.39.0-cp312-cp312-musllinux_1_2_x86_64.whl (539.2 kB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

lazily-0.39.0-cp312-cp312-musllinux_1_2_aarch64.whl (542.0 kB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ ARM64

lazily-0.39.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (541.2 kB view details)

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

lazily-0.39.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (535.9 kB view details)

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

lazily-0.39.0-cp312-cp312-macosx_11_0_arm64.whl (389.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

lazily-0.39.0-cp312-cp312-macosx_10_13_x86_64.whl (397.9 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

File details

Details for the file lazily-0.39.0.tar.gz.

File metadata

  • Download URL: lazily-0.39.0.tar.gz
  • Upload date:
  • Size: 368.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for lazily-0.39.0.tar.gz
Algorithm Hash digest
SHA256 3897bba36e8e3eb721286e5127b255d2c8ddb74355e73ad691186b2372b7228b
MD5 6e2f7e0e221734861e90a865b29174b7
BLAKE2b-256 44eb1568a6d9790f3da11289709792108b9e29727db7c5b8a282a7a009243129

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: lazily-0.39.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 351.2 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for lazily-0.39.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 4c47e3b44a373dadfceba0bdcc6725d3caeaaaeb7393d80dfd8a88286cd1715f
MD5 10f3c11987aae7b6e819330d0ae0759e
BLAKE2b-256 094c453352cbac03bb1177b13747e875f9a75acff27fa9f61cd48a9fbcacbd2b

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 40d139044b1cad600d8031f60711c3a8855ef6b5ed329fe1887ae6106522d7d9
MD5 b68c132c8f4771871fd9d420ec0247ba
BLAKE2b-256 ab7a1dc3ff33758d6a1eec5f222fe7ff34e829f26793a1dcf7125b12bbd116e7

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp314-cp314-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0f17ff5a38110be6495a009d1df61c367b8ea0ae55a1af2cf5b6536c9e8f9bda
MD5 c13fc985f92791519448a2c2d5c08b5e
BLAKE2b-256 12d845a7989e2defc0fef9fcd79405184a5ddd2a54f082d91ee8dc651f2be456

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9484737c7ad0c804e59fe1603e7984a2acf8d21ca32401b6b2b1c46d04624f0f
MD5 8888866f1b44eb8266356a338fe7b20a
BLAKE2b-256 2317ffb82f02a0d313414996710b99b3d138f93fb72e0ed277b0b8178b5662ab

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b47c972c07e8cf6137f8fdcf37d85a5bebb646b7b8ea62abec84898281dfb5e9
MD5 3473d8329ce35c3a4c524492774d1ae5
BLAKE2b-256 1709cb20ea79571a8b959dd7f8984e1867e9b9ad5307f13910ce6cfa0dde3702

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c8a68ef89d0a54dec729944a594d12278e098c579ded6867ae4cfe5473af9d9c
MD5 ffe468b570846321eae487e37dfe2003
BLAKE2b-256 234b7cae18991bf44d83c1d5b30eb0a6d325a7e16b497a4665a52c1da42478c4

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp314-cp314-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 f6afa5fe4a71454a724f1a0a2b6aaaf302074810b9bc4f29fae728fa5c61246c
MD5 526bfd03763a4b45e32308eb97e47753
BLAKE2b-256 f8b23341a0500a01e9cc492ac558f7f1bfb27cad5a49dad4ac6e89a2b3a40374

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: lazily-0.39.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 350.2 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for lazily-0.39.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 ca61c6ca6632b278ed6c0ad42fce2c2bf7819fb14666b11f6ee994fb826991dc
MD5 ac8dbabda41c76e78324896a29ae842e
BLAKE2b-256 e3cabb04835917e45c4794986bad7ec3bc0357f295e003998dcde806c3f409f4

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1ad161f4a7f575f610436f80552145f18b55d52c314632870dcb1372fe1aa9a6
MD5 187ec7e05e320b9d5d8eb31bc6fa941a
BLAKE2b-256 08af0d1ca7c59fde38ece9ef8fb6c52b5e63735d1f5a8caa764f938a6705f0c3

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp313-cp313-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c62e2d55f3bc54285e358e4fc0b2400e839c49f9a2d25b8eed42997bac80b12a
MD5 24c3a7dd2b5fc71600098cfa47ae0f95
BLAKE2b-256 029ee78e35d3426c3dc687661abdc430635298bdc0d75b33522a6579634bcb39

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 eafb1e7325b2c0690ded84492ee3978a362b944b99cc572fc746552a3a5691f9
MD5 6670f9ac520ad3e0afc13cbb2f010a9f
BLAKE2b-256 cdb937c0f09cdee18297d41cfaefe292708766eca03d35584bc1a9e562e266a9

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 305810a36f1da699523b48044797103824697e32ea133aebf83121707e2caaf7
MD5 d28c51ad72f4b62b41385d0e058aec5a
BLAKE2b-256 dafe8a5f346255dbfb9eaf99462d3ad6ee31db17015497d38e5f423e8d650e32

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1560a4ad85676b142d4c8c38239ffc40ea495fe343a8bb4d9d1e55d7e52a39e0
MD5 5c43dfe54fd1fd72dc93e2c24d56dcbc
BLAKE2b-256 9c55db36ec48e2985436f117812cb0f37f5dd38ca2a0b96ce223fd752b914bab

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 3bad0b113b6d8f39e9d89118955588a6b9906ebf71073709660149d60b436c24
MD5 e07f18719f57b581cea77ef7aab29e4c
BLAKE2b-256 a2517d4cf3eeb4156012cedbb311ec8022cb0183c66473bfc86e498a6f648d90

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: lazily-0.39.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 349.6 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for lazily-0.39.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 ffceb83fb43d96db88cdccdbde4e7f63869c31fbfa3239162bac5465ccda2385
MD5 450b2811e543e615a7f79ac1f8f9ae9b
BLAKE2b-256 094deeccd335ef43c53c6998004dc0a7fafb86555c98da66dd297b906fda5661

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3d295b1a5e311b3166e7bfbef4050a89a96967bde12b93d3dec3fe1c60f6e138
MD5 72a55a1feab2c535e3012c44497e0aa4
BLAKE2b-256 35afede6974b99b811e0a70d0da7864a187b59c9cffadcd321adb49d036bd6b0

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a2d00196dd6d0273d8a1493fa29fdd367004201ec4cf2a9e5952b28df00e542d
MD5 40988537bf69b2b9a97b0827eca4b2e2
BLAKE2b-256 7ad38222d87654527445af58b7da0ea68b18112b1789438509d6aefa63f2f0c1

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f438ad890dde6310766dbfb3e1cfe20307f6cd23ef40f2a50717cbff607fb3f1
MD5 fec1d43d71a9dc174b477cd723f48573
BLAKE2b-256 8e3d30102ba9437a71e7bf727f01222eb2108f1ef5b08c4e323f1db150b8adad

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b00490322ff1aadfc26e4ee087eeb2de9314d66ae73547108670c8e4553dec9d
MD5 a470d2401ae0b67b919b2591f087b5e8
BLAKE2b-256 5c02f79928b7792ccb2f7d91abffbb4972af6e4ba7b30aa92ff94499ec93eb98

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8aa664548bfcbddc8ed2bcf05cf5068ec04511ece84d40b4de48970f1a750f04
MD5 354a3b398a3dab7448c917a2e13c1e68
BLAKE2b-256 81428a179c41575f92730d0747cc1643cb9cb46040def0f56106541f2b08759c

See more details on using hashes here.

File details

Details for the file lazily-0.39.0-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for lazily-0.39.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 9b5f9f3e4e12e29e7baafeb859524d0a90aa7f6b051543d6a109152e29d0c7b1
MD5 78a6385a3c3ec515ad41746ffa1910c4
BLAKE2b-256 d1fb840a7837cfe6b49dcdbbd7325ce10d0029c96ae65f50634f5536821bb408

See more details on using hashes here.

Release history Release notifications | RSS feed

0.40.0

22 files

This release

0.39.0 This release

22 files

0.38.0

22 files

0.37.1

22 files

0.37.0

22 files

0.36.0

22 files

0.35.0

22 files

0.34.0

22 files

0.33.0

22 files

0.32.0

22 files

0.31.2

22 files

0.31.1

22 files

0.31.0

8 files

0.30.1

2 files

0.30.0

2 files

0.29.0

2 files

0.27.0

2 files

0.26.0

2 files

0.25.0

2 files

0.24.0

2 files

0.23.0

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.0

2 files

0.11.1

2 files

0.11.0

2 files

0.10.2

2 files

0.10.1

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.1

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page