Skip to main content

A library for deterministic concurrency testing that helps you reliably reproduce and test race conditions

Project description

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))
    executor.run("thread2", lambda: account.transfer(50))
    executor.wait(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)
    executor.run("thread2", counter.increment)
    executor.wait(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:

from frontrun.dpor import explore_dpor

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_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() (sync; active with detect_io=True) or via detect_redis=True (async). 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

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.

explore_interleavings() 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, bytecode 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.

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 DPOR — pass detect_redis=True:

from frontrun.async_dpor import explore_async_dpor
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_async_dpor(
        setup=lambda: None,
        tasks=[increment, increment],
        invariant=lambda s: True,  # check Redis directly in a real test
        detect_redis=True,
    )

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.dpor import explore_dpor

result = explore_dpor(
    setup=make_state,
    threads=[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 Bytecode Exploration

Async shuffler exploration works at natural await boundaries instead of opcodes, making schedules stable across Python versions:

import asyncio
from frontrun import explore_interleavings

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

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

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

Project details


Download files

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

Source Distribution

frontrun-0.4.1.tar.gz (236.1 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.4.1-cp314-cp314t-manylinux_2_39_x86_64.whl (733.6 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.39+ x86-64

frontrun-0.4.1-cp314-cp314t-manylinux_2_39_aarch64.whl (722.9 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.39+ ARM64

frontrun-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl (658.4 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

frontrun-0.4.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (733.5 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

frontrun-0.4.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (725.5 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

frontrun-0.4.1-cp314-cp314-macosx_11_0_arm64.whl (659.1 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

frontrun-0.4.1-cp313-cp313t-manylinux_2_39_x86_64.whl (733.9 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.39+ x86-64

frontrun-0.4.1-cp313-cp313t-manylinux_2_39_aarch64.whl (723.2 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.39+ ARM64

frontrun-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl (658.7 kB view details)

Uploaded CPython 3.13tmacOS 11.0+ ARM64

frontrun-0.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (733.8 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

frontrun-0.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (726.2 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

frontrun-0.4.1-cp313-cp313-macosx_11_0_arm64.whl (659.8 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

frontrun-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (733.9 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

frontrun-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (726.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

frontrun-0.4.1-cp312-cp312-macosx_11_0_arm64.whl (659.4 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

frontrun-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (734.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

frontrun-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (725.7 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

frontrun-0.4.1-cp311-cp311-macosx_11_0_arm64.whl (663.1 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

frontrun-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (733.9 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

frontrun-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (725.6 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

frontrun-0.4.1-cp310-cp310-macosx_11_0_arm64.whl (662.8 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for frontrun-0.4.1.tar.gz
Algorithm Hash digest
SHA256 5ff018571a9652587577887946ef6866a69622d8d14ccd9ced702d232dca1548
MD5 f4f476cd095e63aa32f677c51dbc5384
BLAKE2b-256 a52a5a27455f815125601294f23a1a7e7c97cc90c301c3bf0d9c1436ed7aef68

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1.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.4.1-cp314-cp314t-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp314-cp314t-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 774ebe0b3dbd70412b67e65472e6b6a1cab375bde05754a39e000c007f90fd83
MD5 9a0f209e94fbf96ab2e32c6323bfc6a1
BLAKE2b-256 ab000e60fc46f45d683966d975ebc7fca682daab3fbb4fb8142be6fecd659189

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp314-cp314t-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp314-cp314t-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 fbf4756dd82f43969b895d1fece6ddcdd217d3b5f746f88eab22b55975dab143
MD5 ab9cc869e1165f1ae455c88f2aeacb42
BLAKE2b-256 f1aca588ff1186c108329de440104837fae6f7e1ef0e6afb301823a521b85040

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e0ead910107577d1485748997f7da4c51c09577a4d504fcb520278e4de08b2f0
MD5 986f0a6e048b75e438406da64ca9d77e
BLAKE2b-256 3077b98ba63941ce04fb2180906daefa916203cd89cc072047759a0f2b92d4ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9fc804b1a54e82a519a4aaed670f073e0aa8bf8d168a6c894f36bcecf7cef38f
MD5 0add971112b54baf519a3c3292db7cf8
BLAKE2b-256 479067c73f8cbb44a98abae4e4507edac845d11db41f878f9938bac12a498b68

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 93684b04ef5be787b0f9e7001e7b4f21003bcf76bd557dac98983afcb978f9a5
MD5 a6f7d0ff2418e53415a0ed3b3aa1f8d9
BLAKE2b-256 ee03ec243e73dc29cbc992fd9330cb6e0e3dd3de5383f68bf7b187f03f16720d

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 981130053556c89519885ca3118a1305e7baa3f2a91180b9861d3ff95a4b9aa4
MD5 1b880239cff34079453ed841b344880d
BLAKE2b-256 18cd9384aafdcc291c2642b970b1d5c6c96aa8a1bf86e5bba87f418f653784d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp313-cp313t-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp313-cp313t-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 c9da58857b8cf140905a4d190ee9cfedbbfe2b7726b69a087134d92063c62030
MD5 4560d4f549e323a31c9b0bf1e04d5363
BLAKE2b-256 a220aae30bb672bb7623115fcfd756e8f091cd85e00b6bc3d728f932089a1fbe

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp313-cp313t-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp313-cp313t-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 319e9912f7db1cabc3d66b47805f3f7ec221be577ae280aab3544a5ac71c493c
MD5 8570dfa8bb6c7975b982821ce862b031
BLAKE2b-256 ea251da0e254cd7b8a4dd104e5afbc924f921ab8d76286a83f952a25c33f6041

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp313-cp313t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 abe340fe3f5470c03e72c01914fd3407c7f5a6ae3413f8be7c4fd3cdb8f85f09
MD5 3fd2e024743c6ac5425e6e4bd1c5ed23
BLAKE2b-256 296352613d88139346025120ae5624001b6e45ceead89a811c11271f7ea937ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-cp313-cp313t-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.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 57e5c20a7c06eef5ea7cf0a3ddbae314f58a77f254b071295f26cadcbbeaf5a3
MD5 f4259ed32f3bf09032d1441f72534914
BLAKE2b-256 1152796a01b8d8d1d5b3dc44993867208c66b7f1a4054160eef6074fe39d163d

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 90abfeedee5fd8b58ac4fe54a0582f72e7d8ed97c36ffc7e9c69b7b6dcef1a2c
MD5 64caff15d04c197fcf7cb3b4f48c5e07
BLAKE2b-256 b16d44437d242adfae61c7f923a24f83f8d93637c0424232618d50274f84ec8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c7d7b25226086eb953e1dffd46bb106569732b668a5d097611388b594f1f0142
MD5 e173252faadcb0bb67e34d1a9d439860
BLAKE2b-256 80916d0c175a983a9d2787ae79173471a060f078ff111b93e3750937bdba96c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 af95827eaae7c863e45647f62ba261a48da7a9e2340a1e1e4a1a912c27a3c326
MD5 73bdad08fdab768a04c215abad4d8436
BLAKE2b-256 d7a73cb466e59fc22415281281585ea24a47dac79b2d79b689392a7212572f07

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7a6d4b5e2194867283454d796f4786fec4d576e5c8273791394dcdbef467ff46
MD5 9773f83365e6c7c85a895e6e47e43cdc
BLAKE2b-256 06f05d09fa5e7f7f2b126d5d203997d1731afc914fcb256fdc0ec022762ddc33

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0679ceb20c143356a7809d05ff79a5f563d495d9775d1d5781b4766b79d4477d
MD5 862e3c91f78d0e0bf4f190a7f2b2fae4
BLAKE2b-256 2ecb688b91fd88708b213bc66495dd33eab8a119e5cc1ae6e55204e1c103733c

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1b23ceb2fa928776bc9c80c54845d600ddd4fca53a2895ca82f5d1ec8ee805d6
MD5 09d98ede285e1f3d3b75be4def30af1f
BLAKE2b-256 c8cae0ef11c247d0c503b13984154d2314cd85aa23c7d7ba688fd71040387b00

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fdc3eea5aaa64b5df37d706223451cc0c890dd2436d9d604926a50105b456333
MD5 5ff8d167ba58fd4e2116682e24828826
BLAKE2b-256 efe736d873e27316d38fc30f7b1b39da183aa802417ffffe251df5fb04ffe670

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3f393b921fdf33a973b4f42e7e17bc9b41270621e2efe1d75f52e56f26a89065
MD5 4ce6eb2ea208df907aedb1ef713cd4f1
BLAKE2b-256 c9638e96b992863617ebaf0070607b94827979d2f9ced614e0f5a1c615d6f0f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 be672662ee268fd85eb9f603f2dd53c900668a032226bc5d018dbe2ed797dfa3
MD5 a47219613f81e853cf3879b469baac41
BLAKE2b-256 a9ddf5e701e89a5d0cd6d10f5229697e91041e209def435591fcc96124a29edf

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 32b364a62def4eae791bb666b662002d3de5fea3ea17bcb9663017b7b3522a8c
MD5 b48e8fca375df2732b5f0857b770b959
BLAKE2b-256 097ac01e6670b74c6dd581909431edff5ccac168f664b0ff674bbdffd15e3024

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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.4.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for frontrun-0.4.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4203a2e0aa03b190d1137bfcac5e5df82e816cf383b4277aa78acb42c3625c36
MD5 4e360862f653149350fc286ff476c044
BLAKE2b-256 f6025fe6d02b928ed03e35e73d500a8289e55de6f360958d7230396b44b6f38c

See more details on using hashes here.

Provenance

The following attestation bundles were made for frontrun-0.4.1-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 Pingdom Monitoring Sentry Error logging StatusPage Status page