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-8.0.0-cp314-cp314-win_amd64.whl (11.0 MB view details)

Uploaded CPython 3.14Windows x86-64

wingfoil-8.0.0-cp314-cp314-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp314-cp314-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

wingfoil-8.0.0-cp313-cp313-win_amd64.whl (10.9 MB view details)

Uploaded CPython 3.13Windows x86-64

wingfoil-8.0.0-cp313-cp313-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp313-cp313-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

wingfoil-8.0.0-cp312-cp312-win_amd64.whl (10.9 MB view details)

Uploaded CPython 3.12Windows x86-64

wingfoil-8.0.0-cp312-cp312-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp312-cp312-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

wingfoil-8.0.0-cp311-cp311-win_amd64.whl (11.0 MB view details)

Uploaded CPython 3.11Windows x86-64

wingfoil-8.0.0-cp311-cp311-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp311-cp311-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

wingfoil-8.0.0-cp310-cp310-win_amd64.whl (11.0 MB view details)

Uploaded CPython 3.10Windows x86-64

wingfoil-8.0.0-cp310-cp310-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp310-cp310-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

wingfoil-8.0.0-cp39-cp39-win_amd64.whl (11.0 MB view details)

Uploaded CPython 3.9Windows x86-64

wingfoil-8.0.0-cp39-cp39-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp39-cp39-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

wingfoil-8.0.0-cp38-cp38-win_amd64.whl (11.0 MB view details)

Uploaded CPython 3.8Windows x86-64

wingfoil-8.0.0-cp38-cp38-manylinux_2_38_x86_64.whl (13.7 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.38+ x86-64

wingfoil-8.0.0-cp38-cp38-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 11.0 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-8.0.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 942eb4fcd43e0aa31c89acf57706931f74ed9f4ff8494a41c10343f06975afaf
MD5 4958b92dd8fbaec81de8e13981e7c795
BLAKE2b-256 5f7d0b25b3b25d2b2d4bbb7f95bb3c70a3a0e45d2cd66ff92181865471a206c4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp314-cp314-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 7e4e8d31e460d7875121a5c0385888c057f550191bc02d012462c5626c19b23b
MD5 7375917c5d8cb995bc71df017ad15b1a
BLAKE2b-256 49796ed5d0798637e6ef360a6528784ab76dde61ca3e49a5df9fe117ec0d9191

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 89efdd99ffa3e56a55752b751e04794db71a3b52d8a707dc8a1a12546c26a2b5
MD5 d3448bde4d7635a21481a5560ad88636
BLAKE2b-256 d13608f80f63445658447d9aa2c49e558bb0e160f77e6957f14d3edb47f86f9d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 10.9 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-8.0.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 7a1c9f0c5d2ba98b767522f3557beb54ff89a5aff9a08ae13ea0775e5f079770
MD5 99efe9c6edbac0e6a3642f7fa82b5b0c
BLAKE2b-256 8556aaf02d6961649260c1fca5a5fd05a3337272fed508e386b7399485a4a9c4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp313-cp313-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 9bfd5a64c3f51ffd07ca4b3ea1c45a3e6f883b2e3a7e20289a2b40363c2e738b
MD5 11200b0e06f33c026e3d4fde61f00db7
BLAKE2b-256 055b4fa5aaea654e37a7261f559caa47e8a06b07b3078e2c6c73b5fdbb3c97be

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7ce2a5d1050680e3d01a9ec615ab247063e91c609b3e835c5564536f2bab45f3
MD5 39ba763eb95bbee4ccfde628a1337b2e
BLAKE2b-256 a0ccf8d9214ced262cf5d8dc9a329d401c90e97e4b22a2a82686193b774dc5f7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 10.9 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-8.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 814445832149b4cdbb2c349d0710124a3b7cc7662df9a9fe69385508fe452a3d
MD5 2cdca8edb06c954bddbaa8188e42b953
BLAKE2b-256 e414497ef3db70b665f354ac6076d382ec9d0cc632b85ebec63bd024b739e808

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp312-cp312-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 dfe6dccc63a749f8498811b4691af78256e85a62a4ab45af793e0d31c6fe83e0
MD5 b9581ce3c604883f27ed8fe85de768ee
BLAKE2b-256 f51d3867ce732ebfcd0442751527fa59b033fc29d9d15ef72c88d2baa8f31517

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1510347397ce57ae56bee50c18e2333c0dcd3c692478f5035dcf7ca9fe01d91f
MD5 ca6d8aa40901d135bd31fb4251900290
BLAKE2b-256 bd5a1303f6bd151a7dc600fe92f2061690a6d2c86bac2c6644e8c97852d0bc4e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 11.0 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-8.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 8edd77179da730fbb150aea56fa49d2aaa0b99d3422205f4f6a19f2969be9059
MD5 7f0a2bc034164ce8ffffcdf9193b1251
BLAKE2b-256 4b56feec4c66293ecd928fb48847fd6ffca8f6fda641feefea3e06ed76ca6282

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp311-cp311-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 5932a2a8dfe3c8fc14c03f6c4bdf9f70b90ac84c592341f70ae3a3fc9933ecfa
MD5 3529a47efefa22cf5928981a5cb07b4c
BLAKE2b-256 e6e3a6692028b4f2e4bd338966e3eb35ede7f12569785f62ad41379fa3f2d090

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 715634c7d226d19c76bc07b9bccba0ed1721e5a0ba9461f25594482ca4e475f9
MD5 1c93d270cc7fdbb8f8877885b18d7c09
BLAKE2b-256 762a3d78ca6946dc0bb6c0589df2ad982cddeb5775b0cd7e02ae2317097b488f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 11.0 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-8.0.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 e25c54f1c55ed28aad9fb196efb077657c8e5a827c0287770e15060bfdf821e2
MD5 f9414d4f19710c6e3161bbce14ab36c6
BLAKE2b-256 9593f3fd067ccf98d9c181eff22a31d01fb48f8c16e85625d9a3099947407ad1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp310-cp310-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 b7c06add5028b91db268ad9bfa8881d7057a36ca7d342ebc9fdbd5b1cf26d45b
MD5 6d482293cfd72f84141a5762cf13fd33
BLAKE2b-256 74866281236511bd1427ff9ae318ef1c5b0a9532b7a948ec2960cac49597293c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1e93e2d00f9130b3b64bf7c4d813674e92b1fa801673cfbea93bd88542111328
MD5 8ca52504ddb9063b0fd52e0857b4ca24
BLAKE2b-256 bf3fbab6765a7c10f2247ce31b1391b584a79ad9cb14d05644c063730c012f6e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 11.0 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-8.0.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 6777d26312cb21291d6bfeb56e6250d108d6fb5d03888255e1d0b0c6f1fe2eea
MD5 07257f95306291799e0151ce09a22ff6
BLAKE2b-256 77c465bc9a549cd85288601dc15174765cc62d328d7e5e254b413b7ba08bb65b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp39-cp39-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 51dccfd781de95d49cbda7bb2d47c5e169f29ecd034f18acb772cfc0e8f7e899
MD5 17d942457384be2156f6ab972dcded70
BLAKE2b-256 c847fbfb2159eee08e1756984a3a719d7cf31a4f91a909ad6f497f292b936b05

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 557ae9b58ac2a4a31325efd19c451093c20065f7054f6d19c5ab5aa6f623aa94
MD5 39553a70344052331d2c18082112d1c2
BLAKE2b-256 2fa95eaa11b821ca24f218e1a06cb1bd4bbbfa9e36766c37b1e75176f0e30ee5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-8.0.0-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 11.0 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-8.0.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 9b5b6e2c56c2ce015fdb1908004f1bdea7c15b343a7bea3dd8650593aaffc2d1
MD5 52294103beae5744e40838eeadf95d55
BLAKE2b-256 2f70790dc5d0992cd6957a1c90ff5a23bb098f41a24af556e86e02f6e14e7b87

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp38-cp38-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 2cdb58b450c6ea4c47696cc7642e2a9100376fea2fed65ae0ecd88e480a42015
MD5 7830a4cc659e455b86b591d2003023d6
BLAKE2b-256 1755958b1054c4e6e0f8a76eb16cafd815bd10223f34bbb81425310794d34562

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-8.0.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5b2f90980b7126667cede0d4f3c4718283fc23e38499a47221542e5b4ba06c34
MD5 6e36b6d46141ae61c0ec4d77cfaedb71
BLAKE2b-256 ed92ba8cebf3c26f92c0b5cc5c641424682891cf871b2eaa9e4d42ea8e0c02cd

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