Usage¶
Installation¶
rangeslib requires Python 3.12 or newer and has no runtime dependencies.
python -m pip install .
Contributor tooling is installed separately:
python -m pip install -e ".[dev]"
Public API¶
Application code should import the public facade modules and, when needed, the
Range container:
from rangeslib import Range, ranges, views
Modules beginning with _ are private implementation details.
Range¶
Range is an eager mutable sequence backed by collections.UserList.
Construction is positional:
from rangeslib import Range
values = Range(1, 2, 3)
nested = Range([1, 2, 3])
assert list(values) == [1, 2, 3]
assert list(nested) == [[1, 2, 3]]
List-like reconstruction operations preserve Range:
assert list(values[1:]) == [2, 3]
assert list(values + [4]) == [1, 2, 3, 4]
assert list([0] + values) == [0, 1, 2, 3]
assert list(values * 2) == [1, 2, 3, 1, 2, 3]
assert list(values.copy()) == [1, 2, 3]
Generators¶
The ranges module constructs eager Range values.
Factory |
Result |
Edge behavior |
|---|---|---|
|
empty |
always empty |
|
one-element |
preserves the value type |
|
integers in |
same direction rules as built-in |
|
integers in |
non-positive counts are empty |
|
|
non-positive counts are empty |
Pipelines¶
Adaptors can be called directly or placed on the right side of |:
from rangeslib import ranges, views
result = (
ranges.iota(1, 7)
| views.reverse()
| views.filter(lambda value: value % 2 == 0)
| views.transform(lambda value: value * 10)
| views.take(2)
)
assert list(result) == [60, 40]
Ordinary iterables can start pipelines because adaptors implement reflected |
dispatch:
text = "abcdef" | views.take(3) | views.to(str)
assert text == "abc"
Adaptors can also be composed and reused:
pipeline = views.filter(lambda value: value % 2 == 0) | views.take(3)
assert list([1, 2, 3, 4, 5, 6] | pipeline) == [2, 4, 6]
assert list([10, 11, 12, 14] | pipeline) == [10, 12, 14]
Materialization¶
Most adaptors return a fully materialized Range, making results repeatable.
views.to is the terminal conversion adaptor and returns the target callable’s
result.
Use views.all() to materialize an existing iterable as a reusable Range. It
is the closest equivalent to C++ views::all in the current eager design:
assert list([1, 2, 3] | views.all()) == [1, 2, 3]
assert list(("a", "b") | views.all()) == ["a", "b"]
assert list("abc" | views.all()) == ["a", "b", "c"]
views.take(count) and views.counted(count) stop early for non-negative
counts, so they can bound one-shot or infinite iterators. Negative take
intentionally follows Python slice semantics and materializes the input first.
Use views.to(str) to concatenate string elements without a separator. Other
targets are called with the pipeline iterable, so custom conversion functions
and collection types continue to work as before.
Adaptor Catalog¶
all,reverse,filter,transform,take,drop, andcountedprocess values.takewhile/take_whileanddropwhile/drop_whileprocess prefixes.elements,keys, andvaluesproject indexed tuple-like elements.enumerate,concat,zip,zip_transform, andcartesian_productcombine values.adjacent,pairwise,adjacent_transform, andpairwise_transformcreate tuple windows.chunk,slide,chunk_by, andstridegroup or sample finite inputs.join,join_with, andsplithandle nested values and separator patterns.toconverts the final iterable to a collection or custom result.
zip accepts any number of companion iterables and stops at the shortest input:
assert list([1, 2, 3] | views.zip(["a", "b"], [True, False])) == [
(1, "a", True),
(2, "b", False),
]
Delimiters¶
split and join_with accept either scalar delimiters or iterable separator
patterns:
assert [list(chunk) for chunk in [1, 0, 2, 0] | views.split(0)] == [[1], [2], []]
assert [list(chunk) for chunk in [1, 0, 0, 2] | views.split([0, 0])] == [[1], [2]]
assert list([[1], [2, 3]] | views.join_with(0)) == [1, 0, 2, 3]
assert list([[1], [2, 3]] | views.join_with([0, 0])) == [1, 0, 0, 2, 3]
An empty split separator raises ValueError before consuming the input.
An empty join_with separator is valid and behaves like join.
Type Checking¶
The installed distribution includes a py.typed marker. Public type assertions
are kept in tests/typecheck/public_api.py and run in CI with both mypy and
Pyright.
The facade preserves useful public types, including mixed two-range zip and
cartesian_product, exact pairwise tuples, and typed keys / values over
pair-like inputs.
Performance Checks¶
For local performance measurements, run:
PYTHONPATH=src .venv/bin/python scripts/benchmark.py
The benchmark script is not part of CI because timing varies by machine. Use it for comparing changes locally before and after implementation work.