Providing some additional capabilities on top of itertools.
Project description
ben42code.myitertools
Providing some additional capabilities on top of itertools.
Everything here is lazy and stream-friendly: values are pulled from the source only as far as the requested result requires.
Installation
pip install ben42code.myitertools
Requires Python 3.10+.
Features
| Feature | Intent |
|---|---|
islice_extended |
itertools.islice with negative start/stop/step support. |
IteratorCounter |
Transparent wrapper that counts the values pulled through it. |
StreamSequence |
A lazy Sequence view (len, indexing, slicing) over a one-shot iterator. |
The
>>>examples below are executed as doctests by the test suite, so they are guaranteed to stay in sync with the code.
islice_extended
islice_extended(iterable: Iterable[T], stop: int | None) -> Iterator[T]
islice_extended(iterable: Iterable[T], start: int | None, stop: int | None, step: int | None = 1) -> Iterator[T]
Slice any iterable the way list[start:stop:step] would — including negative
start/stop indices and a negative step — pulling from the source lazily
instead of materialising it up front.
>>> from ben42code.myitertools import islice_extended
>>> list(islice_extended([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], -1, -5, -1))
[9, 8, 7, 6]
>>> list(islice_extended([0, 1, 2], None, None, -1))
[2, 1, 0]
Notes
- Non-negative bounds + positive step → pure
itertools.islicedelegation, O(1) extra memory. - ⚠️ A negative
start/stopmust find the end of the stream: the input is consumed to exhaustion and buffered — O(n) time and memory (hangs on an unbounded source). - A negative
step(with non-negative bounds) buffers up tostart + 1values — O(start). - Buffered values are released as they are yielded, so retained memory shrinks while you iterate.
IteratorCounter
IteratorCounter(iterator: Iterator[T] | Iterable[T])
count: int # values pulled from the source so far
Wrap an iterator/iterable and expose, at any time, how many values have been pulled through it — without changing what flows downstream.
>>> from itertools import islice
>>> from ben42code.myitertools import IteratorCounter
>>> wrapper = IteratorCounter('ABCDEFGHIJKLMNOP')
>>> list(islice(wrapper, 2, 5))
['C', 'D', 'E']
>>> wrapper.count
5
Notes
- Fully lazy and single-pass: O(1) time per value, O(1) extra memory.
.countreflects values actually pulled from the source, so it doubles as a probe of how far a downstream consumer really advanced the stream (e.g.islice(_, 2, 5)pulls5, not3).
StreamSequence
StreamSequence(iterable: Iterable[T])
take(n: int | None) -> list[T] # advance the visible front, returning the values
consume(n: int | None) -> None # advance the visible front, discarding the values
Expose a one-shot iterator/iterable (generator, file, socket, itertools chain …)
through the
collections.abc.Sequence
protocol — len(), positive/negative indexing, iteration and slicing — while
still consuming the source lazily.
>>> from itertools import count
>>> from ben42code.myitertools import StreamSequence
>>> stream = StreamSequence(count(0)) # unbounded source
>>> stream[3] # pulls only 0..3
3
>>> stream.take(3)
[0, 1, 2]
>>> stream[0] # the visible front has advanced
3
>>> StreamSequence(count(0))[::2].take(5) # lazy slice over an unbounded source
[0, 2, 4, 6, 8]
Notes
- On-demand: a non-negative index or
take(n)pulls only as far as needed; with no live sub-iterators,consume/takestream straight past the cache — O(1) retained memory on a self-draining source. - Slices and previously created iterators keep their own anchor, so they still see values the parent moved past; buffering is bounded to what live sub-iterators hold back, and released values are tombstoned and compacted in amortised O(1).
- ⚠️ Operations that must reach the end —
len(), negative indexing,__contains__/indexon a miss,count,reversed— walk the source to exhaustion and hang on an unbounded stream; use them only on a bounded view. - Built for one-shot sources: wrapping a random-access
Sequence(list,tuple,range…) only adds indirection — use it directly instead. - ⚠️ Not thread-safe: a
StreamSequenceand its sub-iterators need external synchronisation for concurrent use.
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.
Source Distribution
Built Distribution
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 ben42code_myitertools-0.0.6.tar.gz.
File metadata
- Download URL: ben42code_myitertools-0.0.6.tar.gz
- Upload date:
- Size: 13.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e0e4044dd1a409c78f26e46317e9f1b8882997003f25e3f4692138cfddc1b8f
|
|
| MD5 |
f4525007472f6ee3ae31db9cb3515178
|
|
| BLAKE2b-256 |
5e8022056ef89c2bdd84f8eb4bf207157ebb8393c3942ffe61b5e5248e434054
|
Provenance
The following attestation bundles were made for ben42code_myitertools-0.0.6.tar.gz:
Publisher:
release.yml on ben42code/myitertools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ben42code_myitertools-0.0.6.tar.gz -
Subject digest:
1e0e4044dd1a409c78f26e46317e9f1b8882997003f25e3f4692138cfddc1b8f - Sigstore transparency entry: 2190763327
- Sigstore integration time:
-
Permalink:
ben42code/myitertools@5411f0eaf56fd0dd2068742e5d133b704bf64dc4 -
Branch / Tag:
refs/tags/v0.0.6 - Owner: https://github.com/ben42code
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5411f0eaf56fd0dd2068742e5d133b704bf64dc4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ben42code_myitertools-0.0.6-py3-none-any.whl.
File metadata
- Download URL: ben42code_myitertools-0.0.6-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
708eef3ab42540380e0ab1ecc86f0db2dd122cedc8f4c26f8b908b98793dc266
|
|
| MD5 |
fab914c5492705ec8f0217d7ea34ccd6
|
|
| BLAKE2b-256 |
7d6272208ffe46c8b0882da11e0f9a0029a9213b5d779f77a060d27b1a41b455
|
Provenance
The following attestation bundles were made for ben42code_myitertools-0.0.6-py3-none-any.whl:
Publisher:
release.yml on ben42code/myitertools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ben42code_myitertools-0.0.6-py3-none-any.whl -
Subject digest:
708eef3ab42540380e0ab1ecc86f0db2dd122cedc8f4c26f8b908b98793dc266 - Sigstore transparency entry: 2190763411
- Sigstore integration time:
-
Permalink:
ben42code/myitertools@5411f0eaf56fd0dd2068742e5d133b704bf64dc4 -
Branch / Tag:
refs/tags/v0.0.6 - Owner: https://github.com/ben42code
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5411f0eaf56fd0dd2068742e5d133b704bf64dc4 -
Trigger Event:
release
-
Statement type: