DataCurrent
Python streaming, made simple.
DataCurrent is a production-ready asynchronous streaming library. It gives you one consistent API for lists, async generators, queues, WebSockets, Server-Sent Events and streaming HTTP responses.
Version 1.0.0 · Stable / Production
- 279 tests passing, with 100% line and branch coverage.
- Required networking dependencies install automatically.
- No broker, database, API key or hosted service.
Install
pip install datacurrent
Python 3.11 or newer is required. httpx and websockets are installed with the
package, so HTTP streaming, SSE and WebSocket clients work immediately.
Framework helpers are optional:
pip install "datacurrent[fastapi]"
pip install "datacurrent[starlette]"
pip install "datacurrent[all]"
Quick start
import asyncio
from datacurrent import Stream
async def main() -> None:
result = await (
Stream.from_iterable(range(10))
.filter(lambda number: number % 2 == 0)
.map(lambda number: number * number)
.take(4)
.collect()
)
print(result) # [0, 4, 16, 36]
asyncio.run(main())
Streams are lazy and single-consumer:
stream = Stream.from_iterable([1, 2, 3])
async for item in stream:
print(item)
# A second iteration raises StreamConsumedError.
Common terminals:
await Stream.from_iterable([1, 2, 3]).collect() # [1, 2, 3]
await Stream.from_iterable([1, 2, 3]).count() # 3
await Stream.from_iterable([3, 1, 2]).reduce(max) # 3
await Stream.empty().first("fallback") # "fallback"
Async callbacks work everywhere a callback is accepted:
users = await Stream.from_iterable(user_ids).map(fetch_user, concurrency=8).collect()
Operators
map, filter, flat_map, take, skip, batch, buffer, distinct,
enumerate, window, debounce, throttle, timeout, retry, recover,
tap, zip, merge and concat.
batches = Stream.from_iterable(range(1_000)).filter(lambda number: number % 3 == 0).batch(100)
async for batch in batches:
print(len(batch))
Backpressure
Buffers are bounded and block the producer by default. Data is not silently dropped.
stream = Stream.from_iterable(range(100_000)).buffer(size=64)
Lossy behaviour must be explicit and is counted:
stream = Stream.from_iterable(range(10_000)).buffer(
size=16,
overflow="drop_oldest",
)
items = await stream.collect()
print(len(items), stream.stats["dropped"])
Policies: block, drop_newest, drop_oldest, error.
Real-time data
WebSocket
from datacurrent import WebSocketStream
async with WebSocketStream.connect("wss://example.com/events") as stream:
await stream.send_json({"subscribe": "trades"})
async for message in stream:
print(message)
Server-Sent Events
from datacurrent import SSEStream
async with SSEStream.connect("https://example.com/events") as stream:
async for event in stream:
print(event.event, event.json())
Streaming HTTP
from datacurrent import HTTPStream
async with HTTPStream("https://example.com/feed.ndjson") as response:
async for line in response.iter_lines():
handle(line)
Fan-out and events
from datacurrent import Channel, EventBus
channel = Channel(buffer_size=64)
first = channel.subscribe()
second = channel.subscribe()
await channel.publish("deploy finished")
bus = EventBus()
@bus.subscribe("user.*")
async def on_user(event):
print(event.topic, event.data)
await bus.publish("user.created", {"user_id": 123})
Retries
from datacurrent import RetryPolicy
stream = Stream.from_factory(connect_and_read).retry(
RetryPolicy(max_attempts=3, base_delay=0.2, jitter=0.1)
)
Retries require a replayable source, such as a factory or a list. A consumed
generator raises NonReplayableStreamError instead of silently restarting.
Why DataCurrent
- One model for iterables, queues, HTTP, SSE and WebSockets.
- Backpressure by default, with explicit and counted drop policies.
- Bounded concurrency and cancellation-safe cleanup.
- No infrastructure: no broker, database or external account.
- Explicit delivery semantics; no false durability claims.
- Typed API and sync or async callbacks throughout.
HTTP clients such as httpx and aiohttp handle requests; DataCurrent adds the
stream engine around them. Reactive libraries provide operator algebra, while
broker frameworks require Kafka, Redis or RabbitMQ. DataCurrent is the
in-process streaming layer that works without any of them.
Compatibility and limits
- Python 3.11+ on asyncio; no Trio or AnyIO backend.
- In-memory
ChannelandEventBusdelivery is at most once. - No durable broker adapters or OpenTelemetry exporter in 1.0.0.
- Not published to PyPI; the project name is provisional.
License
MIT.
Metadata
Release files for datacurrent 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| datacurrent-1.0.0.tar.gz | 49.6 kB | Without provenance | Details for datacurrent-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| datacurrent-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for datacurrent-1.0.0-py3-none-any.whl |
Total release size: 108.9 kB
Release files / datacurrent-1.0.0.tar.gz
| Download URL | datacurrent-1.0.0.tar.gz |
|---|---|
| Size | 49.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a9563629faaffa27504608e6a2719b32e44b7622d0ea15860cac39f776d9bead
|
|
BLAKE2b-256 checksum How to use checksums |
f64459ae7d1d5954f374e78b11dae8b4a0c8d0b2c347c07be0376a1c92b371b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / datacurrent-1.0.0-py3-none-any.whl
| Download URL | datacurrent-1.0.0-py3-none-any.whl |
|---|---|
| Size | 59.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9774639f873fea5a61641a037fe740b8690e76924635bb279da6e2f7f1eb9878
|
|
BLAKE2b-256 checksum How to use checksums |
1c833da65e7bbf3a78300c7289516aaec470b910309383575f88453445066dd8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Security for datacurrent 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.