Skip to main content

peregrine

A drop-in ASGI and WSGI server for Python, written in Swift.
Up to 302,000 requests a second on four CPUs, and FastAPI at 1.2–1.3× uvicorn in the-benchmarker's results.
HTTP/1.1, HTTP/2, HTTP/3, WebSocket and WebTransport.

PyPI version Python versions MIT license


pip install peregrine-server
peregrine --host 0.0.0.0 --workers 0 main:app    # where you ran: uvicorn main:app

Requests per second with a worker per CPU at 256 connections, on four CPUs. On Peregrine: raw WSGI 302,417, raw ASGI 271,396, BlackSheep 202,141, FastAPI 72,306, Flask 50,423, Django 47,806. Reference: Elysia on Bun 350,622.

  • Faster with the framework you already use. In the published results of the-benchmarker/web-frameworks, the same FastAPI application answers 1.2–1.3× as many requests on Peregrine as on uvicorn, and Django 7–34× as many as on gunicorn. On four CPUs here, BlackSheep reaches 202,000 requests a second and FastAPI 77,000. How that was measured.
  • Nothing to change in the application. ASGI 3 and PEP 3333 in full, for FastAPI, Starlette, Django and Flask, with lifespan and WebSockets. The protocol is detected, and the options are the ones you know: coming from uvicorn or gunicorn.
  • What usually needs a proxy in front, built in. HTTP/2 and HTTP/3, TLS with Let's Encrypt certificates, static files with sendfile, compression, rate limiting, a response cache, Prometheus metrics, and a SIGHUP that replaces every worker without refusing a connection.
  • Free-threaded Python. On CPython 3.14t, --free-threaded runs the workers as threads of one process: the throughput of processes at a third of the memory.
  • Wheels for Linux x86_64 and aarch64, CPython 3.11 to 3.14 and 3.14t, including the official python:*-slim images. No Swift toolchain needed.

Built around two goals: spend as little time as possible outside the application, and spend as little memory as possible per connection.

It runs in the same process as CPython — there is no socket between Swift and Python, no serialisation step, and no second process. Swift owns the accept loop, the HTTP parser and the response writer; Python owns the application. A wheel installs the server as peregrine._native, an extension module the peregrine command loads into your own interpreter, so applications run in exactly the python3 they were installed for.

pip install peregrine-server                # wheel if one matches; else compiled

peregrine --port 8000 myapp:application     # WSGI, protocol auto-detected
peregrine --port 8000 --workers 0 myapp:app # ASGI, one worker per CPU
peregrine --reload myapp:app                # restart on source changes

peregrine --http3 --tls-cert cert.pem --tls-key key.pem myapp:app

Further reading: INSTALLATION.md — what to install and what to do when it goes wrong. CONFIG.md — configuring FastAPI and Flask for every protocol here. ARCHITECTURE.md — how the server is built, and why. TRANSPORT.md — what each protocol does and what is implemented of it. BENCHMARKS.md — the raw ASGI and WSGI, FastAPI, Django, Flask and BlackSheep entries on Peregrine, and Elysia on Bun, with the load command, applications and worker count of the-benchmarker/web-frameworks, and how that differs from what the site publishes. DEPLOY.md — how a release reaches PyPI. RELEASE.md — what changed in each version.


Numbers

The suite's own applications and load command, from the-benchmarker/web-frameworks: zrk, an open-loop ramp to 500,000 requests a second, 15 s per level, with --workers $(nproc). Requests per second at 64 / 256 / 512 connections, the mean of three runs, all in one session, WSL2 on 4 CPUs with the load generator on the same machine, CPython 3.14, Peregrine 1.1.5:

on Peregrine 64 256 512
raw WSGI 293,025 302,417 256,660
raw ASGI 221,826 271,396 260,155
BlackSheep 179,208 202,141 197,687
FastAPI 57,553 72,306 76,818
Flask 49,933 50,423 50,964
Django 46,058 47,806 45,806
Elysia on Bun, for reference 346,465 350,622 356,547

No run returned an error. The raw entries vary most between runs, by up to a quarter, so their order at 512 connections means nothing.

The site measures on its own machine, 16 CPUs, so its figures cannot be set beside these. What it shows is the same frameworks on different servers. Peregrine was added to the suite in September 2026; in its dataset of 2026-09-13, on Peregrine 1.0:

site entry 64 256 512
FastAPI on peregrine 54,338 59,273 60,201
FastAPI on uvicorn 41,891 47,335 48,552
Django on peregrine 39,840 39,718 39,654
Django on gunicorn 1,165 5,727 4,699

BENCHMARKS.md has the latency, every run, the versions, where this machine differs from the suite's, and the commands that repeat it.

These are hello-world routes, so they measure what a server adds to a request rather than what an application can do. A real application doing database work will be dominated by that work, and the gaps will narrow accordingly.

The server is about 1.7 MB of text and data as the extension module (1.3 MB as the executable, which needs no position-independent code), and a live connection costs one 16 KiB pooled read buffer plus a slot of about 200 bytes. Nearly all of a worker's resident memory is CPython and the application.


Coming from uvicorn or gunicorn

Point Peregrine at the same application object. The protocol is detected, so there is no worker class to name, and most options keep their names. What differs is mostly units, because Peregrine's timeouts are in milliseconds:

uvicorn gunicorn peregrine
uvicorn main:app gunicorn -k uvicorn.workers.UvicornWorker main:app peregrine main:app
gunicorn myproject.wsgi peregrine myproject.wsgi:application
--host 0.0.0.0 --port 8000 -b 0.0.0.0:8000 --host 0.0.0.0 --port 8000
--uds /run/app.sock -b unix:/run/app.sock --unix /run/app.sock
--workers 4 -w 4 --workers 4, or 0 for one per CPU
--threads 8 --wsgi-threads 8
--reload --reload --reload
--ssl-certfile c.pem --ssl-keyfile k.pem --certfile c.pem --keyfile k.pem --tls-cert c.pem --tls-key k.pem
--forwarded-allow-ips '*' --forwarded-allow-ips '*' --forwarded-allow-ips '*'
--root-path /api --root-path /api
--timeout-keep-alive 5 --keep-alive 5 --keep-alive 5000
--timeout-graceful-shutdown 30 --graceful-timeout 30 --graceful-timeout 30000
--lifespan off --no-lifespan
--ws-max-size 16777216 --ws-max-message 16777216
--ws-ping-interval 20 --ws-ping-interval 20000
--factory --factory
access log on by default --access-logfile - --access-log
--log-level info --log-level info --log-level info

uvloop is used when it is installed (pip install "peregrine-server[uvloop]"), as with uvicorn. SIGTERM drains the workers, and SIGHUP replaces them one at a time without refusing a connection.


What is supported

HTTP/1.1 HTTP/2 HTTP/3 WebSocket WebTransport
ASGI ✓ ✓ ✓ ✓ ✓
WSGI ✓ ✓ ✓ 501 501

WebSockets and WebTransport are refused for WSGI rather than half-served: both are streams that outlive their response, and PEP 3333 has no way to express one. Everything else is the same code for both — see one request path.

WSGI (PEP 3333): full environ, wsgi.input as a C-level stream (read, readline, readlines, iteration), start_response including exc_info semantics and the legacy write callable, wsgi.file_wrapper, iterable close(), repeated request headers folded per spec, automatic Content-Length/chunked framing. start_response may be called from inside the first iteration of the returned iterable, as the spec requires a server to allow, and a Content-Length the application declares is enforced rather than trusted.

Output is unbuffered in the sense PEP 3333 means. A block yielded by an iterator goes to the socket before the next one is asked for, and a block handed to write() goes out before the call returns — taking the response head with it, if it is the first. A generator that yields a progress line and then works for a second is therefore seen to do so. A list or tuple return value is still written in one go, because every part of it is already in hand and nothing is waiting.

ASGI 3.0 (HTTP): full scope including client, server, raw_path and state, streaming request bodies, streaming responses with genuine write backpressure, http.disconnect, and the lifespan protocol with state shared into request scopes. Applications that do not implement lifespan are detected and skipped. Response headers are accepted in any shape the specification allows — tuples or lists, bytes, bytearray or str.

An ASGI application is started as soon as the request head is parsed, not once the body has finished arriving. That is what lets one reject an upload at byte one — unauthorised, too large, wrong content type — instead of paying to receive all of it first, and it is the only way receive() can mean anything on a request that is still being sent. Body bytes are read no further ahead than the application has asked for.

Answering early leaves the rest of that body on the wire, and it is not a request. If what remains is small and already here it is swallowed and the connection is reused; otherwise that response is the last one on the connection.

A receive() made after the response is complete is answered with http.disconnect rather than parked. The request is over at that point, and a task waiting on a body nobody will read holds the connection with it.

ASGI 3.0 (WebSocket): the full connect / accept / receive / send / close cycle, subprotocol negotiation, extra handshake headers, fragmented messages, text and binary, keepalive ping/pong with a dead-peer timeout, and a message size limit. Details.

WebTransport: sessions, streams in both directions, unreliable datagrams and the close capsule, through a documented ASGI extension — ASGI has no WebTransport specification, so this one is Peregrine's.

Free-threaded CPython (PEP 703): --free-threaded runs the workers as threads of one process rather than as processes, on an interpreter built without the GIL. Same parallelism, one copy of the application:

peregrine --workers 0 --free-threaded myapp:app

On four cores with a CPU-bound application that is 5,907 req/s in 47 MB against 5,832 req/s in 143 MB for four worker processes — the throughput of processes at a third of the memory, because the application is imported once instead of four times. The ASGI lifespan runs once per worker thread, on the event loop that thread serves requests with, so what an application opens in startup is attached to the loop that will await it. Details.


Installing

A wheel is tagged for one CPython and one platform. PyPI has them for CPython 3.11 to 3.14 and free-threaded 3.14t, on Linux x86_64 and aarch64 with glibc 2.35 or newer: Debian 12, Ubuntu 22.04, what came after them, and the official python:*-slim images. When one matches, pip installs it and Swift is not required. When none does, as on macOS, Alpine or an older distribution, pip compiles the sdist against the interpreter you are installing into:

pip install peregrine-server

In a container nothing else is needed:

FROM python:3.13-slim
RUN pip install --no-cache-dir "peregrine-server[uvloop]" fastapi
COPY main.py .
CMD ["peregrine", "--host", "0.0.0.0", "--workers", "0", "main:app"]
# plus a Swift 6.1+ toolchain from https://swift.org/install
git clone https://github.com/grepjava/peregrine
cd peregrine && bash scripts/build-extension.sh    # peregrine._native
PYTHONPATH=python python3 -m peregrine --port 8000 myapp:app

The extension module is the default wherever Peregrine is installed or built from source. swift build -c release builds the standalone executable, which embeds libpython and takes the same options; it is for working on Peregrine itself.

Requirements, per-platform packages, certificates and the failure modes worth recognising: INSTALLATION.md.


Usage

peregrine [options] MODULE:ATTRIBUTE

  --host HOST              interface to bind (default 127.0.0.1)
  --port PORT              port to bind (default 8000)
  --unix PATH              listen on a unix socket instead
  --workers N              worker processes, 0 = one per CPU (default 1)
  --free-threaded          run the workers as threads of one process
                           instead of as processes; needs a free-threaded
                           CPython (python3.13t or newer)
  --protocol wsgi|asgi     force the application protocol (default: detect)
  --root-path PATH         SCRIPT_NAME / ASGI root_path prefix
  --scheme http|https      scheme reported to the application
  --backlog N              listen backlog (default 2048)
  --max-connections N      concurrent connections per worker (default 4096)
  --max-body BYTES         largest accepted request body (default 16 MiB)
  --max-header-size BYTES  largest accepted request head (default 32 KiB)
  --keep-alive MS          idle keep-alive timeout (default 5000)
  --request-timeout MS     how long a request may stall mid-message (30000)
  --graceful-timeout MS    time in-flight requests get on shutdown (10000)
  --drain-delay MS         on SIGTERM, fail the health check and keep serving
                           for MS before draining, for load balancers
  --wsgi-threads N         WSGI application threads per worker (default 1)
  --forwarded-allow-ips L  proxies whose X-Forwarded-* headers are trusted
  --factory                the target is a factory returning the application
  --venv DIR               virtualenv whose packages the app should import
  --no-auto-venv           ignore VIRTUAL_ENV from the environment
  --python-path DIR        directory to prepend to sys.path (repeatable)
  --python-home DIR        PYTHONHOME, for the standalone executable only
  --reload                 restart workers when source files change
  --no-uvloop              do not use uvloop even when installed
  --no-lifespan            skip the ASGI lifespan protocol
  --lifespan-scope WHICH   with --free-threaded, run the lifespan per worker
                           thread (worker, default) or once for the whole
                           process (process)
  --tls-cert PATH          PEM certificate chain; enables TLS with ALPN.
                           Repeatable, with a --tls-key each: the first pair
                           is the default and the rest are chosen by SNI
  --tls-key PATH           PEM private key for the preceding --tls-cert
  --tls-ciphers LIST       OpenSSL cipher list for TLS 1.2
  --ktls                   let the kernel encrypt TLS, so --static-dir files
                           go out with sendfile over HTTPS too
  --no-http2               refuse HTTP/2 and answer HTTP/1.1 only
  --http2-only             serve only HTTP/2 (h2c), with no HTTP/1 fallback
  --http3                  also serve HTTP/3 over QUIC (needs TLS)
  --quic-port PORT         UDP port for HTTP/3 (default: the TCP port)
  --no-websockets          reject WebSocket upgrades with 501
  --ws-max-message BYTES   largest accepted WebSocket message (16 MiB)
  --ws-ping-interval MS    keepalive ping period, 0 to disable (20000)
  --ws-ping-timeout MS     how long an unanswered ping may go (20000)
  --ws-max-queue N         messages buffered for a slow app (default 32)
  --ws-max-queue-bytes N   bytes buffered for a slow app (default 4 MiB)
  --ws-compress            permessage-deflate for clients that offer it
  --static-dir P=DIR       serve URL prefix P from DIR with sendfile,
                           without calling the application (repeatable)
  --acme-domain NAME       get and renew a certificate from Let's Encrypt,
                           answering tls-alpn-01 on this port (repeatable)
  --acme-email ADDR        contact address for the ACME account
  --acme-cache DIR         account key and certificate (default ./acme)
  --acme-staging           use Let's Encrypt's staging CA
  --acme-directory URL     use another ACME CA
  --acme-ca-bundle PATH    roots to trust for the CA's own HTTPS
  --redirect-http PORT     answer plain HTTP on PORT with a redirect to https
  --hsts SECONDS           Strict-Transport-Security on every TLS response
  --rate-limit RATE        429 past RATE requests per client (100/s, 600/m),
                           counted across all workers
  --rate-limit-burst N     requests allowed at once before RATE applies
  --cache-size MIB         answer repeated GETs from a cache shared by every
                           worker, for responses the application marks fresh
                           (read CONFIG.md first)
  --cache-max-object KIB   largest body the cache keeps (default 1024)
  --cache-ttl-max SECONDS  longest a response is kept (default 300)
  --compress               compress text-like application responses with
                           br, zstd or gzip (see CONFIG.md about BREACH)
  --compress-min-size N    leave bodies declared smaller than N alone (1024)
  --compress-static        serve FILE.br / FILE.zst / FILE.gz beside a
                           --static-dir file to clients that accept it
  --request-start-header   hand the app X-Request-Start for queue-time APMs
  --request-id             an X-Request-ID per request, for the app, the
                           response and the access log
  --trace-context          log a request's W3C trace and parent span IDs
  --health-check-path P    answer P with 200 in the server, without calling
                           the application (e.g. /healthz)
  --access-log             log one line per request
  --access-log-format F    text (default) or json; implies --access-log
  --metrics-port PORT      serve Prometheus metrics on this port
  --metrics-host HOST      what the metrics port binds (default --host)
  --log-level LEVEL        debug, info, warning, error, silent
  --version                print the version and exit

The protocol is detected by inspecting the callable: a coroutine function, or one taking three positional parameters, is ASGI; two parameters is WSGI. Force it with --protocol if your application is wrapped in something opaque.

SIGTERM or SIGINT drains gracefully, with a deadline. SIGHUP replaces every worker one at a time, each replacement accepting on the socket its predecessor had before that one is asked to stop, so nothing is refused and nothing is reset -- which also makes it the certbot deploy hook, because the replacements read the certificate off disk again. See reloading without a restart, and the shutdown sequence, which is more careful than it looks and deliberately so.

Behind a reverse proxy

--forwarded-allow-ips takes a comma-separated list of addresses or CIDR blocks, unix, or * for every peer. Only headers arriving from a peer on that list are honoured; from anyone else X-Forwarded-For, X-Forwarded-Proto and Forwarded are ignored rather than trusted, because a client can send them too.


Frameworks

Checked against real applications rather than only the specifications (bash scripts/framework-test.sh):

  • FastAPI (ASGI) — routing, middleware, lifespan context managers including teardown on SIGTERM, StreamingResponse, WebSocket endpoints driven by the websockets client, the generated OpenAPI document, and the anyio worker threads FastAPI uses for synchronous endpoints.
  • Flask (WSGI) — routing, request bodies, streamed responses, request.is_secure and request.remote_addr derived from forwarded headers, and blocking views overlapping properly on --wsgi-threads.

Both run over HTTP/3 with no integration at all: a request is the same request whatever carried it. WebTransport is the exception for FastAPI, because a session is not a request — Starlette's router asserts on the scope type before it routes — so peregrine.contrib puts a router in front that answers sessions and passes everything else through:

from fastapi import FastAPI
from peregrine.contrib.fastapi import WebTransportRouter

api = FastAPI()
app = WebTransportRouter(api)            # serve this one

@app.route("/chat/{room}")
async def chat(session):
    await session.accept()
    async for stream in session.incoming_streams():
        await stream.send(b"hello " + await stream.read(), end=True)

Flask needs nothing at all: as a WSGI application it is served over HTTP/1.1, HTTP/2 and HTTP/3, and WebSocket and WebTransport, which PEP 3333 cannot express, are refused with a 501. How to configure both, protocol by protocol. What the router does.


Why Swift

The interesting question is not "why not C" but "why not Python, or Rust, or Go", since all four can host an application server and three of them are more usual choices for one.

It compiles to a native binary with no runtime to schedule around. A server is a loop over a poller; anything that inserts its own scheduler between the loop and the syscall — a garbage collector that stops the world, a green-thread runtime that decides when a read happens — buys concurrency this design does not need and costs latency it cannot recover. Swift has neither. Reference counting is deterministic, and where it would cost anything it can be removed, which is a large part of what the server does.

It talks to C without a binding layer. Embedding CPython means calling a C API constantly: PyDict_SetItem, PyObject_Vectorcall, Py_DECREF, a few hundred times per request. In Swift those are direct calls through a thin shim for the parts that are macros. There is no FFI marshalling, no unsafe boundary to justify per call site, and no second object model to keep in step with CPython's — a PyObject * is an OpaquePointer, and a ~Copyable struct makes the compiler prove the decref happens exactly once. The same is true of OpenSSL, epoll and recvmmsg.

It is memory-safe by default and unsafe on request. Almost all of this server is ordinary safe Swift: bounds-checked, ownership-checked, no null. The hot path opts out deliberately and locally — raw pointers into a read buffer, a slab of connection structs — and those opt-outs are visible in the source because they have to be spelled Unsafe. That is a better default for a network-facing parser than a language where everything is unsafe and discipline is the only guard, and a better ceiling than one where the escape hatch is awkward enough that you write the slow thing instead.

Generics and value types make the fast version the readable one. ByteBuffer is a struct passed in registers; the HTTP parser returns offsets into it; the QUIC packet builder writes through a ~Copyable writer that cannot be aliased. None of that needs a comment explaining what the pointer arithmetic is for, because there is no pointer arithmetic in it.

The honest costs: the ecosystem for this kind of work is small, so the QUIC stack, the TLS 1.3 handshake, HPACK and QPACK are all written here rather than pulled in; Linux tooling is thinner than C's; and Foundation is avoided entirely because it would bring back the allocation behaviour the design exists to remove.


Correctness and hardening

The HTTP/1.1 parser is strict wherever strictness prevents request smuggling — whitespace before a colon, Content-Length with Transfer-Encoding, disagreeing lengths, any Transfer-Encoding that is not a bare chunked, obs-fold, a missing or repeated Host. Response headers containing CR or LF are refused outright. Request header names containing underscores are dropped, and a Proxy: header is dropped entirely. The full list.

Every transport is checked against an implementation that shares none of its code, because a test written against the same understanding as the code proves only that the understanding is consistent.

swift test                                      # 150 unit tests: parser,
                                                #   chunking, buffers, writer,
                                                #   websocket framing, HPACK,
                                                #   QUIC packet protection,
                                                #   and the fuzz corpus
bash scripts/integration-test.sh                #  56 end-to-end checks
python3 scripts/feature-test.py                 # 196 checks for the failure
                                                #   modes a plain request never
                                                #   reaches: slow consumers,
                                                #   stuck-request shutdown,
                                                #   lifespan cleanup, worker
                                                #   restarts, reload
bash scripts/framework-test.sh                  # checks against real FastAPI
                                                #   and Flask applications,
                                                #   over HTTP/1.1 and HTTP/2
<venv>/bin/python scripts/http2-test.py         # 162 checks against `h2`
<venv>/bin/python scripts/http3-test.py         # 114 checks against `aioquic`
python3 scripts/contrib_test.py                 #  58 Python-only: routing,
                                                #   converters, session helper
<venv>/bin/python scripts/webtransport-test.py  # sessions, streams, datagrams,
                                                #   plus FastAPI over HTTP/3
                                                #   and WebTransport
swift run -c release pgfuzz                     # mutation fuzzing of every
                                                #   parser that reads bytes
                                                #   from the network

CI runs all of it on every push, against CPython 3.11 through 3.14 and a free-threaded 3.14, on Linux and macOS, plus the fuzzer under AddressSanitizer. The suites are the ones above — there is no CI-only test path, so a green run there means what a green run here means. More on the fuzzing.

HTTP/2 conformance is checked with h2spec, which is not vendored here:

peregrine --port 8443 --tls-cert cert.pem --tls-key key.pem examples.asgi_app:app &
h2spec -h 127.0.0.1 -p 8443 -t -k    # 146 tests, 146 passed

QUIC packet protection is checked against RFC 9001 appendix A directly: the key schedule, the header protection and the sample packets are the RFC's own bytes.


What is not

  • sendfile for wsgi.file_wrapper. The wrapper works and streams in chunks, but does not yet drop into sendfile(2) the way --static-dir does.
  • Byte ranges and directory indexes for --static-dir. It serves assets with an ETag and answers If-None-Match; it is not a file server.
  • Compressing --static-dir files on the fly. --compress-static serves copies compressed at build time; a file with no copy is sent as it is, which keeps sendfile(2) and keeps the CPU for requests.
  • SNI for HTTP/3. Several certificates are chosen by name over TCP; HTTP/3 serves the first pair whatever the client asks for, because the QUIC handshake here is built from the primitives rather than driven by OpenSSL.
  • QUIC connection migration across workers, and 0-RTT. A connection survives a change of address, but not a change of worker, and every handshake is a full one.
  • HTTP/3 server push, and WebSocket over HTTP/2 or HTTP/3. HTTP/3 advertises extended CONNECT because that is how WebTransport arrives; webtransport is the only :protocol served. HTTP/2 does not advertise it.
  • Windows. The I/O layer is epoll/kqueue.
  • Spans. --trace-context puts an incoming W3C trace on the access-log line and hands the header to the application untouched, and there are Prometheus metrics on --metrics-port, but the server records no OpenTelemetry spans of its own. The application's instrumentation is the right place for those, and there are good ones.

By default a synchronous WSGI application occupies its worker for the duration of the call. Scale with --workers, and with --wsgi-threads when the application spends its time waiting on I/O rather than on the CPU.

Metadata

Release files for peregrine-server 1.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for peregrine-server 1.1.5
File Size Uploaded
peregrine_server-1.1.5.tar.gz 1.9 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for peregrine-server 1.1.5
File
peregrine_server-1.1.5-cp314-cp314t-manylinux_2_35_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.35+ x86-64 Details
peregrine_server-1.1.5-cp314-cp314t-manylinux_2_35_aarch64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.35+ ARM64 Details
peregrine_server-1.1.5-cp314-cp314-manylinux_2_35_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.35+ x86-64 Details
peregrine_server-1.1.5-cp314-cp314-manylinux_2_35_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.35+ ARM64 Details
peregrine_server-1.1.5-cp313-cp313-manylinux_2_35_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.35+ x86-64 Details
peregrine_server-1.1.5-cp313-cp313-manylinux_2_35_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.35+ ARM64 Details
peregrine_server-1.1.5-cp312-cp312-manylinux_2_35_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.35+ x86-64 Details
peregrine_server-1.1.5-cp312-cp312-manylinux_2_35_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.35+ ARM64 Details
peregrine_server-1.1.5-cp311-cp311-manylinux_2_35_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.35+ x86-64 Details
peregrine_server-1.1.5-cp311-cp311-manylinux_2_35_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.35+ ARM64 Details

Total release size: 62.3 MB

Release files / peregrine_server-1.1.5.tar.gz

Download URL peregrine_server-1.1.5.tar.gz
Size 1.9 MB
Tags Source
SHA-256 checksum
How to use checksums
1f63ca2bf99fe3574e64a1de67f372581d38126c20e1f993c5759abd171bdbb5
BLAKE2b-256 checksum
How to use checksums
07de3f6652c4d114c4349f2535410035c61b433a8e6d34598e1a0412b56b0214
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp314-cp314t-manylinux_2_35_x86_64.whl

Download URL peregrine_server-1.1.5-cp314-cp314t-manylinux_2_35_x86_64.whl
Size 6.2 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
914c10987a4b532fe6d7bfdbd1dcd2e5cde34a59ad81b4151180e63487d985bb
BLAKE2b-256 checksum
How to use checksums
653e2b61beaa3b0e84e9d1f311cb585a96432f2f8d66c2e3aaaa1199e6366bc4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp314-cp314t-manylinux_2_35_aarch64.whl

Download URL peregrine_server-1.1.5-cp314-cp314t-manylinux_2_35_aarch64.whl
Size 5.9 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.35+ ARM64
SHA-256 checksum
How to use checksums
5e4d5556ae060dbc93b7517daed01fadce8924e69c24b54e2efdcf7a77ada5d3
BLAKE2b-256 checksum
How to use checksums
9e214e7d276e16470b85b67c9e7c80568d0d8236d91d778f1c611675d8585b6c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp314-cp314-manylinux_2_35_x86_64.whl

Download URL peregrine_server-1.1.5-cp314-cp314-manylinux_2_35_x86_64.whl
Size 6.2 MB
Tags CPython 3.14 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
1749e052c1bc860d5a554aed6df5b86d60650725e1ca93dd51773cb1f7e53a75
BLAKE2b-256 checksum
How to use checksums
7423efff7ba5713a06ab151e74eef709a5395d2c66fdc5957b167bf5fbad511a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp314-cp314-manylinux_2_35_aarch64.whl

Download URL peregrine_server-1.1.5-cp314-cp314-manylinux_2_35_aarch64.whl
Size 5.9 MB
Tags CPython 3.14 Linux glibc 2.35+ ARM64
SHA-256 checksum
How to use checksums
56296adbdbf4915c5f53c1c6dc9813fcda2afb5a8dc390fc7f3bb0da33476cc3
BLAKE2b-256 checksum
How to use checksums
2c91c36dfb4e9482ed18b39e6caaa526c060ce2b4bbde325b09c329cdfd2dd8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp313-cp313-manylinux_2_35_x86_64.whl

Download URL peregrine_server-1.1.5-cp313-cp313-manylinux_2_35_x86_64.whl
Size 6.2 MB
Tags CPython 3.13 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
6f52890d8f1fe8112371e166aa5fd18cd1d67a083487ad5e7e0a3d75b35890ad
BLAKE2b-256 checksum
How to use checksums
1379e56f3b14c28858bc8b9aceb927d22a9b22c2cfe2c9350c1a5382bc7456ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp313-cp313-manylinux_2_35_aarch64.whl

Download URL peregrine_server-1.1.5-cp313-cp313-manylinux_2_35_aarch64.whl
Size 5.9 MB
Tags CPython 3.13 Linux glibc 2.35+ ARM64
SHA-256 checksum
How to use checksums
5cd69964a609475d587cfcf8d3a187e71adee4001f2ec29b5d77f5b3b1c7deb7
BLAKE2b-256 checksum
How to use checksums
8d8b37d51ec92ef572b73b87093d37076969c87b4b7852f2a969c10442ce20ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp312-cp312-manylinux_2_35_x86_64.whl

Download URL peregrine_server-1.1.5-cp312-cp312-manylinux_2_35_x86_64.whl
Size 6.2 MB
Tags CPython 3.12 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
b1578f9e93877815d3958a9a69bd93dc681daeb97528b16877397f52e46e522d
BLAKE2b-256 checksum
How to use checksums
ef3fa80e4ae245b4cb1b59b38299fe817b12533d3f320a796cc29a6f3fb8c469
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp312-cp312-manylinux_2_35_aarch64.whl

Download URL peregrine_server-1.1.5-cp312-cp312-manylinux_2_35_aarch64.whl
Size 5.9 MB
Tags CPython 3.12 Linux glibc 2.35+ ARM64
SHA-256 checksum
How to use checksums
55e53d7726ecb99b069e2fcb8f995744393f8cb3b89d29f833156cf2be634ee2
BLAKE2b-256 checksum
How to use checksums
e5754ee2e27083c1e319e985ead0c3fb8478d9fb785e6904248852647606bb80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp311-cp311-manylinux_2_35_x86_64.whl

Download URL peregrine_server-1.1.5-cp311-cp311-manylinux_2_35_x86_64.whl
Size 6.2 MB
Tags CPython 3.11 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
4ba06bce058de47f4ceccebdbcc5aa03003239c55b2953c65bdef65e2e445495
BLAKE2b-256 checksum
How to use checksums
d3582ab8f2a05dcbdcdbb25ea5845f701597b16ee33ca6302883c4ab51f1eb7c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / peregrine_server-1.1.5-cp311-cp311-manylinux_2_35_aarch64.whl

Download URL peregrine_server-1.1.5-cp311-cp311-manylinux_2_35_aarch64.whl
Size 5.9 MB
Tags CPython 3.11 Linux glibc 2.35+ ARM64
SHA-256 checksum
How to use checksums
265272555f97194bb02a1da4a0379adc2d1ac6733e42d93a3a8d972fc7b4d23e
BLAKE2b-256 checksum
How to use checksums
955f929a86f925879bacc1a4cd6d17914b8fe0c41903603ba7806e9e1621814b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

1.1.7

11 release files

This release

1.1.5 This release

11 release files

1.1.4

11 release files

1.1.3

6 release files

1.1.1

6 release files

1.1.0

6 release files

1.0.0

6 release files

0.8.0

1 release file

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