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

Uploaded CPython 3.14Windows x86-64

wingfoil-6.0.5-cp314-cp314-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp314-cp314-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

wingfoil-6.0.5-cp313-cp313-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.13Windows x86-64

wingfoil-6.0.5-cp313-cp313-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp313-cp313-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

wingfoil-6.0.5-cp312-cp312-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.12Windows x86-64

wingfoil-6.0.5-cp312-cp312-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp312-cp312-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

wingfoil-6.0.5-cp311-cp311-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.11Windows x86-64

wingfoil-6.0.5-cp311-cp311-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp311-cp311-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

wingfoil-6.0.5-cp310-cp310-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.10Windows x86-64

wingfoil-6.0.5-cp310-cp310-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp310-cp310-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

wingfoil-6.0.5-cp39-cp39-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.9Windows x86-64

wingfoil-6.0.5-cp39-cp39-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp39-cp39-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

wingfoil-6.0.5-cp38-cp38-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.8Windows x86-64

wingfoil-6.0.5-cp38-cp38-manylinux_2_38_x86_64.whl (12.9 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.38+ x86-64

wingfoil-6.0.5-cp38-cp38-macosx_11_0_arm64.whl (9.1 MB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 c382e792acd9f46bab1287a81b8316e4d352c0f31e6084dde680233368bde838
MD5 e7306c43450e0735a3e2f0fbed1922d7
BLAKE2b-256 6250529f92355c76e451a99eaf893c748b6900ff5d1dbbf79ae8ca259365374f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp314-cp314-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 250f442db1d14e86436d45b46ad208ea4484d05a91a5345c20a46683b785fae3
MD5 db3d24fbe72101f3d0bd49e599a11d2e
BLAKE2b-256 db17f302f0c2eaac47f706d43cee7c3e0c0c6f9ad589924c15775c3d048272ee

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 986d89ac7f336f32253c62364ff7f8b818287da16357530fa6fbc0ceba81445f
MD5 e3c74f3ef7c680e53d78739219313f12
BLAKE2b-256 800d654227065574626af55fa2eec18a2221b71f66c7adb8f35fd9dcce821759

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 1a4382b6447268782f6b049067d5c3dc999f95dd687bf17ffdc016c557916046
MD5 500c8e66c66b6f2e0d2da3ce1e3789b2
BLAKE2b-256 ba90fff84e78f237568e198f4fc6a5b804e81a0a4ce914cfda6e2eb6943432f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp313-cp313-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 5349cf5d30214663189d34f00048cc852a8e609dc20ca1564e281968a8df56d8
MD5 1384645ec077fd12f1aec63c1b9ced57
BLAKE2b-256 463eb08c9e04f327a2c634b3b86ad9ba63f249ebd0ee6c5817ceb51e5767ea08

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c02615bb22e99255446e716c23cb2209ad934707cb748de3aacf21a7c3abc9fa
MD5 8337618eb2a3c37ff23456f86e41d179
BLAKE2b-256 d1757bc7e68cf74aa4f2efc0639570b4314ecb45d02e9cdb2b29959470555a39

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0888333e216db5143928488de473d612d1dfdaca659947cbd974b03327a63418
MD5 6917ee8f658f48823af9c10db234c190
BLAKE2b-256 327692ea0d8d67ef975a7606611ccdeb63740fbcc5b229fbc3c7c992fb13cea6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp312-cp312-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 8bf14bbf3382d514dc50a0ae728fdfa7b532c8297559c40f22764dfe341956ef
MD5 690001fbcd6289320d8b9a778a9c2915
BLAKE2b-256 2aebc96b09215bb6aa59692427dec45434679c70f48cc1c782fd4d455064736b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7ba03c5e0a5a58bcdbbf5f3df0fa2ec474908f096ecfeb5e382fdefb561430c0
MD5 6d725c12b633faa07384a83e6c278696
BLAKE2b-256 893a2ba17ae94b1d092e11d3e711097aae15ecbe3f45941d509b5c91f104d3f7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 3bc880aecc1a9e200176ecbb2cefbf5b43db351d81ee6b0b46e5e0ab562c4341
MD5 938863da236b9674c7313c75f45d0f61
BLAKE2b-256 fdd3843cc88f21741bece45c9242398fff36f3e0d4bbeb63b4b74e9e42e7d1e0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp311-cp311-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 deca45d9c02179830d55c3c3b0c6430eb653bdaad3111e122d6b65afadb8c350
MD5 2cf442ff9216a2157240377b96d14326
BLAKE2b-256 04a05426a360325cb547c4c21c2fba559ddf2bcc7bdb6280a552e7463a599f73

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 947bf2ab999af2bd5c1d9c1a175f005db357cf10c6bea4512a9b5bf26b69fd05
MD5 f81ac54b67648bc669de43c60fba27b8
BLAKE2b-256 f9bf47342216a21c81eafd0855896b1a14eb6b6b19a65f100c287ff1e2cba201

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 4c913179fe995488356d8fd8a94ce184cf344e96e37afa7edf2803c101a8f545
MD5 a2149e065cf5c1b13c4da806632cc5a4
BLAKE2b-256 a6c1949abee3828de6b5df309d73ff681f73191f7d8cbfc1337064be833538e3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp310-cp310-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 790afe9e8fc7d128daa7e8182fee4492a04ff790b049ad05d97fe10b869fc754
MD5 9f640814fe3bfee2e1c67629759cd6d0
BLAKE2b-256 8d382c9c8823e85c174233be91a74d7a532d47b001676c96f9c626c2e52a5bbc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b16804381679791df2b2224028ebdbc3f44fdd6e0cea88b71f00a6418d596d45
MD5 ba9eb9a468c30de1cbd8406310e5a99c
BLAKE2b-256 e0082d89f5bfb7d910270814fc896e1ccecf9b71039dbba3647e374472a55476

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 2ec85396b1ea82010cc4480d6599d912cdcabc1851537835931c145595a8c0ef
MD5 d6dc803cf587f9896b20c599bb6986ce
BLAKE2b-256 8f825db0e649b5b420657b8a0043f8e1684a3fb22bd129504654f626f8e3f754

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp39-cp39-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 ea58b780885013ad42175d61d97a43a99e7da9ce84cc490dc1c0fc492cdbe900
MD5 59b2bf074510ba5fff0bd8bd1fa2b08c
BLAKE2b-256 ec3f148b96ef05988069a966106b6fa950d8ac2e762ab365d168c450f138d639

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c47ca3199b9e758237fb15a0df9689c01c5133eba4b5eef55ef3e9142e07abd3
MD5 c28549d8893132daeebfde4b394891a4
BLAKE2b-256 bc39e417b78fe616a14785af3e1927930958390b11076fa3a01d98dfcfda27d9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: wingfoil-6.0.5-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 10.1 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-6.0.5-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 2393f70c8053dd5b8cd0d44652b413183523eac511e19821c5a2090d44c1c80d
MD5 4e2c5ae7bbf60e559d07c5c96988cf0d
BLAKE2b-256 4acd0668345a522150435c82bfa085d4111ef120898746a17405560fcd27bfa7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp38-cp38-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 9e91940c2b9f1c5299b22527c739d770b057117015a1876195df37e10a8628da
MD5 4077e069d353bce24cb1d0fcc9fb0017
BLAKE2b-256 7008888439adef18b0f16942e49057ebc2fad5fd5bc48ee809885f43a541057a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for wingfoil-6.0.5-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 481b0915a81b583d4a3c778f7ad1b412afa86939560df85a7cd0592bc07b8c8c
MD5 22db4453188a7165123b97d0b6431afa
BLAKE2b-256 c95c02e253f102a19f0fe6064199e4e93a39a6d45b9c94997a0c78fff344546a

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