{ "info": { "author": "Rog\u00e9rio Sampaio de Almeida", "author_email": "rsalmei@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8" ], "description": "![alive!](https://raw.githubusercontent.com/rsalmei/alive-progress/master/img/alive.gif)\n\n# alive-progress :)\n## An animated and smart Progress Bar for python!\n\n[![PyPI version](https://img.shields.io/pypi/v/alive-progress.svg)](https://pypi.python.org/pypi/alive-progress/)\n[![PyPI pyversions](https://img.shields.io/pypi/pyversions/alive-progress.svg)](https://pypi.python.org/pypi/alive-progress/)\n[![PyPI status](https://img.shields.io/pypi/status/alive-progress.svg)](https://pypi.python.org/pypi/alive-progress/)\n\nEver found yourself in a remote ssh session, doing some lengthy operations, and every now and then you feel the need to hit [enter] just to ensure you didn't lose the connection? Ever wondered where your processing is in, and when will it finish? Ever needed to *pause* the progress bar for a while, return to the python REPL for a manual inspection or fixing an item, and then *resume* the process like it never happened? I did...\n\nI've made this cool progress bar thinking about all that, the Alive-Progress bar! :)\n\n[![alive-progress](https://raw.githubusercontent.com/rsalmei/alive-progress/master/img/main.gif)](https://asciinema.org/a/260868)\n\n\nI like to think of it as a new kind of progress bar for python, as it has among other things:\n - a cool live spinner, which makes it clear the process did not hang and your terminal/connection is healthy;\n - a visual feedback of the current speed/throughput, as the spinner runs faster or slower according to the actual processing speed;\n - an efficient multi-threaded bar, which updates itself at a fraction of the actual speed (1,000,000 iterations per second equates to roughly 60fps refresh rate) to keep CPU usage low and avoid terminal spamming; \ud83d\udccc new: you can now calibrate this!\n - an expected time of arrival (eta), that shows the remaining processing time in a friendly way, not anything like `eta: 1584s`, it will nicely show `eta: 0:26:24` as you would expect (but anything less than a minute is indeed `eta: 42s`);\n - a `print()` hook, which allows print statements in the midst of an alive-bar context, nicely cleaning the output of any garbage, and even enriching with the current count when it occurred;\n - after your processing has finished, a nice receipt is printed with the statistics of that run, including the elapsed time and observed throughput;\n - it tracks the actual count in regard of the expected count, so it will look different if you send in more or less than expected;\n - it automatically detects if there's really an allocated tty, and if there isn't, only the final receipt is printed, so you can safely include the alive-bar in all and any code and rest assure your log file won't get 60fps garbage;\n - you can pause the alive-bar! I think that's an unprecedented feature for a progress-bar, it's incredible to orchestrate operations that require manual interaction on some items;\n - it is customizable, with a growing smorgasbord of different bar and spinner styles, as well as several factories to easily generate yours!\n\n\n## Get it\n\nJust install with pip:\n\n```bash\n$ pip install alive-progress\n```\n\n\n## Awake it\n\nOpen a context manager like this:\n\n```python\nfrom alive_progress import alive_bar\nitems = range(1000) # retrieve your set of items\nwith alive_bar(len(items)) as bar: # declare your expected total\n for item in items: # iterate as usual\n # process each item\n bar() # call after consuming one item\n```\n\nAnd it's alive! \ud83d\ude32\n\nIn general lines, just retrieve the items, enter the `alive_bar()` context manager, and iterate/process normally, calling `bar()` once per item.\n\n\n### Grasp it\n\n- the `items` can be any iterable, and usually will be some queryset;\n- the first argument of the `alive_bar` is the expected total, it could be a `qs.count()` for querysets, a `len(items)` for iterables which supports it, or any integer/anything that returns an integer;\n- the `bar()` call is what makes the bar go forward -- you usually call it in every iteration after consuming an item, but you can get creative! For example you could call it only when you find something you want, or call it more than once in the same iteration, depending on what you want to monitor. Just adjust the total accordingly to get a useful eta;\n- the `bar()` call also returns the current count/percentage if needed, and enables to pass situational messages to the bar.\n\nSo, you could even use it like:\n\n```python\nwith alive_bar(3) as bar:\n corpus = read_big_file()\n bar('file read, tokenizing')\n tokens = tokenize(corpus)\n bar('tokens ok, processing')\n process(tokens)\n bar()\n```\n\n\n## Alive-Bar modes\n\nActually the `total` argument is optional. Providing it makes the bar enter the **definite mode**, the one used for well-bounded tasks. This mode has all counter, throughput and eta statistics the bar has to offer.\n\nIf you do not provide a `total`, the bar enters the **unknown mode**. In this mode, the whole progress-bar is animated like the cool spinners, as it's not possible to determine the percentage of completion. You still get counter and throughput statistics.\n(the cool spinners are still present in this mode, and each animation runs independently of each other, rendering a unique show in your terminal \ud83d\ude1c).\n\nThese are the **auto modes**, the ones where the percentage is calculated for you.\n\nThen you have the (\ud83d\udccc new) **manual modes**, where you get to manually control the bar!\nJust pass a `manual=True` argument to `alive_bar()`, and you gain the ability to send a percentage (a float between 0 and 1) to the `bar()` handler to put the alive-bar in wherever position you want! Call it as frequently as you need.\nThe frames per second will be computed according to the sent progress and the actual elapsed time.\n\nIn these modes, you can also optionally provide the `total`, to enter the **manual definite mode** and get all the same count, throughput and eta statistics as the auto definite mode. The count is dynamically inferred when needed.\nIf you don't provide the `total` you get the **manual unknown mode**, where it's not possible to infer the count and throughput values, so a simpler \"percent/second\" is used for throughput, which can still be used to estimate an eta, nicely calculated to get to 100%.\n\n\n### The `bar` handler\n\n- in **auto** modes: `bar(text=None, incr=1)` \u2794 increases the current count (by any positive increment), optionally setting the situational text message, and returns the new count;\n- in **manual** modes: `bar(perc=None, text=None)` \u2794 sets the new progress percentage, optionally setting the situational text message, and returns the new percentage.\n\n\n## Printing messages\n\nWhile in an alive progress bar context, you have two ways to output messages:\n - calling `bar(text='message')`, which sets/overwrites a situational message within the bar line, usually to display something about the items being processed, or the phase the processing is in;\n - calling the usual Python `print('message')`, which will print an enriched message that includes the current position of the alive bar, thus leaving behind a log and continuing the bar below it.\n\nBoth methods work the same in **definite**, **unknown** and **manual** modes, and always clear the line appropriately to remove any garbage on screen. (_Click to see it in motion_)\n\n[![alive-progress messages](https://asciinema.org/a/lDM5zGPvPWFHHZOw0DMAMMH5F.svg)](https://asciinema.org/a/260875)\n\n\n## Styles\n\nWondering what styles does it have bundled? It's `showtime`! ;) (_Click to see it in motion_)\n\n[![alive-progress spinner styles](https://asciinema.org/a/OR83rcm8J06w0OC9pkgnaJmYG.svg)](https://asciinema.org/a/260872)\n\nI've made these styles to test all combinations of parameters of the factories, but I think some of them ended up very very cool! Use them, or create your own!\n\nThere's also a bars `showtime(spinners=False)` ;)\n\n[![alive-progress bar styles](https://raw.githubusercontent.com/rsalmei/alive-progress/master/img/showtime-bars.gif)](https://asciinema.org/a/263491)\n\n\n## Customization\n\nAll of the major components are individually customizable, both globally and per use!\n\nAnd you can mix and match them! (_Click to see it in motion_)\n\n[![alive-progress customization](https://asciinema.org/a/j392MaLz1w0zDw6EVHw4QbLAO.svg)](https://asciinema.org/a/260882)\n\n\n## Advanced\n\n### Calibration (\ud83d\udccc new)\n\nThe Alive-Bar has a cool visual feedback of the current throughput, so you can instantly see how fast your processing is, as the spinner runs faster or slower with it.\nFor this to happen, I've put together and implemented a few fps curves to empirically find which one gave the best feel of speed:\n\n![alive-bar fps curves](https://raw.githubusercontent.com/rsalmei/alive-progress/master/img/alive-bar_fps.png)\n(interactive version [here](https://www.desmos.com/calculator/ema05elsux))\n\nThe graph shows the logarithmic (red), parabolic (blue) and linear (green) curves, as well as an adjusted logarithmic curve (dotted orange), with a few twists for small numbers. I've settled with the adjusted logarithmic curve, as it seemed to provide the best all around perceived speed changes.\n\nThe default Alive-Bar calibrations are _1,000,000_ in auto (and manual definite) modes and 1 (100%) in manual unknown mode. Both enable a vast operating range and generally work well.\n\nBut let's say your processing hardly gets to 20 items per second, and you think the Alive-Bar is rendering sluggish, you can:\n\n```python\n with alive_bar(total, calibrate=20) as bar:\n ...\n``` \n\nAnd it will be running waaaay faster... :)\nAdjust the calibration to your liking!\n\n\n### Create your own animations\n\nMake your own spinners and bars!\nThere's builtin support for frames, scrolling, bouncing, delayed and compound spinners! Get creative! (_Click to see it in motion_)\n\n[![alive-progress creative](https://asciinema.org/a/mK9rbzLC1xkMRfRDk5QJMy8xc.svg)](https://asciinema.org/a/260884)\n\n\n### The Pause mechanism\n\nTo use the pause mechanism, you must use a generator to yield the objects you want to interact with. The bar object includes another context manager to do that, just do `with bar.pause(): yield obj`.\n\nLet's see an example, suppose you need to reconcile transactions. You need to iterate over thousands of them, detect somehow the faulty ones, and fix them. They could be broken or not synced or invalid or anything else, several different problems. Typically you would have to let the process run, appending to a list each inconsistency found, and waiting, potentially a long time, until the end to be able to do anything. You could mitigate this by processing in chunks, but that has its own implications.\n\nWith the Alive-Progress bar and the Pause mechanism, you can inspect these transactions in **real-time**! You wait only until the next one is found! To use it you would do something like this:\n\n```python\ndef reconcile_transactions():\n qs = Transaction.objects.filter() # django example, or in sqlalchemy: session.query(Transaction).filter()\n with alive_bar(qs.count()) as bar:\n for transaction in qs:\n if not validate(transaction):\n with bar.pause():\n yield transaction\n bar()\n```\n\nThat's it! Then you could use it in ipython or your preferred _REPL_! Just call the function to instantiate the generator and `next()` with it. The progress bar will run as usual, but as soon as an inconsistency is found, the bar pauses itself and you get the prompt back!\n\n```text\nIn [11]: gen = reconcile_transactions()\n\nIn [12]: next(gen, None)\n|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 105/200 [52%] in 5s (18.8/s, eta: 4s)\nOut[12]: Transaction<#123>\n```\n\nHow cool is that?! Debug and fix that transaction any way you want, and when you're done, continue the process with the same `next` as before... The bar returns like nothing happened!! :)\n\n```text\nIn [21]: next(gen, None)\n|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | \u2581\u2583\u2585 105/200 [52%] in 5s (18.8/s, eta: 4s)\n```\n\n\n### Forcing animations on non-interactive consoles (like Pycharm's)\n\nPycharm's python console do not report itself as \"interactive\", so I've included a `force_tty` argument to be able to use the alive-progress bar in it.\n\nSo, just start it as:\n\n```python\nwith alive_bar(1000, force_tty=True) as bar:\n for i in range(1000):\n time.sleep(.01)\n bar()\n```\n\nDo note that this console is heavily instrumented and has more overhead, so the outcome may not be as fluid as you would expect.\n\n\n## To do\n\n- ~~create an unknown mode for bars (without a known total and eta)~~\n- ~~implement a pausing mechanism~~\n- ~~change spinner styles~~\n- ~~change bar styles~~\n- ~~include a global configuration system~~\n- ~~create generators for scrolling, bouncing, delayed and compound spinners~~\n- ~~create an exhibition of spinners and bars, to see them all in motion~~\n- ~~include theme support in configuration~~\n- include colors in spinners and bars\n- try some adaptive algorithm for ETA, like moving average or exponential smoothing\n- any other ideas welcome!\n\n\n## Interesting facts\n\n- This whole project was implemented in functional style;\n- It uses extensively Python _Closures_ and _Generators_, they're in almost all modules;\n- ~It does not declare even a single class~ Now it have one, to enable color support (len and concatenation with colored text);\n- It does not have any dependencies.\n\n\n## Changelog highlights:\n- 1.3.0: new fps calibration support, include force_tty and manual options in global configuration, multiple increment support\n- 1.2.0: filled blanks bar styles, clean underflow representation of filled blanks\n- 1.1.1: optional percentage in manual mode\n- 1.1.0: new manual mode\n- 1.0.1: pycharm console support, improve compatibility with python streams\n- 1.0.0: first public release, already very complete and mature\n\n\n## License\nThis software is licensed under the MIT License. See the LICENSE file in the top distribution directory for the full license text.\n\n\n## Did you like it?\n\nThank you for your interest!\n\nI've put much \u2764\ufe0f and effort into this.\n\nHope you like it.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/rsalmei/alive-progress", "keywords": "progress,bar,spinner,progress-bar,eta,monitoring,python,terminal,multi-threaded,REPL,alive,animated,visual,feedback", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "alive-progress", "package_url": "https://pypi.org/project/alive-progress/", "platform": "", "project_url": "https://pypi.org/project/alive-progress/", "project_urls": { "Homepage": "https://github.com/rsalmei/alive-progress" }, "release_url": "https://pypi.org/project/alive-progress/1.3.0/", "requires_dist": null, "requires_python": ">=2.7, <4", "summary": "An animated and smart Progress Bar for python.", "version": "1.3.0" }, "last_serial": 5839671, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "a20d163bc56e94eaed582786d890cbca", "sha256": "f711420255808e749776f4956ed3bf2240b8d1f223ff0996941901e68780efa2" }, "downloads": -1, "filename": "alive_progress-1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "a20d163bc56e94eaed582786d890cbca", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 15308, "upload_time": "2019-08-05T06:01:35", "url": "https://files.pythonhosted.org/packages/75/bf/38e2628f0ed1461044756a75a7feb7424330ff23b9d0a7f6f01ff456f13a/alive_progress-1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9c6164f59fdc5e03d4a61160aeb5dc30", "sha256": "96293023490bd1750d365e5e52108fe9d505b7c92ce7dbe5a0c72ed9927ddd15" }, "downloads": -1, "filename": "alive-progress-1.0.tar.gz", "has_sig": false, "md5_digest": "9c6164f59fdc5e03d4a61160aeb5dc30", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 14875, "upload_time": "2019-08-05T06:01:37", "url": "https://files.pythonhosted.org/packages/59/4a/63ed275c8a8f4e473435d1b09ef188294356b07026b2bff9f501a88a3bb3/alive-progress-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "851a7b7930362932f68c76917cb0eaa8", "sha256": "f828be59e67dee540700d5329304e199ef34d49a0d1ce9a9702a1aa54f33dd87" }, "downloads": -1, "filename": "alive_progress-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "851a7b7930362932f68c76917cb0eaa8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 16930, "upload_time": "2019-08-09T04:44:43", "url": "https://files.pythonhosted.org/packages/aa/9c/c8a6d7a83dec15bd7c7956b5e4343774b09e00a67c810bf8fa1353417beb/alive_progress-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a8898ed241b8ebeb5fed2143b368fa31", "sha256": "10e7942033c2fd8b1195270f5429640e93254c3c039382d7d1da261ee5a8e086" }, "downloads": -1, "filename": "alive-progress-1.0.1.tar.gz", "has_sig": false, "md5_digest": "a8898ed241b8ebeb5fed2143b368fa31", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 18173, "upload_time": "2019-08-09T04:44:45", "url": "https://files.pythonhosted.org/packages/2e/2f/d71875b08c0c50e892d6cdb5706996bc3b8d3ccee979721eddce89a20388/alive-progress-1.0.1.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "6644718a678ed8fc7153efadad815bbc", "sha256": "0a78f39206bc2981b954507338b16228e89ba2998f7a2328987c0af517605644" }, "downloads": -1, "filename": "alive_progress-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "6644718a678ed8fc7153efadad815bbc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 17741, "upload_time": "2019-08-17T04:17:01", "url": "https://files.pythonhosted.org/packages/41/da/e6ef24e3ad9a1268a16e86f23f4c94721b5c1c0d2e1b23ff8114e3ca2c56/alive_progress-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6de647af47d3c39bf6f7b88d6c93ddbe", "sha256": "6742d82e9bc8640257e38c55b928db0428439242a054233f1df78ca92233e242" }, "downloads": -1, "filename": "alive-progress-1.1.0.tar.gz", "has_sig": false, "md5_digest": "6de647af47d3c39bf6f7b88d6c93ddbe", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 19488, "upload_time": "2019-08-17T04:17:03", "url": "https://files.pythonhosted.org/packages/49/d3/e76e5080dba3ef0c021ce865a98b398f75617cb72da876072c5ab77b8713/alive-progress-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "4323e5de32425668e53c350b2d3d8bf6", "sha256": "41279b87cfd62ba5462020dc1215442f51c6471886b6ac957c04977f8a529211" }, "downloads": -1, "filename": "alive_progress-1.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "4323e5de32425668e53c350b2d3d8bf6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 17941, "upload_time": "2019-08-21T03:03:48", "url": "https://files.pythonhosted.org/packages/5c/e9/4ae1a3359eb06a12fccdf8cc5a734aa658ee4205b4c5c71e1bff78a5c9c1/alive_progress-1.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d810c440072a6298fc93aa6efe90a2bf", "sha256": "9e74640dd0ee8e0a70643c3d08d7bba0fbebdfe0652db20f5b7ed02b182e7a8a" }, "downloads": -1, "filename": "alive-progress-1.1.1.tar.gz", "has_sig": false, "md5_digest": "d810c440072a6298fc93aa6efe90a2bf", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 19876, "upload_time": "2019-08-21T03:03:50", "url": "https://files.pythonhosted.org/packages/a5/41/31ac2195d37d5f2c2c9c8cc51a61dd4788e0b9826f4b5895609689fd43d0/alive-progress-1.1.1.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "424c41502cdbdab722765c58b6ab0ddd", "sha256": "2017a460cfc45b85421795282296f3706f5e140f8a7deea24c1bf8b49369a685" }, "downloads": -1, "filename": "alive_progress-1.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "424c41502cdbdab722765c58b6ab0ddd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 18151, "upload_time": "2019-08-24T06:02:53", "url": "https://files.pythonhosted.org/packages/c3/15/604e6bbd85dbe540b82594e82f487a43b5e50562184239e7c3fc8e46fa4b/alive_progress-1.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "326cd434e71c8fdabeaec4dc17fabec4", "sha256": "179671e5ae842b152768739b0e68fed479f2b698076812156e825dabc8c7a4a3" }, "downloads": -1, "filename": "alive-progress-1.2.0.tar.gz", "has_sig": false, "md5_digest": "326cd434e71c8fdabeaec4dc17fabec4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 20155, "upload_time": "2019-08-24T06:02:55", "url": "https://files.pythonhosted.org/packages/b7/0b/cea68a10df1cffb20a742277222e3e31dfe00b015f5f55f47b9aa4587ee4/alive-progress-1.2.0.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "c493d8969ec61e452281bcc75c9aef51", "sha256": "c55a690d474a44cb91f7d39844dade27c242ad8b4201c1ab896b1fe87db98436" }, "downloads": -1, "filename": "alive_progress-1.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "c493d8969ec61e452281bcc75c9aef51", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 20506, "upload_time": "2019-09-17T05:45:08", "url": "https://files.pythonhosted.org/packages/bf/f8/7ee19176595f56a0ee0b5f38c9837585ab6b7f5f85406c62ebcf17109bd7/alive_progress-1.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d5cf7feddb4ea9e23caa3005d5dade57", "sha256": "3bd4bd9952d94aa3ba76dde684e994bea073cca53c92357732d35b4609dc6c29" }, "downloads": -1, "filename": "alive-progress-1.3.0.tar.gz", "has_sig": false, "md5_digest": "d5cf7feddb4ea9e23caa3005d5dade57", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 23163, "upload_time": "2019-09-17T05:45:11", "url": "https://files.pythonhosted.org/packages/e6/a4/1e44dadbf3b72e0ce1f22f1630ca9e4da9dee3654560d830738ceff41730/alive-progress-1.3.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c493d8969ec61e452281bcc75c9aef51", "sha256": "c55a690d474a44cb91f7d39844dade27c242ad8b4201c1ab896b1fe87db98436" }, "downloads": -1, "filename": "alive_progress-1.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "c493d8969ec61e452281bcc75c9aef51", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=2.7, <4", "size": 20506, "upload_time": "2019-09-17T05:45:08", "url": "https://files.pythonhosted.org/packages/bf/f8/7ee19176595f56a0ee0b5f38c9837585ab6b7f5f85406c62ebcf17109bd7/alive_progress-1.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d5cf7feddb4ea9e23caa3005d5dade57", "sha256": "3bd4bd9952d94aa3ba76dde684e994bea073cca53c92357732d35b4609dc6c29" }, "downloads": -1, "filename": "alive-progress-1.3.0.tar.gz", "has_sig": false, "md5_digest": "d5cf7feddb4ea9e23caa3005d5dade57", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, <4", "size": 23163, "upload_time": "2019-09-17T05:45:11", "url": "https://files.pythonhosted.org/packages/e6/a4/1e44dadbf3b72e0ce1f22f1630ca9e4da9dee3654560d830738ceff41730/alive-progress-1.3.0.tar.gz" } ] }