Skip to main content

Frontrun

A library for deterministic concurrency testing.

pip install frontrun

Overview

Frontrun is named after the insider trading crime where someone uses insider information to make a timed trade for maximum profit. The principle is the same here, except you use insider information about event ordering for maximum concurrency bugs.

The core problem: race conditions are hard to test because they depend on timing. A test that passes 95% of the time is worse than a test that always fails, because it breeds false confidence. Frontrun replaces timing-dependent thread interleaving with deterministic scheduling, so race conditions either always happen or never happen.

Four approaches, in order of decreasing interpretability:

  1. DPOR — Systematically explores every meaningfully different interleaving. When it finds a race, it tells you exactly which shared-memory accesses conflicted and in what order. Powered by a Rust engine using vector clocks to prune redundant orderings.

  2. Bytecode exploration — Generates random opcode-level schedules and checks an invariant under each one. Often finds races very efficiently (sometimes on the first attempt), and can catch races that are invisible to DPOR (e.g. shared state inside C extensions). The trade-off: error traces show what happened but not why — you get the interleaving that broke the invariant, not a causal explanation.

  3. Marker schedule exploration — Exhaustive exploration of all interleavings at the # frontrun: marker level. Much smaller search space than bytecode exploration, with completeness guarantees.

  4. Trace markers — Comment-based synchronization points (# frontrun: marker_name) that let you force a specific execution order. Useful when you already know the race window and want to reproduce it deterministically in a test.

All four have async variants. A C-level LD_PRELOAD library intercepts libc I/O for database drivers and other opaque extensions.

DPOR deadlock detection (dining philosophers)

DPOR explores thread interleavings and detects deadlocks via wait-for-graph cycle analysis. Here it finds the circular wait in the classic 3-philosopher dining problem:

Deadlock diagram showing DPOR exploration of the dining philosophers problem. Three threads each acquire one fork (lock) then block waiting for the next, forming a cycle.

The timeline shows each thread's lock acquisitions (green), context switches (pink arrows), and the point where the deadlock is detected. Run make screenshot to regenerate this image from examples/dpor_dining_philosophers.py.

Quick Start: Bank Account Race Condition

A pytest test that uses trace markers to trigger a lost-update race:

from frontrun.common import Schedule, Step
from frontrun.trace_markers import TraceExecutor

class BankAccount:
    def __init__(self, balance=0):
        self.balance = balance

    def transfer(self, amount):
        current = self.balance  # frontrun: read_balance
        new_balance = current + amount
        self.balance = new_balance  # frontrun: write_balance

def test_transfer_lost_update():
    account = BankAccount(balance=100)

    # Both threads read before either writes
    schedule = Schedule([
        Step("thread1", "read_balance"),    # T1 reads 100
        Step("thread2", "read_balance"),    # T2 reads 100 (both see same value!)
        Step("thread1", "write_balance"),   # T1 writes 150
        Step("thread2", "write_balance"),   # T2 writes 150 (overwrites T1's update!)
    ])

    executor = TraceExecutor(schedule)
    executor.run({
        "thread1": lambda: account.transfer(50),
        "thread2": lambda: account.transfer(50),
    }, timeout=5.0)

    # One update was lost: balance is 150, not 200
    assert account.balance == 150

Case Studies

46 concurrency bugs found across 12 libraries by running bytecode exploration directly against unmodified library code: TPool, threadpoolctl, cachetools, PyDispatcher, pydis, pybreaker, urllib3, SQLAlchemy, amqtt, pykka, and tenacity. See detailed case studies.

Usage Approaches

1. Trace Markers

Trace markers are special comments (# frontrun: <marker-name>) that mark synchronization points in multithreaded or async code. A sys.settrace callback pauses each thread at its markers and waits for a schedule to grant the next execution turn. This gives deterministic control over execution order without modifying code semantics — markers are just comments.

A marker gates the code that follows it: the thread pauses at the marker and only executes the gated code after the scheduler says so. Name markers after the operation they gate (e.g. read_value, write_balance) rather than with temporal prefixes like before_ or after_.

from frontrun.common import Schedule, Step
from frontrun.trace_markers import TraceExecutor

class Counter:
    def __init__(self):
        self.value = 0

    def increment(self):
        temp = self.value  # frontrun: read_value
        temp += 1
        self.value = temp  # frontrun: write_value

def test_counter_lost_update():
    counter = Counter()

    schedule = Schedule([
        Step("thread1", "read_value"),
        Step("thread2", "read_value"),
        Step("thread1", "write_value"),
        Step("thread2", "write_value"),
    ])

    executor = TraceExecutor(schedule)
    executor.run({
        "thread1": counter.increment,
        "thread2": counter.increment,
    }, timeout=5.0)

    assert counter.value == 1  # One increment lost

2. DPOR (Systematic Exploration)

DPOR (Dynamic Partial Order Reduction) systematically explores every meaningfully different thread interleaving. It automatically detects shared-memory accesses at the bytecode level — attribute reads/writes, subscript accesses, lock operations — and uses vector clocks to determine which orderings are equivalent. Two interleavings that differ only in the order of independent operations (two reads of different objects, say) produce the same outcome, so DPOR runs only one representative from each equivalence class.

When a race is found, the error trace shows the exact sequence of conflicting accesses and which threads were involved:

Prefer frontrun.explore() — the new unified entry point (0.5+). The old per-strategy functions (explore_dpor, explore_interleavings, etc.) are deprecated and scheduled for removal in 0.6.

from frontrun import explore

class Counter:
    def __init__(self):
        self.value = 0

    def increment(self):
        temp = self.value
        self.value = temp + 1

def test_counter_is_atomic():
    result = explore(
        setup=Counter,
        workers=Counter.increment,
        count=2,
        invariant=lambda c: c.value == 2,
    )
    result.assert_holds()
Old API (deprecated, will be removed in 0.6)
from frontrun.dpor import explore_dpor

def test_counter_is_atomic():
    result = explore_dpor(
        setup=Counter,
        threads=[lambda c: c.increment(), lambda c: c.increment()],
        invariant=lambda c: c.value == 2,
    )
    assert result.property_holds, result.explanation

This test fails because Counter.increment is not atomic. The result.explanation shows the conflict:

Race condition found after 2 interleavings.

  Write-write conflict: threads 0 and 1 both wrote to value.

  Thread 0 | counter.py:7             temp = self.value
           | [read Counter.value]
  Thread 0 | counter.py:8             self.value = temp + 1
           | [write Counter.value]
  Thread 1 | counter.py:7             temp = self.value
           | [read Counter.value]
  Thread 1 | counter.py:8             self.value = temp + 1
           | [write Counter.value]

  Reproduced 10/10 times (100%)

DPOR explored exactly 2 interleavings out of the 6 possible (the other 4 are equivalent to one of the first two). For a detailed walkthrough of how this works, see the DPOR algorithm documentation.

Search strategies: The default DFS strategy is optimal for exhaustive exploration (stop_on_first=False) — it produces the minimum number of executions. When the trace space is very large and you have a limited execution budget (stop_on_first=True or a low max_executions), use a non-DFS strategy like search="bit-reversal" to spread exploration across diverse conflict points early, finding bugs faster on average. See search strategy documentation for details.

Scope and limitations: DPOR tracks Python bytecode-level conflicts (attribute and subscript reads/writes, lock operations) plus I/O. Redis key-level conflicts are detected by intercepting redis-py's execute_command(); activate with detect_io=True (works in both sync and async from 0.5). SQL conflicts are detected by intercepting DBAPI cursor.execute(). These key/table-level detectors are important: raw socket detection uses host:port as the resource ID, so every send and recv to the same server appears to conflict — without key-level or SQL-level refinement this causes a combinatorial explosion of spurious interleavings. C-extension shared state (NumPy arrays, etc.) is not tracked at all. The frontrun CLI adds C-level socket interception via LD_PRELOAD for opaque drivers, also at the coarse host:port level.

3. Bytecode Exploration (Random Strategy)

Bytecode exploration generates random opcode-level schedules and checks an invariant under each one, in the style of Hypothesis. Each thread fires a sys.settrace callback at every bytecode instruction, pausing to wait for its scheduler turn. No markers or annotations needed.

The random strategy often finds races very quickly — sometimes on the first attempt. It can also find races that are invisible to DPOR, because it doesn't need to understand why a schedule is bad; it just checks whether the invariant holds after the threads finish. If a C extension mutates shared state in a way that breaks your invariant, random exploration will stumble into it. DPOR won't, because it can't see the C-level mutation.

The trade-off: error traces are less interpretable. You get the specific opcode schedule that broke the invariant and a best-effort interleaved source trace, but not the causal conflict analysis that DPOR provides.

Prefer frontrun.explore(strategy='random') — the new unified entry point (0.5+). The old explore_interleavings is deprecated and will be removed in 0.6.

from frontrun import explore

def test_counter_is_atomic():
    result = explore(
        setup=lambda: Counter(value=0),
        workers=Counter.increment,
        count=2,
        invariant=lambda c: c.value == 2,
        strategy="random",
    )
    result.assert_holds()
Old API (deprecated, will be removed in 0.6)
from frontrun.bytecode import explore_interleavings

class Counter:
    def __init__(self, value=0):
        self.value = value

    def increment(self):
        temp = self.value
        self.value = temp + 1

def test_counter_is_atomic():
    result = explore_interleavings(
        setup=lambda: Counter(value=0),
        threads=[
            lambda c: c.increment(),
            lambda c: c.increment(),
        ],
        invariant=lambda c: c.value == 2,
        max_attempts=200,
        max_ops=200,
        seed=42,
    )

    assert result.property_holds, result.explanation

This fails with output like:

Race condition found after 1 interleavings.

  Lost update: threads 0 and 1 both read value before either wrote it back.

  Thread 1 | counter.py:7             temp = self.value
           | [read value]
  Thread 0 | counter.py:7             temp = self.value
           | [read value]
  Thread 1 | counter.py:8             self.value = temp + 1
           | [write value]
  Thread 0 | counter.py:8             self.value = temp + 1
           | [write value]

  Reproduced 10/10 times (100%)

The reproduce_on_failure parameter (default 10) controls how many times the counterexample schedule is replayed to measure reproducibility. Set to 0 to skip.

Note: Opcode-level schedules are not stable across Python versions. CPython does not guarantee bytecode compatibility between releases, so a counterexample from Python 3.12 may not reproduce on 3.13. Treat counterexample schedules as ephemeral debugging artifacts.

Automatic I/O Detection

Both the bytecode explorer and DPOR automatically detect socket and file I/O operations (enabled by default via detect_io=True). When two threads access the same network endpoint or file path, the operation is reported as a conflict so the scheduler explores their reorderings.

Python-level detection (monkey-patching):

  • Sockets: connect, send, sendall, sendto, recv, recv_into, recvfrom
  • Files: open() (read vs write determined by mode)

Resource identity is derived from the socket's peer address (host:port) or the file's resolved path — two threads hitting the same endpoint or file conflict; different endpoints are independent.

Redis Key-Level Conflict Detection

DPOR goes beyond coarse socket-level detection for Redis: it intercepts execute_command() on redis-py clients, classifies each command as a read or write on specific keys, and reports per-key resource IDs to the engine. Two threads operating on different Redis keys are independent; only operations on the same key (with at least one write) trigger interleaving exploration.

Sync DPOR — Redis patching is active automatically when detect_io=True (the default):

from frontrun.dpor import explore_dpor
import redis

def test_redis_counter_race(redis_port):
    class State:
        def __init__(self):
            r = redis.Redis(port=redis_port, decode_responses=True)
            r.set("counter", "0")
            r.close()

    def increment(state):
        r = redis.Redis(port=redis_port, decode_responses=True)
        val = int(r.get("counter"))
        r.set("counter", str(val + 1))
        r.close()

    result = explore_dpor(
        setup=State,
        threads=[increment, increment],
        invariant=lambda s: int(redis.Redis(port=redis_port).get("counter")) == 2,
        detect_io=True,   # default — activates Redis key-level patching
    )
    assert not result.property_holds  # DPOR finds the lost-update race

Async DPORdetect_io=True covers Redis in async too (from 0.5):

from frontrun import explore
import redis.asyncio as aioredis

async def test_async_redis_race(redis_port):
    async def increment(state):
        r = aioredis.Redis(port=redis_port, decode_responses=True)
        val = int(await r.get("counter"))
        await r.set("counter", str(val + 1))
        await r.aclose()

    result = await explore(
        setup=lambda: None,
        workers=increment,
        count=2,
        invariant=lambda s: True,  # check Redis directly in a real test
        detect_io=True,
    )

In 0.5 the async-only detect_redis=True kwarg was folded into detect_io=True so sync and async behave the same. detect_redis=True still works through 0.5 with a DeprecationWarning; it is removed in 0.6.

The same key-level precision applies to hashes (HGET/HSET), lists, sets, sorted sets, and all other Redis data structures — 160+ commands are classified. See the Redis technical details for a full walkthrough.

C-Level I/O Interception

When run under the frontrun CLI, a native LD_PRELOAD library (libfrontrun_io.so) intercepts libc I/O functions directly. This covers opaque C extensions — database drivers (libpq, mysqlclient), Redis clients, HTTP libraries, and anything else that calls libc's send(), recv(), read(), write(), etc.

Intercepted functions: connect, send, sendto, sendmsg, write, writev, recv, recvfrom, recvmsg, read, readv, close

The library maintains a process-global file-descriptor → resource map:

connect(fd, sockaddr{127.0.0.1:5432}, ...)  →  record fd=7 → "socket:127.0.0.1:5432"
send(fd=7, ...)                              →  report write to "socket:127.0.0.1:5432"
recv(fd=7, ...)                              →  report read from "socket:127.0.0.1:5432"
close(fd=7)                                  →  remove fd=7 from map

Events are transmitted to the Python side via one of two channels:

  • Pipe (preferred): IOEventDispatcher creates an os.pipe() and sets FRONTRUN_IO_FD to the write-end fd. The Rust library writes directly to the pipe (no open/close overhead per event), and a Python reader thread dispatches events to registered listener callbacks in arrival order. The pipe's FIFO ordering provides a natural total order without timestamps.
  • Log file (legacy): FRONTRUN_IO_LOG points to a temp file. Events are appended per-call (open + write + close each time) and read back in batch after execution.
from frontrun._preload_io import IOEventDispatcher

with IOEventDispatcher() as dispatcher:
    dispatcher.add_listener(lambda ev: print(f"{ev.kind} {ev.resource_id}"))
    # ... run code under LD_PRELOAD / DYLD_INSERT_LIBRARIES ...
# all events are also available as dispatcher.events

Trace Filtering (trace_packages)

By default, frontrun only traces user code — files outside the stdlib, site-packages, and frontrun's own internals. When the code under test lives inside an installed package (Django apps, plugin architectures, etc.), pass trace_packages to widen the filter:

from frontrun import explore

result = explore(
    setup=make_state,
    workers=[thread_a, thread_b],
    invariant=check_invariant,
    trace_packages=["mylib.*", "django_filters.*"],
)

Patterns use fnmatch syntax and are matched against dotted module names (e.g. django_filters.views). All exploration entry points (explore_dpor, explore_interleavings, and their async variants) accept this parameter. See trace filtering docs for details.

Async Support

Trace markers, random interleaving exploration, and DPOR all have async support.

Async Trace Markers

from frontrun import TraceExecutor
from frontrun.common import Schedule, Step

class AsyncCounter:
    def __init__(self):
        self.value = 0

    async def get_value(self):
        return self.value

    async def set_value(self, new_value):
        self.value = new_value

    async def increment(self):
        # frontrun: read_value
        temp = await self.get_value()
        # frontrun: write_value
        await self.set_value(temp + 1)

def test_async_counter_lost_update():
    counter = AsyncCounter()

    schedule = Schedule([
        Step("task1", "read_value"),
        Step("task2", "read_value"),
        Step("task1", "write_value"),
        Step("task2", "write_value"),
    ])

    executor = TraceExecutor(schedule)
    executor.run({
        "task1": counter.increment,
        "task2": counter.increment,
    })

    assert counter.value == 1  # One increment lost

Async Exploration

Async exploration works at natural await boundaries instead of opcodes, making schedules stable across Python versions. frontrun.explore() detects async workers automatically:

Prefer frontrun.explore() — the new unified entry point (0.5+). The old explore_interleavings (async form) and explore_async_dpor are deprecated and will be removed in 0.6.

import asyncio
from frontrun import explore

class Counter:
    def __init__(self):
        self.value = 0

    async def increment(self):
        temp = self.value
        await asyncio.sleep(0)  # any natural await is a scheduling point
        self.value = temp + 1

# DPOR (default) — systematic
async def test_async_counter_dpor():
    result = await explore(
        setup=Counter,
        workers=Counter.increment,
        count=2,
        invariant=lambda c: c.value == 2,
    )
    result.assert_holds()

# Random strategy — fast, probabilistic
async def test_async_counter_random():
    result = await explore(
        setup=Counter,
        workers=Counter.increment,
        count=2,
        invariant=lambda c: c.value == 2,
        strategy="random",
        max_attempts=200,
    )
    result.assert_holds()
Old async API (deprecated, will be removed in 0.6)
from frontrun import explore_interleavings

async def test_async_counter_race():
    result = await explore_interleavings(
        setup=lambda: Counter(),
        tasks=[lambda c: c.increment(), lambda c: c.increment()],
        invariant=lambda c: c.value == 2,
        max_attempts=200,
    )
    assert result.property_holds, result.explanation

CLI

The frontrun CLI wraps any command with the I/O interception environment:

# Run pytest with frontrun I/O interception
frontrun pytest -vv tests/

# Run any Python program
frontrun python examples/orm_race.py

# Run a web server
frontrun uvicorn myapp:app

The CLI:

  1. Sets FRONTRUN_ACTIVE=1 so frontrun knows it's running under the CLI
  2. Sets LD_PRELOAD (Linux) or DYLD_INSERT_LIBRARIES (macOS) to load libfrontrun_io.so/.dylib
  3. Runs the command as a subprocess

Pytest Plugin

Frontrun ships a pytest plugin (registered via the pytest11 entry point) that patches threading.Lock, threading.RLock, queue.Queue, and related primitives with cooperative versions before test collection.

Patching is on by default when running under the frontrun CLI. When running plain pytest without the CLI, patching is off unless explicitly requested:

frontrun pytest                    # cooperative lock patching is active (auto)
pytest --frontrun-patch-locks      # explicitly enable without CLI
pytest --no-frontrun-patch-locks   # explicitly disable even under CLI

Tests that use explore_interleavings() or explore_dpor() will be automatically skipped when run without the frontrun CLI, preventing confusing failures when the environment isn't properly set up.

Platform Compatibility

Feature Linux macOS Windows
Trace markers (sync + async) Yes Yes Yes
Bytecode exploration (sync + async) Yes Yes Yes
DPOR (Rust engine) Yes Yes Yes
frontrun CLI + C-level I/O interception Yes Yes No

Linux is the primary development platform and has full support for all features including the LD_PRELOAD I/O interception library.

macOS supports all features. The frontrun CLI uses DYLD_INSERT_LIBRARIES to load libfrontrun_io.dylib. Note that macOS System Integrity Protection (SIP) strips DYLD_INSERT_LIBRARIES from Apple-signed system binaries (/usr/bin/python3, etc.). Use a Homebrew, pyenv, or venv Python to avoid this limitation.

Windows support is limited to trace markers, bytecode exploration, and DPOR — the pure-Python and Rust PyO3 components that don't rely on LD_PRELOAD. The frontrun CLI and C-level I/O interception library are not available on Windows because they depend on the Unix dynamic linker's symbol interposition mechanism, which has no direct Windows equivalent.

Development

Prefer assert_holds() over manual asserts

InterleavingResult exposes a convenience helper that raises AssertionError with the race explanation on failure and returns None silently on success:

result = explore_dpor(setup, [thread1, thread2], invariant)
result.assert_holds()  # preferred over: assert result.property_holds, result.explanation

An optional msg_prefix is prepended to the explanation:

result.assert_holds(msg_prefix="transfer race: ")

Running Tests

# Build everything and run tests
make test-3.10

# Or via the frontrun CLI
make build-dpor-3.10 build-io
frontrun .venv-3.10/bin/pytest -v

Download files

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

Source Distribution

frontrun-0.5.0.tar.gz (285.8 kB view details)

Uploaded Source

Built Distributions

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

frontrun-0.5.0-cp314-cp314t-manylinux_2_39_x86_64.whl (791.0 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.39+ x86-64

frontrun-0.5.0-cp314-cp314t-manylinux_2_39_aarch64.whl (785.0 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.39+ ARM64

frontrun-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl (720.0 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

frontrun-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (791.3 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

frontrun-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (787.6 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

frontrun-0.5.0-cp314-cp314-macosx_11_0_arm64.whl (720.3 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

frontrun-0.5.0-cp313-cp313t-manylinux_2_39_x86_64.whl (791.0 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.39+ x86-64

frontrun-0.5.0-cp313-cp313t-manylinux_2_39_aarch64.whl (785.1 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.39+ ARM64

frontrun-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (791.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

frontrun-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (786.8 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

frontrun-0.5.0-cp313-cp313-macosx_11_0_arm64.whl (720.0 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

frontrun-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (791.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

frontrun-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (787.1 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

frontrun-0.5.0-cp312-cp312-macosx_11_0_arm64.whl (719.5 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

frontrun-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (791.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

frontrun-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (787.3 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

frontrun-0.5.0-cp311-cp311-macosx_11_0_arm64.whl (723.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

frontrun-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (791.6 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

frontrun-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (787.4 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

frontrun-0.5.0-cp310-cp310-macosx_11_0_arm64.whl (723.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file frontrun-0.5.0.tar.gz.

File metadata

  • Download URL: frontrun-0.5.0.tar.gz
  • Upload date:
  • Size: 285.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for frontrun-0.5.0.tar.gz
Algorithm Hash digest
SHA256 562c84864b7d2bb07ae5327a0f58beb3301e4f8175546970dd88af71c9482232
MD5 ac03add1e01f0267386f84f202eea556
BLAKE2b-256 82c94174dbb57b7f887dc81dfebc04b5d9e11e0d98539d7aac74851bb8c71559

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0.tar.gz:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp314-cp314t-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp314-cp314t-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 29d72ab6edf4129fa0becd77439bdbbad0b52b5ef9595cb956ade944969d4f75
MD5 3139befce23178bb95db8b53664b7041
BLAKE2b-256 749e894ed31a7185f8e519e98d1821b9b1a33d3e5b8b03631c965ac92dbdc9da

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp314-cp314t-manylinux_2_39_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp314-cp314t-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp314-cp314t-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 d82095a41d686812547d6c522979ce664fe000ab834ab17688f7bd9e33b81268
MD5 1b3b0e0bbcdd1f624b717c59af000a61
BLAKE2b-256 1cb193d8b65e1a9595185078a45544fb31e000aac9553ae53396e3bf9c7c8c99

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp314-cp314t-manylinux_2_39_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 858d4f36adcab714a01c88f6e9f3e6a4aae7ff2280136613c587a96ec1f1f5b5
MD5 4527c45522a6ad76e9c716bc824d4f07
BLAKE2b-256 3dfc7472075a572bcc2b3e190bd082cac917862fefa7816c5ed0231906926716

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0a58cf864ba144e88710d6e00e8ba9390a61a751860ba8833600a688fda7d059
MD5 ebc3ba2de39cbdba8a7e77620de41517
BLAKE2b-256 51554ff4e40e0c54c2613a031abb25d53b50d3ac7dbefb7d1faca6af7d9e7ddf

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 72c168c8ca71da0ec989187316377b1bffeec4e94f80be08cfcc1deb434221b5
MD5 fa23fad483610ee811055f7b3cae1805
BLAKE2b-256 87dd63bb4bf699ea4d82b4854ccd5a3b9e8908f0e00d1325336965360d0e453e

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 526c51c0bafdc4dcf168b3d88d6235ce3c5cc0b6e0ece2064812d243641c1b58
MD5 08d1d1f56d3df53a35bfae050594cf48
BLAKE2b-256 29a063875f91251d008db9f90ccb9122e2ca4fce6f5e543a3efae81c7195feef

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp313-cp313t-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp313-cp313t-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 7eb4c18f81e9f785e01d5351c6e1f795312ec6fb75c9726e0e2abbca4c626564
MD5 1e9707a2713d1f54546dba972d698f26
BLAKE2b-256 05a31f227b1ed93b61db1923840258ad374ac6f3e0d76d65e317ff687a51a57d

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp313-cp313t-manylinux_2_39_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp313-cp313t-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp313-cp313t-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 9abd86230bb5d4a4fa59d862d8e9eb50692ddd0d29c2115f28b70313d6d773a0
MD5 6a3c5f1acba0d1e6072295f3842f4eed
BLAKE2b-256 e12aea500d469e35bfbf1ef84e77340c265ca3bb322f2517f90ad1983352d0e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp313-cp313t-manylinux_2_39_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1df62cfddd5ee5238c42947f6403160e3c3be2aa8e676bc2c6ef9c9daa4916bb
MD5 0bfeddd6d6835ad2a85357e89f7e64e1
BLAKE2b-256 211a446e7cd610cab050f440f82133597432368703a81b3fc54e8cd4634a05a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 082ccea64663cdadbe1da8182224efec57b87f986d0c5fbf5b13b8942ec0b72f
MD5 46d7e7a51e4034c10f327a6f30620839
BLAKE2b-256 03c3b77e91f63cde06935d2b8285366bc1937024d09d36d020f78da17bac5e03

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c5231202d0ef1b7a97adcb196e36cda1b6a3a2f530c7ac429138dbd977df3449
MD5 ccda0a50debc5b0bdb39b745fd035a47
BLAKE2b-256 4241281dfe2cb6eca43a70439c4d7c4eb3beaff35cf0f6c0547dde245ff575ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7a6041319f58495eab178e23b234bfad27550f80a2ad9e4b29cf82c06c92b167
MD5 6583e086c8d7e55fe07946b2d27269c1
BLAKE2b-256 915d1fcd11927c1239a9affec69d1e71cb9b2aee722fceb84f55e8cf39839b4a

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 19cf51cdec4f95c59b9b6b467b5c73f1ac99479cce1f4b02006a8186de793bca
MD5 d1ea52b8a28c9982ff6801c81f3b3402
BLAKE2b-256 e26432140bdc31fd3638345a6df90847d2845f06101822bf1e4d94602c704193

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 95706e18c8654c5005bbec19e5afd2428190c5bf91ef9a86595e689ce1941962
MD5 cca02d2e9534b5141dcdedf12cfacb43
BLAKE2b-256 f0784a5cbf403625892316255be49aa512480eaa702f8fe9335498762c8b3189

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5f669f1f2499ec5b662bd9425ba5f4a29650dca934a4fe2feacdd128034059d5
MD5 222d422eb836372072fb221a14ef8eed
BLAKE2b-256 1584bfda0d4c4e3720bfecc6cf213bd0ac5c67dfd61843a1da324c185390100b

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a1a09e35e7bc0f5cde3fe34f7c582ef21b8e704bcbcd214c3befe86c190f0f5f
MD5 8a3e55c71bf2479405d86131a2a4f4d9
BLAKE2b-256 d688147fd3e6720e4f8128d9ffd5a5299773e88b3191cb345b8626f3c2d6428d

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 26895a899e52047a5826e48858a4876db149b0d0425f63cbb75c8fe5844d4cc1
MD5 4f07fa861cb4f95bf0517a2b606919fa
BLAKE2b-256 9c95c82b774fdb5d327435ce68b9643f7a79c5dbc19f0f041d6a8f9eb538a581

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c5e27d42fb62b5d75612ca65f76712e23a88e882c9d8d1b3f145050a088a56f8
MD5 d3c8387ea2d0a8bc7fe0909652ef092b
BLAKE2b-256 a4fea9c7a33de0f08283d7e775476bef4ee285cb31d0c962f8e982ac693df354

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 783c4a3d7cbe83319e3cdf929df053982afbbd0c042fbf5aa270e937b903b77b
MD5 0a7e80469d9ed8da925f7d8e1b985491
BLAKE2b-256 f0984637d7770b5ed108592ff0fdf6568b1cd8053c16e983fc06561458870a31

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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

File details

Details for the file frontrun-0.5.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.5.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 727d3178464996f9c9b3c0f4b92c98bbb7df0024471fb5dbfeeccc12728c6b67
MD5 c3ff5199c0950ec161a31e1617759735
BLAKE2b-256 8cf7fc46991faf0e8e54446aa03fe15d960d8659d1d070e9d0daaeee9a5ee479

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.5.0-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: publish.yml on lucaswiman/frontrun

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 Sentry Error logging StatusPage Status page