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

Coverage by feature family across every binding, generated from coverage.json in lazily-spec. Legend: ✅ shipped · ~ partial · absent · not applicable. The canonical matrix with per-cell notes and platform carve-outs lives in lazily-spec § Cross-Language Coverage.

Summary — family × language

Family Rust Python Kotlin JS Dart Zig Go C++ C# GDScript
Reactive graph ~
Materialization
Family sync
Statecharts
Keyed collections ~
Reactive queue
Broadcast topic
Work queue
CRDT data types ~ ~ ~ ~ ~ ~ ~
Lossless tree
Egress ~ ~ ~ ~ ~ ~ ~ ~
Ingress
Wire codec ~
Transport & FFI ~ ~ ~
Message passing ~
Reliable sync ~ ~ ~ ~ ~ ~ ~ ~ ~
Distributed plane
Causal receipts ~
Security boundary
Membership
Coordination
Presence
Temporal
Rate shaping
Windowing
Resilience
Portable stdlib
Service plane
Instrumentation

Roll-up rule: a family cell is only when every required row in that family is ; ~ when the family is mixed (some shipped or partial); when no required row is shipped or partial; only when every required row in the family is not applicable. Rows the spec marks MAY (optional) are excluded from the roll-up — declining an optional feature is not a gap.

A family cell summarises 74 feature rows. For row-level marks, per-cell notes, and platform carve-outs see the canonical coverage matrix in lazily-spec.

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).
  • LatestDurableProjectionCore / LatestDurableProjection — keyed durable egress that converges each sink key to its latest desired epoch, permits one in-flight attempt per key, and generation-fences stale acknowledgements.
  • 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.

Latest-durable projection — lazily.latest_durable_projection

Use LatestDurableProjection when the durable side effect is a projection of current state (for example, saving the latest document image), rather than a command log where every intermediate value must execute. upsert_desired keeps only the newest pending epoch per key; claim allows at most one sink attempt per key; ack_applied and fail_retryable must match that attempt's generation and epoch. reconnect advances the sink generation and safely requeues claimed work, so a stale actor can never clear newer intent.

from lazily import LatestDurableProjection

projection = LatestDurableProjection[str, str]({}, generation=1)
projection.upsert_desired("document", epoch=41, value="latest text")
attempt = projection.claim("document", generation=1).envelope
assert attempt is not None

# Await the external write in the caller's driver, then acknowledge its exact
# token. A concurrent epoch 42 remains pending even when epoch 41 succeeds.
projection.ack_applied(attempt.key, attempt.generation, attempt.epoch)

The graph-agnostic LatestDurableProjectionCore and the reactive LatestDurableProjection, ThreadSafeLatestDurableProjection, and AsyncLatestDurableProjection shells implement the same contract. The async shell's transitions are intentionally synchronous; only the external sink driver awaits I/O. All three shells replay conformance/egress/latest_durable_projection.json from lazily-spec v0.38.0 and correspond to the corrected lazily-formal v0.38.1 model.

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.

Transport-agnostic reactive ingress — lazily.ingress

A client consuming a remote stream usually grows four accidental mechanisms: a refresh() loop that re-reads whether the connection is healthy, a hand-rolled "is this message still relevant?" check, a reconnect path that forgets what was already applied, and transport-shaped consumer code that disagrees with itself per transport. Every one of those is a derive being simulated with a call. IngressCell makes them derives, and makes the transport a value the primitive never touches.

An envelope carries its own provenance (generation / sequence / stamped_at), so a WebSocket frame, an RPC response, and a polled page are the same input once decoded. Admission applies a normative order — lifecycle → generation fence → freshness → generation handoff → dedupe → ordering → backpressure → merge — and each keyed scope exposes four independent reader kinds plus three receipt channels.

from lazily import IngressCell, IngressEnvelope, IngressPolicy, Sum

ctx: dict = {}
ingress = IngressCell[str, int](ctx, IngressPolicy(reorder_window=4), Sum)

ingress.admit(IngressEnvelope("alpha", 1, 0, 0, 5))
assert ingress.value("alpha") == 5
assert ingress.readiness("alpha") == "ready"     # a derive, not a poll

# Out of order: buffered, so nothing a reader can observe moved.
ingress.admit(IngressEnvelope("alpha", 1, 2, 0, 4))
assert ingress.value_is_valid("alpha")            # the value reader stays warm

# The delivery that closes the gap flushes the run as ONE coalesced window.
ingress.admit(IngressEnvelope("alpha", 1, 1, 0, 2))
assert ingress.value("alpha") == 11
assert ingress.drain("alpha") == 11               # an egress, never an ack
assert ingress.suspend("alpha").from_sequence == 3

ThreadSafeIngressCell and AsyncIngressCell are the other two flavors of the same contract; all three replay the canonical lazily-spec/conformance/ingress/*.json corpus. Nothing in the family is async-coloured — an admission decision is a function of the fence, the watermark, the reorder buffer, and the observed clock, so there is nothing to await. Awaiting belongs to the transport, and the transport is outside the primitive by construction.

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()

# The same frames over `msgpack`, the cross-language binary default: an
# externally tagged envelope over MessagePack maps keyed by the *json* field
# names. Map key order is encoder-defined, so conformance is a semantic round
# trip — `decode(encode(m)) == m` — never a golden byte string.
packed = IpcMessage.of_snapshot(snap).encode_msgpack()
assert IpcMessage.decode_msgpack(packed).snapshot == snap

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 — the same cell kernel, the same keyed collections and CRDTs, and the same lazily-spec wire protocol — so peers written in different languages talk to each other without a translation layer.

Repo Language
lazily-rs Rust — the reference implementation
lazily-py Python — you are here
lazily-go Go
lazily-kt Kotlin / JVM
lazily-js JavaScript / TypeScript
lazily-cs C# / .NET
lazily-cpp C++
lazily-zig Zig
lazily-dart Dart / Flutter
lazily-react React / Preact bindings layered over lazily-js (not a separate language binding)

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.

Per-binding parity, with per-cell notes and platform carve-outs, lives in lazily-spec § Cross-Language Coverage — it is generated from coverage.json, so it does not rot the way a hand-copied table would.

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.40.0.tar.gz (474.9 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.40.0-cp314-cp314-win_amd64.whl (386.9 kB view details)

Uploaded CPython 3.14Windows x86-64

lazily-0.40.0-cp314-cp314-musllinux_1_2_x86_64.whl (572.4 kB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

lazily-0.40.0-cp314-cp314-musllinux_1_2_aarch64.whl (575.4 kB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ ARM64

lazily-0.40.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (574.1 kB view details)

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

lazily-0.40.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (569.0 kB view details)

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

lazily-0.40.0-cp314-cp314-macosx_11_0_arm64.whl (423.7 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

lazily-0.40.0-cp314-cp314-macosx_10_15_x86_64.whl (431.1 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

lazily-0.40.0-cp313-cp313-win_amd64.whl (385.9 kB view details)

Uploaded CPython 3.13Windows x86-64

lazily-0.40.0-cp313-cp313-musllinux_1_2_x86_64.whl (571.6 kB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

lazily-0.40.0-cp313-cp313-musllinux_1_2_aarch64.whl (574.1 kB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ ARM64

lazily-0.40.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (573.4 kB view details)

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

lazily-0.40.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (566.9 kB view details)

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

lazily-0.40.0-cp313-cp313-macosx_11_0_arm64.whl (423.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

lazily-0.40.0-cp313-cp313-macosx_10_13_x86_64.whl (432.1 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

lazily-0.40.0-cp312-cp312-win_amd64.whl (385.3 kB view details)

Uploaded CPython 3.12Windows x86-64

lazily-0.40.0-cp312-cp312-musllinux_1_2_x86_64.whl (574.5 kB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

lazily-0.40.0-cp312-cp312-musllinux_1_2_aarch64.whl (577.4 kB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ ARM64

lazily-0.40.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (576.6 kB view details)

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

lazily-0.40.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (571.3 kB view details)

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

lazily-0.40.0-cp312-cp312-macosx_11_0_arm64.whl (424.5 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

lazily-0.40.0-cp312-cp312-macosx_10_13_x86_64.whl (433.3 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

File details

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

File metadata

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

File hashes

Hashes for lazily-0.40.0.tar.gz
Algorithm Hash digest
SHA256 00dfaa1091b806d822aa1d9a22bae3041fc048139e40c34c3e6cac70ba707bc7
MD5 d784508b3be4ffd4c091897c354f1a8f
BLAKE2b-256 5c2082b19b3eb099902645719c1b36ddb6694776bbb9eea4137af587b074fccd

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for lazily-0.40.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 895f81a83caa4053dc082648833fd03e67db60fd18ea564ec27cbcd3251bd2ad
MD5 da5ef673affec92a4dcc9c4851d6cba7
BLAKE2b-256 72dee7ca4f3112090209d4216b45e7e6889e5dbb35ee19fe81e7eda1767b2f22

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 72681eb4d702d9baf316d4da60405141ae0fee5ef95029dd54e6e6bbe024dd38
MD5 34891fb75ca4d29ff27f5ca06c5159ca
BLAKE2b-256 3521f6aa3b7f6fb3f206dc850e9221b7d39d99c62e740d632722df4d2985f8df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp314-cp314-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4d4c1adb934e8c06c5735cdd91e9f808fc8c94447ddaa47c817a824911cdc77c
MD5 05d16c3ef04124b59dcf2f1f6045d992
BLAKE2b-256 8269391e1a2e0804cf6acb0c38740c308060231d5717b7b5cdc40630b7dde376

See more details on using hashes here.

File details

Details for the file lazily-0.40.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.40.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 25eed4f122936eb84432616e936670933f21e92150ffb812060f8701b3552ea3
MD5 e0f1713642f1f01230413cafd091d66f
BLAKE2b-256 5c0dd19abb348ed4f50b06eda3aa14b570814d9e25611e604c5ddbde566f9ccb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 cb6a35c55da0eb7dc3df9e38d633cd4b17df5c7b44383bedf47971d8fce21350
MD5 82ef41ec292779fe836bf8c26df17a74
BLAKE2b-256 19259e3aa3a0da88de35c530c69c974d46c5314723ac011df0ebb036b812d4a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9710241fa22c8adcd20990a1872d5d120990adfea4d81caf43e565ab577b85d1
MD5 a9fe6553735b49c2be89cd29a8f361fd
BLAKE2b-256 45f7b6f042c59cf8a5bc8885a3eb5db179177bc8ad89262314ac3a625112e03a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 5ab6182628621ae06c328f229ee49d145606a59ab975807e7df7caa73b08d08a
MD5 ec9a49af940a4f152d5db56654466668
BLAKE2b-256 9e1af2b2c4df256111862813497576603fd15970f091204c62cd51377ab096d9

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for lazily-0.40.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 2669ee6da76bcfaab5166ab00f94d3e37bfa86f97abbd0b20a8fa84f684b69d0
MD5 3ae3c35ed9e54fe635949cd3e7bfbe10
BLAKE2b-256 339d0901d1ae12f5cf297b819d8cfb4d7d083d17c7d81b08d4abeaf79f4505c2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9d6fe860302f0be5c3cbf8d1a217ccb2881267af84f7e1ca05cd892c4247c54b
MD5 e2a42d52b85a79841e473512388bea87
BLAKE2b-256 a65072c28a8a8282d5e367738c1740fd39717c1713207f709a33d7fd657bde97

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp313-cp313-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 61b2124c151883da11dc92a8fb254a3737e2ed2122e79d290f6b2544ae31e7fd
MD5 440b35ddf3c6c5999d0c31c4784a1155
BLAKE2b-256 42143c4a6d876ea4df281424fd37988590be278455b0d384abdb1c3012af125b

See more details on using hashes here.

File details

Details for the file lazily-0.40.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.40.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4b2e89ae0104d07a67241ea9e7bd639c5f79bfa846619395f4831c4f396d6a82
MD5 278b38f55bb12b2c3238352dc70b94fb
BLAKE2b-256 fa6bd01eade4c0b552a24bb7c88dea2480beae3e36ee02c2ab9d8897a94afe2a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 37060efd8360bfafb9be68517a1975604ee8589cad908dee885e2d5252cd0701
MD5 7442088169b5f203f5bae3b803706003
BLAKE2b-256 22b6ef134fcd396b20c30fab2a18cad661b8743019cb7b9789e552bf93f3e87f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 36ef778383f5bfaea31daf54587d39549d3ca844b959a88a57448f360d4a093b
MD5 42ecbd472fdfe832d2340e5b41680852
BLAKE2b-256 db993c3c89205f752cc0522d4ed1fb859392e20324c1eda8675efaaead917efe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 ee69f2b71ec8221ab2dd5efcfb564911e51172dedea957d8fcfa282f8987aa28
MD5 e3d7900235b29deeff248235a1b80819
BLAKE2b-256 2dc3a1efef0bab5a8e188479adbc5c10543661f52041f160cc5f7012c522c9a0

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for lazily-0.40.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 c357f1c6cc87954252340580fa8b5a4cc6b0096b51c6d4c439d8ee81576cd535
MD5 a60e27bb921466fe7dfc237a77c030dc
BLAKE2b-256 cf32da6f25ea226d6d49c4660e671c07c0c7ead3a7ac51e09b12397ee792e47f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 49afdeae24dae12a244929bf684f4281ffe0ebf40ed97ec9949cafdc05e47007
MD5 1f0390c4f7fa4b04c52d301fe919a829
BLAKE2b-256 f9126f7e2d7beb079c8174a7fef614837aa22b0cc5c8f03652f5d5954437b04a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 469f471621fe1d27fe62355f292c5cd708efeff5ea0dab79f88f7f0963bde8f5
MD5 debdd1949bdb00ba3011fd8fa162dc63
BLAKE2b-256 04294a1d0a5881f03ba9b15a5a04100a2c51edee5e692230778bbd816e261f32

See more details on using hashes here.

File details

Details for the file lazily-0.40.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.40.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 6c383568fa88d911530d98cb53c70cd4c3b1d350c4835476b05a11b79ce371a6
MD5 feac6b96c2b8e8cbf37f4ff6007f4425
BLAKE2b-256 7789e771edc05a8b8d7ab8a282a95a71f7ac65e422f1d8e33a3e640f8570843b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1604cd7b81d844ab18d368ba681cb921b24954962b4fc100789c8b119b463bea
MD5 4bebc05eb7f304d16e916f63f42c1995
BLAKE2b-256 afb6301f121d1434040fce87b249a3a96ee43f4cdadd286a5bc12ff5a28fdf44

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6523427ee45abe6088e2d791616e233c9eadbe4118a1ae6dcbc844c61ea8342d
MD5 0bb364688b47dd043e3ed635a9ac4c33
BLAKE2b-256 dbb067b0c422c59387afeaee96df4a27626ab04a295fabed848c1996ae9b6c62

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for lazily-0.40.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 18cd56af16d7ec578902286a980db2442967052b75bf08ce8ffb8286ae42f954
MD5 68bf062619f76c43977ee035deafffeb
BLAKE2b-256 7239e6eb0f38956d751976b517ca21ef1259ce9b6e2fb417b4cb49849121819c

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.40.0 This release

22 files

0.39.0

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