Yet another python streams library
Project description
tinystream / python-streams
This is a simple and lightweight Streams API inspired by Java Streams with support for type hinting.
This package is release as tinystream
at pypi.
Basic API
from tinystream import Stream
stream = Stream([1, 2, 3, 4, 5]) # Stream.of_many(*), Stream.of_dict()
stream \
.map(lambda x: x + 1) \ # flatmap(), peek(), map_key()
.filter(lambda x: x > 2) \ # filter_key(), filter_type()
.sorted(int, reverse=True) \ # sort()
.reverse() \
.limit(2) \
.concat([4]) \
.sum() # reduce(), max(), min(), collect(), count(), find()
Aggregators
Aggregators like sum()
, count()
, max()
will collect()
the data and end the stream. collect()
also caches the data and can be called multiple times, since it returns only a list
.
Built-in Optional support
Some aggregators like sum()
, max()
are optional:
assert Stream((1, 2, 3, 4, 5)).sum().present
Get next value as optional:
assert Stream((1, 2, 3, 4, 5)).next().present
Create custom optional:
from tinystream import Opt
assert Opt(None).absent
Map optional:
assert Opt("String").len == 6
Get default value:
assert Opt(None).get(6) == 6
assert Opt(None).get(lambda: 6) == 6
assert Opt(None).if_absent(lambda: 3).present
Filter value:
assert Opt(0).filter(lambda x: x > 0).absent
You can also access optional index elements of the stream, but this will collect()
and end the stream.
assert Stream([])[2].absent
Type hinting
You can typehint datatypes like:
from dataclasses import dataclass
@dataclass
class Node:
name: str
parent: "Node" = None
parent = Node(name="B")
child = Node(name="A", parent=parent)
for lambdas:
stream = Stream([child])
assert stream.map(lambda x: x.parent).type(Node).next().get().name == "B"
This is not necessary when you pass a mapping function:
def map_parent(n: Node):
return n.parent
assert stream.map(map_parent).next().get().name == "B"
More features
Typed dictionaries
Dictionaries are streamed as tuple(key, value)
children = {"a": Node(name="Child")}
stream = Stream.of_dict(children)
for item in stream:
# item[0] is known as str
# item[1] is known as Node
This is the same like (but without known types):
stream = Stream(children)
Filter by existing key
items_with_name = Stream([child]).filter_key("name")
Filter by type
nodes_only = Stream([child]).filter_type(Node)
Map object name attribute
names = Stream([child]).map_key("name")
Deep mapping of name attributes
list = [
{"node": Node(name="Node A")},
{"node": Node(name="Node B")},
{"node": Node(name="Node C")},
{"node": Node(name="Node D")},
]
Stream(list).map_keys("node", "name")
Collected join
all_names = Stream([child]).map_key("name").join(", ")
Stream many
many = Stream.of_many([1, 2, 3], (4, 5, 6))
many = many.concat([7, 8, 9])
End of stream
stream = Stream(["a", "b", "c"]).on_end(lambda: print("Finished"))
char = stream.next().get()
if char == "a":
stream.end()
Examples
A given data structure like:
data = {
"ranges": [
timedelta(days=3),
]
}
Without tinystream:
if "ranges" in data:
range_data: timedelta
for range_data in filter(lambda x: isinstance(x, timedelta), data["ranges"]):
pass
With tinystream:
for range_data in Opt(data).map_key("ranges").stream().filter_type(timedelta):
pass
Comparison with other libraries
There are a couple of other implementation to fulfill similar requirements.
- https://github.com/vxgmichel/aiostream (most professional)
- https://github.com/alemazzo/Python-Java-Stream
- https://github.com/ramsteak/streams
- https://pypi.org/project/fluentpy
- https://github.com/JaviOverflow/python-streams (outdated)
- https://github.com/9seconds/streams/ (outdated)
- https://github.com/tolsac/streampy (outdated)
- Apache Spark
Run the tests
PYTHONPATH="." pytest --cov=tinystream -n 4 tests/
Release update
- Update version in
setup.py
- Package library
python setup.py sdist
- Publish library
twine upload dist/tinystream-[version].tar.gz
References
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.