# Blanket 1.0: An Early Look at Larry Hastings's Deterministic Threading Tests


[Larry Hastings](https://www.python.org/users/larry/) (CPython core developer behind the [Gilectomy](https://pyvideo.org/speaker/larry-hastings.html) GIL-removal work) released [Blanket](https://github.com/larryhastings/blanket) 1.0 around his PyCon US 2026 talk, ["Conquer multithreaded Python with Blanket"](https://us.pycon.org/2026/schedule/presentation/51/). It puts the Python thread scheduler under test control, making threaded tests deterministic. The repo is 10 days old with six stars, too early for the handbook to recommend, but it lands just as [PEP 703 makes free-threaded Python official](https://pydevtools.com/handbook/explanation/what-is-pep-703.md) for 3.14.

## The problem Blanket solves

A race between two threads might fire one run in a hundred, at the mercy of the OS scheduler, leaving you to either ignore it or hand-write brittle `threading.Event` plumbing to force the bug out. [Free-threaded Python](https://pydevtools.com/handbook/how-to/how-to-use-free-threaded-python-in-a-uv-project.md) makes it worse: code the GIL used to serialize is now genuinely concurrent, so tests that quietly passed start flaking.

## What Blanket does

Blanket wraps the standard `threading` primitives (Lock, Event, Condition, Semaphore), then a Scenario object scripts which thread runs next through `relay()` and `cycle()`:

```python {filename="example.py"}
import blanket

scenario = blanket.Scenario()
lock = scenario.Lock()

def worker(name):
    with lock:
        print(f"worker {name} got the lock")

A = scenario.thread(worker, 'A')
B = scenario.thread(worker, 'B')

lock_api = scenario.api(lock)

with scenario:
    list(lock_api.relay(A, B))

for t in [A, B]:
    t.join()
```

`relay(A, B)` commits A to one lock acquisition, then B, printing `worker A` before `worker B` every run. A bytecode injector inserts the scheduling points, so the only change to the code under test is `scenario.Lock()` in place of `threading.Lock()`.

## Why it's worth watching at six stars

Scanners like pytest-run-parallel and pytest-freethreaded run a test under many threads to find *unknown* races; Blanket goes the other way and scripts a known failing order into a deterministic regression test. Free-threaded Python needs that, and Blanket is the first library shaped right for it. If you have ever chased a flaky threaded test you could not pin down, the [README](https://github.com/larryhastings/blanket) is worth a read today.

## Learn More

* [Blanket on GitHub](https://github.com/larryhastings/blanket)
* [Blanket on PyPI](https://pypi.org/project/blanket/)
* [PyCon US 2026 talk: Conquer multithreaded Python with Blanket](https://us.pycon.org/2026/schedule/presentation/51/)
* [What is PEP 703?](https://pydevtools.com/handbook/explanation/what-is-pep-703.md)
* [Try free-threaded Python with uv](https://pydevtools.com/handbook/tutorial/try-free-threaded-python-with-uv.md)
* [How to use free-threaded Python in a uv project](https://pydevtools.com/handbook/how-to/how-to-use-free-threaded-python-in-a-uv-project.md)
