## Package Description
[![CircleCI](https://dl.circleci.com/status-badge/img/gh/sfkleach/pushable/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/sfkleach/pushable/tree/main) [![Documentation Status](https://readthedocs.org/projects/pushable/badge/?version=latest)](https://pushable.readthedocs.io/en/latest/?badge=latest)
This is a Python package that provides a simple class Pushable that creates "pushable" iterators by wrapping an inner iterator/iterable. Pushable iterators act like dynamically expanding queues, allowing you to peek ahead or push items back onto the queue.
## Basic Usage
We can turn any iterable/iterator into a pushable iterator using the constructor.
```
count_up = Pushable( range( 0, 5 ) )
```
We can use it like an ordinary iterator:
```
print( next( count_up ) )
# Prints 0
```
Or we can look-ahead to see what is coming:
```
whats_up_next = count_up.peek()
print( whats_up_next )
# Print 1
print( next( count_up ) )
# Also prints 1 because peek does not remove the item from the internal queue.
```
We can even push back items onto it:
```
count_up.push("cat")
count_up.push("dog")
print( list( count_up ) )
# Prints 'dog', 'cat', 2, 3, 4
```
## Examples
From an iterator such as a file-object, which will iterate over the lines in a file, create a peekable/pushable iterator. This can be useful for example when we want to know if the iterator still has contents or want a sneak peek at what is coming.
```py
from pushable import Pushable
def read_upto_two_blank_lines( filename ):
with open( filename ) as file:
plines = Pushable( file )
# Pushable iterators can be used as booleans in the natural way.
while plines:
line = next( plines )
# peekOr makes it safe to look ahead.
if line == '\n' and plines.peekOr() == '\n':
# Two blank lines encountered.
break
else:
yield line
```
It is also useful to perform "macro-like" transformation.
```py
from pushable import Pushable
def translate( text, translations ):
ptokens = Pushable( text.split() )
while ptokens:
token = next(ptokens)
if token in translations:
ptokens.multiPush( *translations[token].split() )
else:
yield token
print( ' '.join( translate( 'My name is MYNAME', {'MYNAME':'Fred Bloggs'} ) ) )
# Prints: My name is Fred Bloggs
```
### More Complex Uses
In addition to peeking and popping items, which risks raising a
`StopIteration` exception if there's nothing left on the internal queue, we
can utilise `peekOr` and `popOr` to deliver a default value instead. The
default value is passed as an optional parameter and falls back to None.
We can also peek and pop multiple values using `multiPeekOr` and `multiPopOr`,
which return generators. These support skipping over values so that you can
get the 2nd and 3rd value without getting the first e.g.
```py
(second, third) = Pushable("pqr").multiPop(skip=1, count=2)
print( second, third )
# Prints: q r
```
Lastly, we can push multiple items with `multiPush`:
```py
count_up.multiPush("cat", "dog", "rabbit")
print( list( count_up ) )
# Prints: ['cat', 'dog', 'rabbit']
```
For a full set of available methods see [the documentation](https://pushable.readthedocs.io/en/latest/pushable.html).
Raw data
{
"_id": null,
"home_page": "https://pushable.readthedocs.io/en/latest/",
"name": "pushable",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "iterators, pushable, peekable",
"author": "Stephen Leach",
"author_email": "sfkleach@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/d3/6a/45620d7c5052920e2317a583f80262d6a81b8c2cb2ef4ecd04dda598b8c3/pushable-0.1.8.tar.gz",
"platform": null,
"description": "## Package Description\n\n[![CircleCI](https://dl.circleci.com/status-badge/img/gh/sfkleach/pushable/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/sfkleach/pushable/tree/main) [![Documentation Status](https://readthedocs.org/projects/pushable/badge/?version=latest)](https://pushable.readthedocs.io/en/latest/?badge=latest)\n\nThis is a Python package that provides a simple class Pushable that creates \"pushable\" iterators by wrapping an inner iterator/iterable. Pushable iterators act like dynamically expanding queues, allowing you to peek ahead or push items back onto the queue.\n\n\n## Basic Usage\n\nWe can turn any iterable/iterator into a pushable iterator using the constructor.\n```\ncount_up = Pushable( range( 0, 5 ) )\n```\n\nWe can use it like an ordinary iterator:\n```\nprint( next( count_up ) )\n# Prints 0\n```\n\nOr we can look-ahead to see what is coming:\n```\nwhats_up_next = count_up.peek()\nprint( whats_up_next )\n# Print 1\nprint( next( count_up ) )\n# Also prints 1 because peek does not remove the item from the internal queue.\n```\n\nWe can even push back items onto it:\n```\ncount_up.push(\"cat\")\ncount_up.push(\"dog\")\nprint( list( count_up ) )\n# Prints 'dog', 'cat', 2, 3, 4\n```\n\n## Examples\n\nFrom an iterator such as a file-object, which will iterate over the lines in a file, create a peekable/pushable iterator. This can be useful for example when we want to know if the iterator still has contents or want a sneak peek at what is coming.\n\n```py\nfrom pushable import Pushable\n\ndef read_upto_two_blank_lines( filename ):\n with open( filename ) as file:\n plines = Pushable( file )\n # Pushable iterators can be used as booleans in the natural way.\n while plines:\n line = next( plines )\n # peekOr makes it safe to look ahead.\n if line == '\\n' and plines.peekOr() == '\\n':\n # Two blank lines encountered.\n break\n else:\n yield line \n```\n\nIt is also useful to perform \"macro-like\" transformation.\n\n```py\nfrom pushable import Pushable\n\ndef translate( text, translations ):\n ptokens = Pushable( text.split() )\n while ptokens:\n token = next(ptokens)\n if token in translations:\n ptokens.multiPush( *translations[token].split() )\n else:\n yield token\n\nprint( ' '.join( translate( 'My name is MYNAME', {'MYNAME':'Fred Bloggs'} ) ) ) \n# Prints: My name is Fred Bloggs\n```\n\n### More Complex Uses\n\nIn addition to peeking and popping items, which risks raising a\n`StopIteration` exception if there's nothing left on the internal queue, we\ncan utilise `peekOr` and `popOr` to deliver a default value instead. The \ndefault value is passed as an optional parameter and falls back to None.\n\nWe can also peek and pop multiple values using `multiPeekOr` and `multiPopOr`, \nwhich return generators. These support skipping over values so that you can\nget the 2nd and 3rd value without getting the first e.g.\n\n```py\n(second, third) = Pushable(\"pqr\").multiPop(skip=1, count=2)\nprint( second, third )\n# Prints: q r\n```\n\nLastly, we can push multiple items with `multiPush`:\n```py\ncount_up.multiPush(\"cat\", \"dog\", \"rabbit\")\nprint( list( count_up ) )\n# Prints: ['cat', 'dog', 'rabbit']\n```\n\nFor a full set of available methods see [the documentation](https://pushable.readthedocs.io/en/latest/pushable.html).\n",
"bugtrack_url": null,
"license": "GPL-3.0-or-later",
"summary": "Convert iterators into peekable, pushable iterators",
"version": "0.1.8",
"project_urls": {
"Documentation": "https://pushable.readthedocs.io/en/latest/",
"Homepage": "https://pushable.readthedocs.io/en/latest/",
"Repository": "https://github.com/sfkleach/pushable"
},
"split_keywords": [
"iterators",
" pushable",
" peekable"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a9574a7382916f60ea715ee04bc8c063496e166d1712ce75137945af7e72a417",
"md5": "a54d3e0267dff25325cfdf59a0beb926",
"sha256": "4e2de0e2c09232cb897548f57b0994e358262a65719c62bc23178802a31fcda1"
},
"downloads": -1,
"filename": "pushable-0.1.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a54d3e0267dff25325cfdf59a0beb926",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 17146,
"upload_time": "2024-08-13T19:31:23",
"upload_time_iso_8601": "2024-08-13T19:31:23.435509Z",
"url": "https://files.pythonhosted.org/packages/a9/57/4a7382916f60ea715ee04bc8c063496e166d1712ce75137945af7e72a417/pushable-0.1.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d36a45620d7c5052920e2317a583f80262d6a81b8c2cb2ef4ecd04dda598b8c3",
"md5": "80befa0963fa180b2fb6eaa4fac1675a",
"sha256": "3f0bbdb9acf0bfd3a5c53df8388ad6c3328bb594ac532e48e7c0ea487a73554e"
},
"downloads": -1,
"filename": "pushable-0.1.8.tar.gz",
"has_sig": false,
"md5_digest": "80befa0963fa180b2fb6eaa4fac1675a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 16409,
"upload_time": "2024-08-13T19:31:25",
"upload_time_iso_8601": "2024-08-13T19:31:25.236024Z",
"url": "https://files.pythonhosted.org/packages/d3/6a/45620d7c5052920e2317a583f80262d6a81b8c2cb2ef4ecd04dda598b8c3/pushable-0.1.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-13 19:31:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sfkleach",
"github_project": "pushable",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"circle": true,
"lcname": "pushable"
}