Skip to main content

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.islice delegation, O(1) extra memory.
  • ⚠️ A negative start/stop must 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 to start + 1 values — 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.
  • .count reflects 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) pulls 5, not 3).

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/take stream 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__/index on 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 StreamSequence and its sub-iterators need external synchronisation for concurrent use.

PyPI version PyPI Downloads PyPI - Downloads

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ben42code_myitertools-0.0.6rc18.tar.gz (13.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ben42code_myitertools-0.0.6rc18-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file ben42code_myitertools-0.0.6rc18.tar.gz.

File metadata

File hashes

Hashes for ben42code_myitertools-0.0.6rc18.tar.gz
Algorithm Hash digest
SHA256 99f4407dfcedd66c2126a00fde75fbc906692aacce1f0e9f2f44833e06de4383
MD5 ef25a29505e65c68a95c3123911b0a3e
BLAKE2b-256 8eec8f933fe04301559adbcb2139cc7c47b0a61de4e9c8394b6ae11b2cf5d7f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for ben42code_myitertools-0.0.6rc18.tar.gz:

Publisher: release.yml on ben42code/myitertools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ben42code_myitertools-0.0.6rc18-py3-none-any.whl.

File metadata

File hashes

Hashes for ben42code_myitertools-0.0.6rc18-py3-none-any.whl
Algorithm Hash digest
SHA256 b5304218aec50a56645f235e8fcdee012f3ed4efa2178d5350e9f97cd7e58a02
MD5 c98db4ffb4d7b66400cf91bb0dd40cae
BLAKE2b-256 40ad93f120abd70daa550850354ae1ce28ec9ac03c844a0f21e33ad4decd3f8f

See more details on using hashes here.

Provenance

The following attestation bundles were made for ben42code_myitertools-0.0.6rc18-py3-none-any.whl:

Publisher: release.yml on ben42code/myitertools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page