# frogress - progress tool for snakes
[![Build Status](https://app.travis-ci.com/lukaszb/frogress.svg?token=yU4TayxRr7VaoPy9gksr&branch=master)](https://app.travis-ci.com/lukaszb/frogress)
[![Coverage Status](https://coveralls.io/repos/github/lukaszb/frogress/badge.svg?branch=master)](https://coveralls.io/github/lukaszb/frogress?branch=master)
```
/----------------------------------------------------------------------------------\
| |
@..@ /| [###.......] Progress: 34.2MB / 125.8MB | 25.0% | Time: 14min3s | ETA: 19min52s |
(----) / | |
( >__< ) \----------------------------------------------------------------------------------/
^^ ~~ ^^
```
frogress is small progress indication tool to be used for fast prototyping.
Why *frogress* anyway? Because it's a bar (most of the time) and it jumps on
your terminal, that's why!
- Does NOT break your workflow (in most cases there is no need to call
progress bar to render itself)
- It can guess if you [iterate over a list](#iterate-over-a-list) (or similar iterable) ...
- or if iterate over a file ...
- or if iterate over generator - provided you know it's total length ...
- or not! (no eta, no total steps, no percentage and indicator instead of a bar
but it works!)
- And you can easily teach it how to show progress of fat, gzipped xml file
when using [lxml][lxml] to parse it
- Supports Python 2.6+, Python 3, PyPY
- Fully tested
## Iteration examples
### Iterate over a list
```
>>> import frogress
>>> items = [1, 2, 3, 4, 5]
>>> for item in frogress.bar(items):
... pass # do something with item
[##........] Step 2/5 | 20.0% | Time: 0.1s | ETA: 0.5s
```
### Iterate over a file
```
>>> import frogress
>>> for line in frogress.bar(open('/path/to/file', steps_label='Progress')):
... pass # do something cruel with a line
[###.......] Progress: 3.2MB / 12.8MB | 25.0% | Time: 14min3s | ETA: 19min52s
```
### Iterate over generator
```
>>> import frogress
>>> count = 100
>>> items = range(count)
>>> for item in frogress.bar(items, steps=count):
... pass # do something with item
[#########.] Step 86/100 | 86.0% | Time: 1.2s | ETA: 7.3s
```
### Iterate over a generator with unknown total number of steps
```
>>> import frogress
>>> def counter():
... num = 1
... while True:
... yield num
... num += 1
...
>>> items = counter()
>>> for item in frogress.bar(items):
... pass # do something with item
[........#.] Step: 1410 | Time: 2min14s
[.........#] Step: 1411 | Time: 2min15s
[........#.] Step: 1412 | Time: 2min16s
[.......#..] Step: 1413 | Time: 2min17s
```
### Iterate over gzipped xml file using lxml
The only problem with how to present a progress of file that's being processed
is the source from which frogress should extract progress information. We can
try to do this simple way (without knowledge of how much of the file is already
processed) or give ``frogress`` a *source*.
#### Simple way
```
>>> import frogress
>>> import gzip
>>> from lxml.etree import iterparse
>>> stream = gzip.open('my-fat.xml.gz')
>>> context = iterparse(stream)
>>> for action, element in frogress.bar(context):
... pass # do something with element
... element.clear() # don't forget about the memory!
[...#......] Progress: 41923 | Time: 1h42min
```
This is perfectly fine: we passed an iterable that doesn't provide information
on how many total items there is to process - so we have an bar activity
indicator, no total steps at the progress and no ETA.
However, there is clearly a way of retrieving this information - after all this
is only a file that's being processed. And that file should be passed as
``source`` argument to the ``frogress.bar`` function.
#### Pass source
```
>>> import frogress
>>> import gzip
>>> from lxml.etree import iterparse
>>> stream = gzip.open('my-fat.xml.gz')
>>> context = iterparse(stream)
>>> for action, element in frogress.bar(context, source=stream.myfileobj):
... pass # do something with element
... element.clear() # don't forget about the memory!
[#####.....] Progress: 73.5MB / 156.4MB | 47.3% | Time: 1h42min | ETA: 1h53min
```
Just remember to pass file that is actually processed, not a wrapper! Standard
file would be passed directly, however in example, ``gzip`` module wraps stream
it is working on and it's available as attribute ``myfileobj``. On the other
hand ``bz2`` module doesn't wrap streams. And so on. ``frogress`` can guess if
a stream is file like object, however passing proper source is responsibility
of the user.
## Spinner without actual iterable
Sometimes we just want to show that program is doing something but we don't
really know how long it would take (i.e. perform couple of API requests).
### Example
```
import frogress
import time
def cmd(s=0):
time.sleep(s)
def main():
with frogress.spinner("Waiting for response 1", done="OK"):
cmd(0.5)
with frogress.spinner("Waiting for response 2", done="Done"):
cmd(0.5)
with frogress.spinner("Waiting for response 3", done="All done, really!"):
cmd(0.5)
main()
```
![demo-multi-commands-simple](https://github.com/lukaszb/frogress/assets/190381/37b62e95-9120-4fe6-a035-de17640fc326)
## Progress bar class API
Most of the time you won't need to call those API directly - ``frogress.bar``
function should work for majority of the use cases. If, however, you feel like
you need to make some customization, here we present some examples
```
>>> import frogress
>>> items = [1, 2, 3, 4, 5]
>>> progressbar = frogress.Bar(items)
>>> progressbar.step
0
>>> progressbar.started # it's still None
>>> progressbar.finished # here too
>>> for item in progressbar:
... pass # process the item (it will draw progressbar during iteration)
>>> progressbar.step
5
>>> progressbar.widgets
[<BarWidget>, <ProgressWidget>, <PercentageWidget>, <EtaWidget>, <TimeWidget>]
>>> len(progressbar)
5
>>> progressbar.output
<open file '<stderr>', mode 'w' at 0x103df61e0>
>>> progressbar.started
datetime.datetime(2013, 5, 12, 22, 2, 26, 752454)
>>> progressbar.finished
datetime.datetime(2013, 5, 12, 22, 2, 26, 792901)
```
## Tips & Tricks
### How to change label of the progress widget
```
>>> import frogress
>>> items = [1, 2, 3, 4, 5]
>>> widgets = [frogress.BarWidget, frogress.ProgressWidget('Items: '), frogress.TimerWidget]
>>> for item in frogress.bar(items, widgets=widgets):
>>> pass
```
[lxml]: http://lxml.de/
Raw data
{
"_id": null,
"home_page": "https://github.com/lukaszb/frogress",
"name": "frogress",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "Lukasz Balcerzak",
"author_email": "lukaszbalcerzak@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/6d/50/35f9d1758ac852fe75cd5d687709710ea076fad9b5fdb9f2f6d53f5510d9/frogress-0.10.1.tar.gz",
"platform": null,
"description": "# frogress - progress tool for snakes\n\n[![Build Status](https://app.travis-ci.com/lukaszb/frogress.svg?token=yU4TayxRr7VaoPy9gksr&branch=master)](https://app.travis-ci.com/lukaszb/frogress)\n\n[![Coverage Status](https://coveralls.io/repos/github/lukaszb/frogress/badge.svg?branch=master)](https://coveralls.io/github/lukaszb/frogress?branch=master)\n\n\n```\n /----------------------------------------------------------------------------------\\\n | |\n @..@ /| [###.......] Progress: 34.2MB / 125.8MB | 25.0% | Time: 14min3s | ETA: 19min52s |\n (----) / | |\n ( >__< ) \\----------------------------------------------------------------------------------/\n ^^ ~~ ^^\n```\n\n\nfrogress is small progress indication tool to be used for fast prototyping.\nWhy *frogress* anyway? Because it's a bar (most of the time) and it jumps on\nyour terminal, that's why!\n\n- Does NOT break your workflow (in most cases there is no need to call\n progress bar to render itself)\n- It can guess if you [iterate over a list](#iterate-over-a-list) (or similar iterable) ...\n- or if iterate over a file ...\n- or if iterate over generator - provided you know it's total length ...\n- or not! (no eta, no total steps, no percentage and indicator instead of a bar\n but it works!)\n- And you can easily teach it how to show progress of fat, gzipped xml file\n when using [lxml][lxml] to parse it\n- Supports Python 2.6+, Python 3, PyPY\n- Fully tested\n\n\n## Iteration examples\n\n\n### Iterate over a list\n\n```\n\n >>> import frogress\n >>> items = [1, 2, 3, 4, 5]\n >>> for item in frogress.bar(items):\n ... pass # do something with item\n\n [##........] Step 2/5 | 20.0% | Time: 0.1s | ETA: 0.5s\n\n```\n\n### Iterate over a file\n\n```\n\n >>> import frogress\n >>> for line in frogress.bar(open('/path/to/file', steps_label='Progress')):\n ... pass # do something cruel with a line\n\n [###.......] Progress: 3.2MB / 12.8MB | 25.0% | Time: 14min3s | ETA: 19min52s\n\n```\n\n### Iterate over generator\n\n```\n\n >>> import frogress\n >>> count = 100\n >>> items = range(count)\n >>> for item in frogress.bar(items, steps=count):\n ... pass # do something with item\n\n [#########.] Step 86/100 | 86.0% | Time: 1.2s | ETA: 7.3s\n```\n\n### Iterate over a generator with unknown total number of steps\n\n```\n\n >>> import frogress\n >>> def counter():\n ... num = 1\n ... while True:\n ... yield num\n ... num += 1\n ...\n >>> items = counter()\n >>> for item in frogress.bar(items):\n ... pass # do something with item\n\n [........#.] Step: 1410 | Time: 2min14s\n [.........#] Step: 1411 | Time: 2min15s\n [........#.] Step: 1412 | Time: 2min16s\n [.......#..] Step: 1413 | Time: 2min17s\n\n```\n\n\n### Iterate over gzipped xml file using lxml\n\nThe only problem with how to present a progress of file that's being processed\nis the source from which frogress should extract progress information. We can\ntry to do this simple way (without knowledge of how much of the file is already\nprocessed) or give ``frogress`` a *source*.\n\n\n#### Simple way\n\n```\n\n >>> import frogress\n >>> import gzip\n >>> from lxml.etree import iterparse\n >>> stream = gzip.open('my-fat.xml.gz')\n >>> context = iterparse(stream)\n >>> for action, element in frogress.bar(context):\n ... pass # do something with element\n ... element.clear() # don't forget about the memory!\n\n [...#......] Progress: 41923 | Time: 1h42min\n\n```\n\nThis is perfectly fine: we passed an iterable that doesn't provide information\non how many total items there is to process - so we have an bar activity\nindicator, no total steps at the progress and no ETA.\n\nHowever, there is clearly a way of retrieving this information - after all this\nis only a file that's being processed. And that file should be passed as\n``source`` argument to the ``frogress.bar`` function.\n\n#### Pass source\n\n```\n\n >>> import frogress\n >>> import gzip\n >>> from lxml.etree import iterparse\n >>> stream = gzip.open('my-fat.xml.gz')\n >>> context = iterparse(stream)\n >>> for action, element in frogress.bar(context, source=stream.myfileobj):\n ... pass # do something with element\n ... element.clear() # don't forget about the memory!\n\n [#####.....] Progress: 73.5MB / 156.4MB | 47.3% | Time: 1h42min | ETA: 1h53min\n\n```\n\n\nJust remember to pass file that is actually processed, not a wrapper! Standard\nfile would be passed directly, however in example, ``gzip`` module wraps stream\nit is working on and it's available as attribute ``myfileobj``. On the other\nhand ``bz2`` module doesn't wrap streams. And so on. ``frogress`` can guess if\na stream is file like object, however passing proper source is responsibility\nof the user.\n\n\n## Spinner without actual iterable\n\nSometimes we just want to show that program is doing something but we don't\nreally know how long it would take (i.e. perform couple of API requests).\n\n### Example\n\n```\nimport frogress\nimport time\n\ndef cmd(s=0):\n time.sleep(s)\n\n\ndef main():\n with frogress.spinner(\"Waiting for response 1\", done=\"OK\"):\n cmd(0.5)\n with frogress.spinner(\"Waiting for response 2\", done=\"Done\"):\n cmd(0.5)\n with frogress.spinner(\"Waiting for response 3\", done=\"All done, really!\"):\n cmd(0.5)\n\nmain()\n\n```\n\n![demo-multi-commands-simple](https://github.com/lukaszb/frogress/assets/190381/37b62e95-9120-4fe6-a035-de17640fc326)\n\n\n\n## Progress bar class API\n\nMost of the time you won't need to call those API directly - ``frogress.bar``\nfunction should work for majority of the use cases. If, however, you feel like\nyou need to make some customization, here we present some examples\n\n```\n\n >>> import frogress\n >>> items = [1, 2, 3, 4, 5]\n >>> progressbar = frogress.Bar(items)\n >>> progressbar.step\n 0\n >>> progressbar.started # it's still None\n >>> progressbar.finished # here too\n >>> for item in progressbar:\n ... pass # process the item (it will draw progressbar during iteration)\n >>> progressbar.step\n 5\n >>> progressbar.widgets\n [<BarWidget>, <ProgressWidget>, <PercentageWidget>, <EtaWidget>, <TimeWidget>]\n >>> len(progressbar)\n 5\n >>> progressbar.output\n <open file '<stderr>', mode 'w' at 0x103df61e0>\n >>> progressbar.started\n datetime.datetime(2013, 5, 12, 22, 2, 26, 752454)\n >>> progressbar.finished\n datetime.datetime(2013, 5, 12, 22, 2, 26, 792901)\n\n```\n\n## Tips & Tricks\n\n### How to change label of the progress widget\n\n```\n\n >>> import frogress\n >>> items = [1, 2, 3, 4, 5]\n >>> widgets = [frogress.BarWidget, frogress.ProgressWidget('Items: '), frogress.TimerWidget]\n >>> for item in frogress.bar(items, widgets=widgets):\n >>> pass\n\n\n```\n[lxml]: http://lxml.de/\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A progress tool for humans",
"version": "0.10.1",
"project_urls": {
"Homepage": "https://github.com/lukaszb/frogress"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "bae44e7f4f4148854d63550c96acfb5daec82aec5f801f07323822ab84ae5910",
"md5": "f7f3e05e5aee4cb5001b38ad5369a46f",
"sha256": "a47be1dbca0b89dcbd0628063a159948ff96343e4f5086a4f25e2780469f96d7"
},
"downloads": -1,
"filename": "frogress-0.10.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f7f3e05e5aee4cb5001b38ad5369a46f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 15216,
"upload_time": "2024-04-04T08:15:59",
"upload_time_iso_8601": "2024-04-04T08:15:59.977732Z",
"url": "https://files.pythonhosted.org/packages/ba/e4/4e7f4f4148854d63550c96acfb5daec82aec5f801f07323822ab84ae5910/frogress-0.10.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6d5035f9d1758ac852fe75cd5d687709710ea076fad9b5fdb9f2f6d53f5510d9",
"md5": "f092e32d7acaff2800072d4bb9bb874c",
"sha256": "0150cfb988eeda65e019283a06b69603c26457081c545b1b143d907996bf96d3"
},
"downloads": -1,
"filename": "frogress-0.10.1.tar.gz",
"has_sig": false,
"md5_digest": "f092e32d7acaff2800072d4bb9bb874c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 19300,
"upload_time": "2024-04-04T08:16:01",
"upload_time_iso_8601": "2024-04-04T08:16:01.834023Z",
"url": "https://files.pythonhosted.org/packages/6d/50/35f9d1758ac852fe75cd5d687709710ea076fad9b5fdb9f2f6d53f5510d9/frogress-0.10.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-04 08:16:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lukaszb",
"github_project": "frogress",
"travis_ci": true,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "frogress"
}