Python bindings for the wingfoil Rust library
Project description
🚀 Wingfoil
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
- Installation
- Quick Start
- Core Concepts
- Stream Operators
- Composing Streams:
Graph,bimap,CustomStream - Backtesting with Historical Mode
- Pandas Integration
- I/O Adapters
- Build from Source
- Release Status & Feedback
✨ 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 newStream. - Node — anything schedulable. A
Streamis aNodethat also carries a value; pure side-effect sinks (.for_each,.csv_write,.zmq_pub, ...) return aNode. - 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=False— historical 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 withwingfoil.to_dataframeto materialise apandas.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:
- 📚 Python examples: https://github.com/wingfoil-io/wingfoil/tree/main/wingfoil-python/examples
- 🦀 Rust crate docs: https://docs.rs/wingfoil
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wingfoil-6.0.4-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 9.7 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c88499e116c3ecd5c02b1bd8b629ebb588ab788b330162e14f5156762c17aecd
|
|
| MD5 |
0e80dd5b81a74e6c0dcdc7f9da340bc3
|
|
| BLAKE2b-256 |
9f86211d1ae65c1202ab529a3f83ebd4a28ce8d9d9cf0b43451322ff553222ff
|
File details
Details for the file wingfoil-6.0.4-cp311-cp311-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp311-cp311-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 12.5 MB
- Tags: CPython 3.11, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dfeada72b6077e51644b29ccbb1146e578553cc5fd0089ddf0ea367458d0ac79
|
|
| MD5 |
afe99b29249ed2a1a00fa88a7f56dae6
|
|
| BLAKE2b-256 |
04015cf8949d64e4002c408410831449fb760579ecf2a10d0f6f24bbe441e19e
|
File details
Details for the file wingfoil-6.0.4-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b56a766df4ed6ad26fff33610bcc70f164b0372f3135fdb4ecd1cf7efafe2b3b
|
|
| MD5 |
76c8e724b2427bec331dc341bb1be94b
|
|
| BLAKE2b-256 |
9df7d3dcdc109a71cc46ea2144f4564e95b290a10cf1205bb1a3e8f19e5be871
|
File details
Details for the file wingfoil-6.0.4-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 9.7 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0500649105dd39b48189a1f3af248d5dc9f03bd8c6748055a097f912855e03f
|
|
| MD5 |
ccde7c4db645dbeff113904b89334e7f
|
|
| BLAKE2b-256 |
5cea9800404df6db9ffd217f1736e19da3d934b44d3edbaada65b535bf354846
|
File details
Details for the file wingfoil-6.0.4-cp310-cp310-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp310-cp310-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 12.5 MB
- Tags: CPython 3.10, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6bb06f005731e3ad7e055222de8edccb17ff5a9fc3af1649cdcc1140392df25a
|
|
| MD5 |
20891ff72c36a6f988b11f9e24e58b9c
|
|
| BLAKE2b-256 |
dbc70210c649df305b0e8a6c28519cb42bb5f0f2207302d4c4a928b54b069f2b
|
File details
Details for the file wingfoil-6.0.4-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adfc577ba15690622276577adc7437a5dcb2c245615a9e9fbb08ccb88bcbb500
|
|
| MD5 |
8c00ce8772829700511abfecfcbab320
|
|
| BLAKE2b-256 |
3ec09ed5d203f6e731fcb0b587c39625af5352a6c9d7884049bb844b4a9b8479
|
File details
Details for the file wingfoil-6.0.4-cp39-cp39-win_amd64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp39-cp39-win_amd64.whl
- Upload date:
- Size: 9.7 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c6c18d60ecec7666618861365a4efbff510c6913b39aead4d31363f932ca6c7
|
|
| MD5 |
947ddc9b05d3643fa856d37fcd69f955
|
|
| BLAKE2b-256 |
d9f62c87c6a4bb07845efc5bdf8896aee135751ae04f8ab1c378a098bd1e9052
|
File details
Details for the file wingfoil-6.0.4-cp39-cp39-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp39-cp39-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 12.5 MB
- Tags: CPython 3.9, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12b2b20647233c50edb9a385ede8089a91a95b7c2fa68ac351f0a467c090a25f
|
|
| MD5 |
1ac820209c8bfc85d1014235742ea977
|
|
| BLAKE2b-256 |
7b0af7a74dbb5eb4318cd005ed4aa4767f6188e5b248492a822a6268ba9bd29e
|
File details
Details for the file wingfoil-6.0.4-cp39-cp39-macosx_11_0_arm64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp39-cp39-macosx_11_0_arm64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.9, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5004c1adde8708426258ca5f76447b4c9d289810177660ff288781aa7dc1a0b2
|
|
| MD5 |
28dd2bd7076e4852fa167ce2587c36ca
|
|
| BLAKE2b-256 |
6b825f66ee61f7478efbaa08f214850a54f90ddfb9d2e3ba94f0b86c396d87d9
|
File details
Details for the file wingfoil-6.0.4-cp38-cp38-win_amd64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp38-cp38-win_amd64.whl
- Upload date:
- Size: 9.7 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5641d50e84f80832d4551aa684bfb82f68b2dde36e049731a031a18f3651cadd
|
|
| MD5 |
1f25616d694df72965828d9c9d1923da
|
|
| BLAKE2b-256 |
093b6fa8013dba51be146a5f5ad5b4951a527010c7166e2ffa7a6d5beafffbfc
|
File details
Details for the file wingfoil-6.0.4-cp38-cp38-manylinux_2_38_x86_64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp38-cp38-manylinux_2_38_x86_64.whl
- Upload date:
- Size: 12.5 MB
- Tags: CPython 3.8, manylinux: glibc 2.38+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
441df6a94637de803a3c7481365f781cc1e58bb0d8753362cc84dcfce66cf013
|
|
| MD5 |
7d9dd558279976724e63efabc6c2939a
|
|
| BLAKE2b-256 |
a3fa969a13ad811b49c8c387ea2db3b6d541a3f2e1cc5cfd1885842731594194
|
File details
Details for the file wingfoil-6.0.4-cp38-cp38-macosx_11_0_arm64.whl.
File metadata
- Download URL: wingfoil-6.0.4-cp38-cp38-macosx_11_0_arm64.whl
- Upload date:
- Size: 8.8 MB
- Tags: CPython 3.8, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afab9f5426171ba4d7ca2f778e76fd55d4d150d47ab9747f938b3354d935031c
|
|
| MD5 |
6888ae659eb31a18cf1481ed67bf1bc3
|
|
| BLAKE2b-256 |
375a38681e28ef3e7e27916de75eb08e9e4273dcff0106c7e57b735a7aa9b08c
|