Skip to main content

🚀 Wingfoil

PyPI - Version Documentation Status CI

Wingfoil is a blazingly fast, highly scalable stream processing framework designed for latency-critical use cases such as electronic trading and real-time AI systems. You define a graph of transformations over streams; Wingfoil drives their execution in a tightly scheduled DAG, either against live data or replayed history.

The Rust engine does the heavy lifting; this wingfoil package gives you the same graph model, operators, and production-ready I/O adapters from Python.


Table of Contents


✨ Features

  • Fast — ultra-low latency and high throughput with an efficient DAG execution engine written in Rust.
  • Simple and obvious — define your graph with fluent operators; Wingfoil manages scheduling and data propagation.
  • Backtesting out of the box — switch from real-time to historical replay by flipping a single flag.
  • Production I/O adapters — CSV, KDB+, etcd, ZeroMQ, iceoryx2, FIX 4.4 (incl. TLS), Prometheus, and OTLP — ready to plug into your graph.
  • Multi-language — Rust crate and Python package today, WASM/JS/TS planned.

📦 Installation

pip install wingfoil

Wingfoil wheels are published for Linux, macOS, and Windows on CPython 3.8+.

Optional adapters require the matching server/library (KDB+, etcd, iceoryx2, a FIX counterparty, OTLP collector, etc.) but no additional Python dependencies — the adapter clients are compiled into the wheel.


⚡ Quick Start

from wingfoil import ticker

(
    ticker(1.0)                       # tick every second
        .count()                      # 1, 2, 3, ...
        .map(lambda n: f"hello, world {n}")
        .logged(">>")                 # INFO-log each value
        .run(realtime=True, duration=3.0)
)
[INFO wingfoil] 0.000_092 >> hello, world 1
[INFO wingfoil] 1.008_038 >> hello, world 2
[INFO wingfoil] 2.012_219 >> hello, world 3

run() blocks until the stop condition is reached. Pass any of:

Argument Type Meaning
realtime bool True uses wall-clock time; False is historical replay.
start float | datetime Historical start (Unix-seconds float or UTC datetime).
duration float | timedelta Stop after this many seconds of graph time.
cycles int Stop after this many engine cycles.

🧠 Core Concepts

  • Stream — a time-stamped channel of values. Streams are produced by sources (ticker, constant, I/O adapters) and transformed with operators (.map, .filter, .distinct, ...). Every operator returns a new Stream.
  • Node — anything schedulable. A Stream is a Node that also carries a value; pure side-effect sinks (.for_each, .csv_write, .zmq_pub, ...) return a Node.
  • Graph — a bundle of roots that share one engine run. Use Graph([...]) when you have several independent stream branches that must execute together (e.g. publisher + subscriber + monitoring).
  • Active vs. passive upstreams — an active upstream triggers downstream execution on tick; a passive upstream is read but does not trigger. Most built-in operators use active inputs; .sample(trigger) is the common way to fire a stream from a different clock.

Run Modes

  • realtime=True — the engine tracks wall-clock time. Use with live inputs (sockets, brokers, iceoryx2, etc.).
  • realtime=Falsehistorical replay, driven by event timestamps. Ideal for backtests and deterministic tests. In historical mode the graph runs as fast as the CPU allows; time advances purely from source events.

🧰 Stream Operators

All methods are available on Stream instances. Examples assume from wingfoil import ticker, constant, bimap, Graph.

Source operators

Operator Description
ticker(period) Emit once every period seconds. Returns a Node.
constant(value) Emit value once on the first cycle.

Transforming values

Operator Description
.map(f) Apply f(value) to each tick.
.filter(pred) Drop values where pred(value) is false.
.distinct() Drop consecutive duplicates.
.difference() Emit current - previous.
.delay(seconds) Replay values delayed by seconds.
getattr(s, 'not')() Logical/arithmetic negation (the literal method name is not; invoke via getattr because not is a Python keyword).
.limit(n) Pass through at most n values, then stop.
.sample(trigger) Re-emit the current value on each trigger tick.

Aggregation

Operator Description
.count() Emit tick count: 1, 2, 3, ...
.sum() Running sum (values must be numeric).
.average() Running mean (values must be numeric).
.buffer(n) Tumbling window of size n.
.collect() Accumulate every value into a list emitted each cycle.
.with_time() Pair each value with graph-time as (seconds, value).
.dataframe() Collect [(time, value), ...] for pandas (see below).

Observing and sinking

Operator Description
.inspect(f) Call f(value) and pass the value through.
.logged("label") INFO-log each value and pass it through.
.for_each(f) Terminal sink: f(value, time) on every tick.
getattr(s, 'finally')(f) Terminal sink: f(final_value) called once at shutdown (literal method name finally collides with Python's keyword, so use getattr).
.peek_value() After run(), inspect the last emitted value.

Execution

Operator Description
.run(realtime, start=, duration=, cycles=) Build and run a one-root graph.
Graph([...]).run(...) Build and run a multi-root graph.

Example: most operators in one pipeline

from wingfoil import ticker

avg_of_odds = (
    ticker(0.1)
        .count()
        .filter(lambda x: x % 2 == 1)   # 1, 3, 5, ...
        .map(float)
        .average()                      # running mean
        .logged("avg")
)

avg_of_odds.run(realtime=False, cycles=10)
print("last:", avg_of_odds.peek_value())

🧱 Composing Streams: Graph, bimap, CustomStream

Graph — run several roots together

from wingfoil import ticker, Graph

quotes = ticker(0.1).count().map(lambda i: 100 + i).logged("quote")
heartbeat = ticker(1.0).count().logged("heartbeat")

Graph([quotes, heartbeat]).run(realtime=True, duration=2.5)

bimap — fuse two streams

from wingfoil import ticker, constant, bimap

a = ticker(0.1).count()                       # 1, 2, 3, ...
b = constant(0.5).sample(ticker(0.1))         # 0.5 on every tick

(bimap(a, b, lambda x, y: x + y)
    .logged("sum")
    .run(realtime=False, cycles=5))

CustomStream — write your own operator in Python

Subclass CustomStream and implement cycle():

import math
from wingfoil import ticker, CustomStream

class Polynomial(CustomStream):
    """Sum of upstream[i] * 10**i."""

    def cycle(self):
        value = sum(
            src.peek_value() * math.pow(10, i)
            for i, src in enumerate(self.upstreams())
        )
        self.set_value(value)
        return True

source = ticker(0.1).count()
(
    Polynomial([source] * 3)
        .map(lambda x: x * 0.01)
        .logged("poly")
        .run(realtime=False, cycles=5)
)

🕰️ Backtesting with Historical Mode

Pass realtime=False to drive the graph from source timestamps rather than the wall clock. Add start= if your sources require a specific epoch start (such as kdb_read), and cap the replay with duration= or cycles=.

from datetime import datetime, timezone
from wingfoil import ticker

stream = ticker(0.01).count().collect()
stream.run(
    realtime=False,
    start=datetime(2025, 1, 1, tzinfo=timezone.utc),
    cycles=5,
)
print(stream.peek_value())   # [1, 2, 3, 4, 5]

Historical mode is deterministic — it's the right mode for unit tests and strategy backtests.


🐼 Pandas Integration

wingfoil ships with two pandas helpers:

  • stream.dataframe() — collects (time, value) pairs into a list; combine with wingfoil.to_dataframe to materialise a pandas.DataFrame.
  • wingfoil.build_dataframe({"col": stream, ...}) — aligns several .dataframe() streams by graph time.
from wingfoil import ticker, Graph, build_dataframe

source = ticker(0.01).count().limit(5)
prices = source.map(lambda i: 100 + i).dataframe()
quantities = source.map(lambda _: 10).dataframe()

Graph([prices, quantities]).run(realtime=False)

df = build_dataframe({"price": prices, "qty": quantities})
print(df)
#       time  price  qty
# 0  0.0e+00    101   10
# 1  1.0e-02    102   10
# ...

A single-stream variant using to_dataframe:

from wingfoil import ticker, to_dataframe

stream = (
    ticker(0.01)
        .count()
        .limit(5)
        .map(lambda i: {"price": 100 + i, "qty": 10})
        .dataframe()
)
stream.run(realtime=False)
df = to_dataframe(stream.peek_value())
print(df)

🔌 I/O Adapters

All adapters are exposed from the top-level wingfoil module. Every write method (csv_write, kdb_write, etcd_pub, zmq_pub, iceoryx2_pub, otlp_push) returns a Node — drive it by calling .run(...).

CSV

Read a CSV file into a stream of dicts (keys = column headers, values = strings). The file must have a header row and a timestamp column encoded as integer nanoseconds since the Unix epoch.

from wingfoil import csv_read

rows = csv_read("prices.csv", time_column="time_ns").collect()
rows.run(realtime=False)
print(rows.peek_value())         # [{'time_ns': '...', 'sym': 'AAPL', ...}, ...]

Write a stream of dicts to CSV. Headers are inferred from the first dict; a time column with graph-time nanoseconds is prepended automatically.

from wingfoil import ticker

(
    ticker(0.1)
        .count()
        .limit(5)
        .map(lambda i: {"sym": "AAPL", "price": 100.0 + i})
        .csv_write("out.csv")
        .run(realtime=False)
)

KDB+

Start a q process (q -p 5000) and create the target table:

test_trades:([]time:`timestamp$();sym:`symbol$();price:`float$();qty:`long$())
from wingfoil import ticker, kdb_read

HOST, PORT, TABLE = "localhost", 5000, "test_trades"

# Write: each dict becomes one row; "columns" names the non-time columns.
(
    ticker(1.0).count().limit(10)
        .map(lambda i: {"sym": "AAPL", "price": 100.0 + i, "qty": i * 10 + 1})
        .kdb_write(
            host=HOST, port=PORT, table=TABLE,
            columns=[("sym", "symbol"), ("price", "float"), ("qty", "long")],
        )
        .run(realtime=False)
)

# Read: time-sliced query; returns a stream of dicts.
# `start` and `duration` bound the replay window against the KDB time column.
rows = kdb_read(
    host=HOST, port=PORT,
    query=f"select from {TABLE}",
    time_col="time",
    chunk_size=10_000,
).collect()
rows.run(realtime=False, start=946684800.0, duration=86400.0)
print(rows.peek_value())

Supported kdb_write column types: "symbol", "float", "long", "int", "bool".

etcd

Start etcd (docker run --rm -p 2379:2379 gcr.io/etcd-development/etcd:v3.5.0).

from wingfoil import ticker, etcd_sub

ENDPOINT = "http://localhost:2379"

# Publish: each dict = {"key": str, "value": bytes}, or a list of them per tick.
(
    ticker(1.0).count().limit(3)
        .map(lambda i: {"key": f"/wf/item/{i}", "value": str(i).encode()})
        .etcd_pub(ENDPOINT, lease_ttl=30.0, force=True)
        .run(realtime=True)
)

# Subscribe: snapshot + watch events under a prefix; each tick = list[event].
events = etcd_sub(ENDPOINT, "/wf/").inspect(print)
events.run(realtime=True, duration=2.0)

Event dicts have shape: {"kind": "put"|"delete", "key": str, "value": bytes, "revision": int}.

ZeroMQ

Cross-language compatible — the Rust publisher/subscriber inter-operate with Python on both sides.

Direct mode — hard-coded address, no discovery infrastructure:

# zmq_pub.py
import wingfoil as wf

(
    wf.ticker(0.5).count()
        .map(lambda n: str(n).encode())
        .zmq_pub(port=7779)
        .run(realtime=True)
)
# zmq_sub.py
import wingfoil as wf

data, status = wf.zmq_sub("tcp://127.0.0.1:7779")
data_node = data.inspect(lambda msgs: [print("msg:", m) for m in msgs])
status_node = status.inspect(lambda s: print("status:", s))
wf.Graph([data_node, status_node]).run(realtime=True)

zmq_sub returns (data_stream, status_stream). Each data_stream tick yields list[bytes] of messages received that cycle. status_stream yields "connected" / "disconnected".

etcd discovery — publishers register under a service name; subscribers look it up. Useful for dynamic deployments. Requires a running etcd.

# publisher
wf.ticker(0.5).count().map(lambda n: str(n).encode()) \
    .zmq_pub_etcd("quotes", 7779, "http://127.0.0.1:2379") \
    .run(realtime=True)

# subscriber
data, status = wf.zmq_sub_etcd("quotes", "http://127.0.0.1:2379")

For multi-host deployments where 127.0.0.1 isn't routable, use zmq_pub_etcd_on(name, address, port, endpoint).

iceoryx2 (shared memory)

Zero-copy pub/sub over shared memory. Requires building wingfoil with the iceoryx2 feature (opt-in; see Build from Source).

from wingfoil import ticker, iceoryx2_sub, Iceoryx2ServiceVariant, Iceoryx2Mode, Graph

service = "wingfoil/demo"

sub = iceoryx2_sub(
    service,
    variant=Iceoryx2ServiceVariant.Local,   # or Ipc
    mode=Iceoryx2Mode.Signaled,             # Spin | Threaded | Signaled
)
sub = sub.inspect(lambda msgs: print("received:", msgs)).collect()

pub = (
    ticker(0.1).count()
        .map(lambda n: f"tick {n}".encode())
        .iceoryx2_pub(service, variant=Iceoryx2ServiceVariant.Local)
)

Graph([pub, sub]).run(realtime=True, duration=0.5)

Both ends accept variant (Ipc for cross-process, Local for same-process), history_size, and publisher-side initial_max_slice_len.

FIX protocol

FIX 4.4 initiator, TLS initiator, and acceptor. All return (data_stream, status_stream); TLS additionally returns a sender object for sending outbound messages.

from wingfoil import fix_connect

data, status = fix_connect(
    host="fix.example.com",
    port=9876,
    sender_comp_id="MYCOMP",
    target_comp_id="BROKER",
)

messages = data.inspect(lambda msgs: [print("fix:", m) for m in msgs])
states = status.inspect(lambda ss: [print("session:", s) for s in ss])

import wingfoil as wf
wf.Graph([messages, states]).run(realtime=True, duration=10.0)

Each data tick yields a list[dict] where every dict is {"msg_type": str, "seq_num": int, "fields": [(tag, value), ...]}. Status values are "disconnected" | "logging_in" | "logged_in" or a dict {"status": "logged_out"|"error", "reason"|"message": str}.

TLS initiator (e.g. LMAX) with a sender:

from wingfoil import fix_connect_tls

data, status, sender = fix_connect_tls(
    host="fix-marketdata.london-digital.lmax.com",
    port=443,
    sender_comp_id="USERNAME",
    target_comp_id="LMXBL",
    password="secret",
)

# Send a FIX message on the session:
sender.send({
    "msg_type": "V",
    "fields": [(262, "req1"), (263, "1"), (264, "0")],
})

Acceptor:

from wingfoil import fix_accept

data, status = fix_accept(port=9876, sender_comp_id="MYCOMP", target_comp_id="INIT")

Prometheus

Expose any stream as a gauge metric on a Prometheus-compatible /metrics endpoint.

from wingfoil import ticker, Graph, PrometheusExporter

exporter = PrometheusExporter("0.0.0.0:9091")
exporter.serve()                              # bind and start the HTTP server

tick_count = ticker(1.0).count()
requests_count = ticker(0.1).count()

Graph([
    exporter.register("tick_count", tick_count),
    exporter.register("requests_count", requests_count),
]).run(realtime=True, duration=5.0)

Scrape with curl http://localhost:9091/metrics.

OpenTelemetry OTLP

Push any stream's value to an OTLP HTTP collector as a gauge metric.

from wingfoil import ticker

(
    ticker(1.0).count()
        .otlp_push(
            metric_name="wingfoil_ticks",
            endpoint="http://localhost:4318",
            service_name="demo",
        )
        .run(realtime=True, duration=10.0)
)

🛠️ Build from Source

Most users should pip install wingfoil. To build locally (e.g. to enable the iceoryx2 feature or develop against the bindings), see build.md.

git clone https://github.com/wingfoil-io/wingfoil
cd wingfoil/wingfoil-python
pip install maturin
maturin develop                               # or: maturin develop --features iceoryx2
pytest

📢 Release Status & Feedback

The Wingfoil Python module is currently a beta release. APIs are stabilising and we would love your input — especially if you:

  • are interested in contributing,
  • know of a project Wingfoil is a good fit for,
  • want to request a feature, or
  • have any feedback.

Email us at hello@wingfoil.io, open a GitHub discussion, or browse the issue tracker.

More resources:

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

wingfoil-7.0.1-cp314-cp314-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.14Windows x86-64

wingfoil-7.0.1-cp314-cp314-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp314-cp314-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

wingfoil-7.0.1-cp313-cp313-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.13Windows x86-64

wingfoil-7.0.1-cp313-cp313-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp313-cp313-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

wingfoil-7.0.1-cp312-cp312-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.12Windows x86-64

wingfoil-7.0.1-cp312-cp312-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp312-cp312-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

wingfoil-7.0.1-cp311-cp311-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.11Windows x86-64

wingfoil-7.0.1-cp311-cp311-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp311-cp311-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

wingfoil-7.0.1-cp310-cp310-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.10Windows x86-64

wingfoil-7.0.1-cp310-cp310-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp310-cp310-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

wingfoil-7.0.1-cp39-cp39-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.9Windows x86-64

wingfoil-7.0.1-cp39-cp39-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp39-cp39-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

wingfoil-7.0.1-cp38-cp38-win_amd64.whl (10.8 MB view details)

Uploaded CPython 3.8Windows x86-64

wingfoil-7.0.1-cp38-cp38-manylinux_2_38_x86_64.whl (13.6 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.38+ x86-64

wingfoil-7.0.1-cp38-cp38-macosx_11_0_arm64.whl (9.7 MB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

File details

Details for the file wingfoil-7.0.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 4cf716d93dcd132b5884c011645b458e572d031b446e8b08df7b617dcd6d6388
MD5 2c6c96594567ca455ec79d4ee0d43afd
BLAKE2b-256 82fd049c4ef2a3c8337f73ed376613c08c3726c838f0e2e07c2245ace3b2ff76

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp314-cp314-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp314-cp314-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 7a3e00208fe859096f4a6b70f966c4226aaf73ef74338b24bbfe184ab2e1fda6
MD5 2727a6a29a50a2dda191ce3f5c6c01ef
BLAKE2b-256 076536c1af7d3a7eda71aa37f09ee5ba50f30c15b31d59b0e7d3c8142619b504

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3f10c3a72092c23ac54ec00e862a60f7f87436fabf5de20ebf5c75e9666d1474
MD5 7e2f68ffd7a4c209f6e9195fc346204c
BLAKE2b-256 d74de12511a965a5bbba803c1277c878d119fe7b845a8061b728d59bb00b49e3

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8814e5545499fd8d42aa8c16b2f1957ae19efeb8a83fc3b576de8e69e440f76a
MD5 e0017740f933b72447bd4efa1c1adbb3
BLAKE2b-256 44ca7328acbed56f072d2adf7d89bfdda734bcab579678c62e1ebac33be1c11e

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp313-cp313-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp313-cp313-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 7b0e4cb446f7e6ac6c4730f9dbb0d920e7fcdd59f5609a97ab70db04dedb5ab9
MD5 d166c62de0dca0d47264d9328f940290
BLAKE2b-256 e3bbae473897fdd03ceb5a8083c32945076166d14ebea11f40d3c407854b2f51

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4143748175e19e2756e1ce4fbdfc5ecf39462d7137eb4d171b2b2696a806de92
MD5 7d3c11cac4f99ca28494b25eca9a729f
BLAKE2b-256 2fd9b0a495151c1704552e8c768237bff4f6e41f7caf8049ff67de05ef8b5f4d

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 2b9c13eb230e427adf465714af3beac396da28b84fcc56a0ffb404450bca7e34
MD5 914934fc36c064a763f0500cd452d626
BLAKE2b-256 8347d3a1588e5020c1b7639a266b1d04b88c05eafa5a642bb015e0f8b79cb03a

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp312-cp312-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp312-cp312-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 664765d989bb6cdcfa80ccc65e6a69ab89e73c6b64ad7c09626574f14515e078
MD5 02091b4778e271fcb080393b11c241e4
BLAKE2b-256 e9334b359a53628ef2ea5ed57757ec16026fdf1842496084f7d8578807a67599

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fd0536d84443c10555c62e7bfc4fe71b2e51d107671735e8622a14ae7736a3bc
MD5 5cb6ebf8cd1e0bf2357be2a9e6db185f
BLAKE2b-256 e53ee4a07e16570498b241c5dee23a62bd4e79dd34143a23bc1d7547f8537dd2

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 2205a8dfb1719de1f1c54b77352d0011c329be2bc2e1e7e5be9da12b75607e45
MD5 01ee8ee4aa8efc1b499e7dc924d0cf20
BLAKE2b-256 8341f6f73685ffce3a68f759fa6f5390a2453000a7660263a1adc78d8a0483a0

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp311-cp311-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp311-cp311-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 43df3cd38b81c342e516a9b133c17cfc251e5ddec6acde9b110cc75e90346110
MD5 7cac0761bbb6b342d9e6e24148974468
BLAKE2b-256 c34f56a74ad03f1e40250b43789e0802af1ec920a8f695ccfbfe39d128eb4566

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5dd553e14c079f15b95141e50d6b8b477a947f41f034a412f3a5c19dd9fcd2e9
MD5 c4b30edbaafeccaf615a17fe967317c5
BLAKE2b-256 da6bbe4e01ab157b4d853789a012774256f78a31685af5534f67508537dac5dd

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 723aeb3bc7ef28f283f5893f02fbbb2ade650a6affc5430de8d20bace11459a2
MD5 9255d8d83644c21ca9cb51fcfb9a2f4c
BLAKE2b-256 7b80d58b2cf1adccc0c36f03b530abfd6ae3bd6f74b684a57cd9debb9cb79309

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp310-cp310-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp310-cp310-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 e024e43cd439e519c2a8ae3d1d0c05df90ca7046b5ece16f13d5db3ed92b7637
MD5 ff8ae1e41abc1c28dc938be10f20ad8c
BLAKE2b-256 8d65e4e18df03156fb8fb6e484c953c975fe72aacbd72446fb2b8ca6d418a0fc

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d1fce426afc9ce014754d3fd8d4b9ed87bf542dee6ff0387fdf14f7deeab2f6d
MD5 0c10baba65c783666fb072e21b33ed74
BLAKE2b-256 5ff4cbb1f1b63b159da0856dda5f8e55a1d5e73c9b430d3e680254df0803758d

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 648a2e03cf23b13f8a5b542c8d9ad6d0957b9aceecef77a5bc8000299f8a0a97
MD5 4ba61efae79088f25c073d332e3138ca
BLAKE2b-256 2508bb88154f586da29a6c4b4cc879cab717b8595fbaecf15eef4d77df48b6fa

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp39-cp39-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp39-cp39-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 98877acabf739e72543bebb5312eb547e07d922ab38271e61b16411c2b8eea5f
MD5 4f25982e8b9227d1b08432aa5464272b
BLAKE2b-256 829879e034f8c14c4c291bc46a9ca7e0caebdb07e5ccd363356c6f17d5d81ff1

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 51cf6b344cfd71363537ce6887e0070e19db52cc8dfd64f24db84e3b0c101413
MD5 4c0c9f8bc92d76c422428604f7533516
BLAKE2b-256 84ded0c7b43a77f14d3172fda0ce2975045962182cb678bc2dc6065350ebaee7

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: wingfoil-7.0.1-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 10.8 MB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wingfoil-7.0.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 a4efe65d03bdfb571c5203f1710c7bedb8c4bee9565b86d784108b58b2b71a3b
MD5 bb769a52f14e0fd633568c3eaba2cb6f
BLAKE2b-256 79c123a8c116d9dfbf0b2fa9008f7523dfbe6c7c05d62192447ae932deeb3b4b

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp38-cp38-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp38-cp38-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 6feb5b67e5c8d1623a97c845d8e53a7f68cd81cef8adb4f9dfba42859d81d0bd
MD5 3fb5074f45b487476615b087cfb9ec4b
BLAKE2b-256 410f0bf7d78590212ead575ab05e0db7129adddb325e140ef297ccdd6b6e5034

See more details on using hashes here.

File details

Details for the file wingfoil-7.0.1-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wingfoil-7.0.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 70e4f5389d8472fcc2c9adb5d3ada94aca9446867652a69aa48bff887a89558c
MD5 87950f57b2bea98ee0ca5b4aab58ef01
BLAKE2b-256 6c30c29e5dce0144ca6d3c4e0dc472536b8f2e42f1baec4080a0929dfa3424dd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page