Name | riprova JSON |
Version |
0.3.1
JSON |
| download |
home_page | https://github.com/h2non/riprova |
Summary | Small and versatile library to retry failed operations using different backoff strategies |
upload_time | 2023-08-07 09:23:46 |
maintainer | |
docs_url | None |
author | Tomas Aparicio |
requires_python | |
license | MIT |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
riprova |PyPI| |Coverage Status| |Documentation Status| |Quality| |Versions|
============================================================================
``riprova`` (meaning ``retry`` in Italian) is a small, general-purpose and versatile `Python`_ library
that provides retry mechanisms with multiple backoff strategies for any sort of failed operations.
It's domain agnostic, highly customizable, extensible and provides a minimal API that's easy to instrument in any code base via decorators, context managers or raw API consumption.
For a brief introduction about backoff mechanisms for potential failed operations, `read this article`_.
Features
--------
- Retry decorator for simple and idiomatic consumption.
- Simple Pythonic programmatic interface.
- Maximum retry timeout support.
- Supports error `whitelisting`_ and `blacklisting`_.
- Supports custom `error evaluation`_ retry logic (useful to retry only in specific cases).
- Automatically retry operations on raised exceptions.
- Supports `asynchronous coroutines`_ with both ``async/await`` and ``yield from`` syntax.
- Configurable maximum number of retry attempts.
- Highly configurable supporting max retries, timeouts or retry notifier callback.
- Built-in backoff strategies: constant, `fibonacci`_ and `exponential`_ backoffs.
- Supports sync/async context managers.
- Pluggable custom backoff strategies.
- Lightweight library with almost zero embedding cost.
- Works with Python +2.6, 3.0+ and PyPy.
Backoff strategies
------------------
List of built-in backoff strategies.
- `Constant backoff`_
- `Fibonacci backoff`_
- `Exponential backoff`_
You can also implement your own one easily.
See `ConstantBackoff`_ for an implementation reference.
Installation
------------
Using ``pip`` package manager (requires pip 1.9+. Upgrade it running: ``pip install -U pip``):
.. code-block:: bash
pip install -U riprova
Or install the latest sources from Github:
.. code-block:: bash
pip install -e git+git://github.com/h2non/riprova.git#egg=riprova
API
---
- riprova.retry_
- riprova.Retrier_
- riprova.AsyncRetrier_
- riprova.Backoff_
- riprova.ConstantBackoff_
- riprova.FibonacciBackoff_
- riprova.ExponentialBackoff_
- riprova.ErrorWhitelist_
- riprova.ErrorBlacklist_
- riprova.add_whitelist_error_
- riprova.RetryError_
- riprova.RetryTimeoutError_
- riprova.MaxRetriesExceeded_
- riprova.NotRetriableError_
.. _riprova.retry: http://riprova.readthedocs.io/en/latest/api.html#riprova.retry
.. _riprova.Retrier: http://riprova.readthedocs.io/en/latest/api.html#riprova.Retrier
.. _riprova.AsyncRetrier: http://riprova.readthedocs.io/en/latest/api.html#riprova.AsyncRetrier
.. _riprova.Backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.Backoff
.. _riprova.ConstantBackoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ConstantBackoff
.. _riprova.FibonacciBackoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.FibonacciBackoff
.. _riprova.ExponentialBackoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ExponentialBackoff
.. _riprova.ErrorWhitelist: http://riprova.readthedocs.io/en/latest/api.html#riprova.ErrorWhitelist
.. _riprova.ErrorBlacklist: http://riprova.readthedocs.io/en/latest/api.html#riprova.ErrorBlacklist
.. _riprova.add_whitelist_error: http://riprova.readthedocs.io/en/latest/api.html#riprova.add_whitelist_error
.. _riprova.RetryError: http://riprova.readthedocs.io/en/latest/api.html#riprova.RetryError
.. _riprova.RetryTimeoutError: http://riprova.readthedocs.io/en/latest/api.html#riprova.RetryTimeoutError
.. _riprova.MaxRetriesExceeded: http://riprova.readthedocs.io/en/latest/api.html#riprova.MaxRetriesExceeded
.. _riprova.NotRetriableError: http://riprova.readthedocs.io/en/latest/api.html#riprova.NotRetriableError
Examples
^^^^^^^^
You can see more featured examples from the `documentation` site.
**Basic usage examples**:
.. code-block:: python
import riprova
@riprova.retry
def task():
"""Retry operation if it fails with constant backoff (default)"""
@riprova.retry(backoff=riprova.ConstantBackoff(retries=5))
def task():
"""Retry operation if it fails with custom max number of retry attempts"""
@riprova.retry(backoff=riprova.ExponentialBackOff(factor=0.5))
def task():
"""Retry operation if it fails using exponential backoff"""
@riprova.retry(timeout=10)
def task():
"""Raises a TimeoutError if the retry loop exceeds from 10 seconds"""
def on_retry(err, next_try):
print('Operation error: {}'.format(err))
print('Next try in: {}ms'.format(next_try))
@riprova.retry(on_retry=on_retry)
def task():
"""Subscribe via function callback to every retry attempt"""
def evaluator(response):
# Force retry operation if not a valid response
if response.status >= 400:
raise RuntimeError('invalid response status') # or simple return True
# Otherwise return False, meaning no retry
return False
@riprova.retry(evaluator=evaluator)
def task():
"""Use a custom evaluator function to determine if the operation failed or not"""
@riprova.retry
async def task():
"""Asynchronous coroutines are also supported :)"""
**Retry failed HTTP requests**:
.. code-block:: python
import pook
import requests
from riprova import retry
# Define HTTP mocks to simulate failed requests
pook.get('server.com').times(3).reply(503)
pook.get('server.com').times(1).reply(200).json({'hello': 'world'})
# Retry evaluator function used to determine if the operated failed or not
def evaluator(response):
if response != 200:
return Exception('failed request') # you can also simply return True
return False
# On retry even subscriptor
def on_retry(err, next_try):
print('Operation error {}'.format(err))
print('Next try in {}ms'.format(next_try))
# Register retriable operation
@retry(evaluator=evaluator, on_retry=on_retry)
def fetch(url):
return requests.get(url)
# Run task that might fail
fetch('http://server.com')
License
-------
MIT - Tomas Aparicio
.. _exponential: https://en.wikipedia.org/wiki/Exponential_backoff
.. _fibonacci: https://en.wikipedia.org/wiki/Fibonacci_number
.. _asyncio: https://docs.python.org/3.5/library/asyncio.html
.. _Python: http://python.org
.. _annotated API reference: https://h2non.github.io/paco
.. _async/await: https://www.python.org/dev/peps/pep-0492/
.. _yield from: https://www.python.org/dev/peps/pep-0380/
.. _documentation: http://riprova.readthedocs.io/en/latest/examples.html
.. _read this article: http://dthain.blogspot.ie/2009/02/exponential-backoff-in-distributed.html
.. _Constant backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ConstantBackoff
.. _Fibonacci backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.FibonacciBackoff
.. _Exponential backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ExponentialBackOff
.. _ConstantBackoff: https://github.com/h2non/riprova/blob/master/riprova/strategies/constant.py
.. _whitelisting: https://github.com/h2non/riprova/blob/master/examples/whitelisting_errors.py
.. _blacklisting: https://github.com/h2non/riprova/blob/master/examples/blacklisting_errors.py
.. _error evaluation: https://github.com/h2non/riprova/blob/master/examples/http_request.py
.. _asynchronous coroutines: https://github.com/h2non/riprova/blob/master/examples/http_asyncio.py
.. |PyPI| image:: https://img.shields.io/pypi/v/riprova.svg?maxAge=2592000?style=flat-square
:target: https://pypi.python.org/pypi/riprova
.. |Coverage Status| image:: https://coveralls.io/repos/github/h2non/riprova/badge.svg?branch=master
:target: https://coveralls.io/github/h2non/riprova?branch=master
.. |Documentation Status| image:: https://img.shields.io/badge/docs-latest-green.svg?style=flat
:target: http://riprova.readthedocs.io/en/latest/?badge=latest
.. |Quality| image:: https://codeclimate.com/github/h2non/riprova/badges/gpa.svg
:target: https://codeclimate.com/github/h2non/riprova
.. |Stability| image:: https://img.shields.io/pypi/status/riprova.svg
:target: https://pypi.python.org/pypi/riprova
.. |Versions| image:: https://img.shields.io/pypi/pyversions/riprova.svg
:target: https://pypi.python.org/pypi/riprova
v0.3.0 / 2023-05-20
-------------------
* Deprecate asyncio.corouting
* Drop Python 2 and 3.4 support
v0.2.7 / 2018-08-24
-------------------
* Merge pull request #20 from ffix/forward-exception-instance
* Correct linter warnings
* Re-raise exception instance instead of new exception with no args
* Merge pull request #19 from EdwardBetts/spelling
* Correct spelling mistakes.
* feat(setup): support Python 3.7
* feat(History): add version changes
v0.2.6 / 2018-04-14
-------------------
* fix(#17): handle as legit retriable error Timeout exceptions.
v0.2.5 / 2018-03-21
-------------------
* Merge pull request #15 from jstasiak/allow-newer-six
* Allow newer six
* feat(History): update changes
v0.2.5 / 2018-03-21
-------------------
* Merge pull request #15 from jstasiak/allow-newer-six
* Allow newer six
* feat(History): update changes
v0.2.4 / 2018-03-20
-------------------
* merge(#14): Allow subsecond maxtimes for ExponentialBackoff
v0.2.3 / 2017-01-13
-------------------
* refactor(retry): remove unnecessary partial function
* fix(retry): rename keyword param for partial application
* feat(docs): improve description
* refactor(Makefile): update publish task
v0.2.2 / 2017-01-06
-------------------
* feat(package): add wheel distribution
v0.2.1 / 2017-01-04
-------------------
* fix(retrier): remove debug print statement
v0.2.0 / 2017-01-02
-------------------
* feat(core): use seconds as default time unit (introduces API breaking changes)
* refactor(examples): update examples to use new time unit
* feat(contextmanager): adds context manager support
* feat(examples): add context manager example
* feat: add context managers support
v0.1.3 / 2016-12-30
-------------------
* refactor(async_retrier): simplify coroutine wrapper
* feat(whitelist): add whitelist and blacklist support
* feat(tests): add missing test cases for whitelist
* feat(retry): pass error_evaluator param
* fix(retrier): cast delay to float
* fix(tests): use valid exception for Python 2.7
* feat(#6): add custom error whilelist and custom error evaluator function
* Merge pull request #8 from tsarpaul/master
* refactor(decorator): do not expose retrier instance
v0.1.2 / 2016-12-27
-------------------
* fix(decorator): wrap retries instance per function call
v0.1.1 / 2016-12-27
-------------------
* fix(`#2`_): handle and forward ``asyncio.CancelledError`` as non-retriable error
v0.1.0 / 2016-12-25
-------------------
* First version
.. _#2: https://github.com/h2non/riprova/issues/2
Raw data
{
"_id": null,
"home_page": "https://github.com/h2non/riprova",
"name": "riprova",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "",
"author": "Tomas Aparicio",
"author_email": "tomas+python@aparicio.me",
"download_url": "https://files.pythonhosted.org/packages/2a/f7/b163b617abc6057221eec8e37daf437a6b81db5279bee368748be8e2e5b1/riprova-0.3.1.tar.gz",
"platform": null,
"description": "riprova |PyPI| |Coverage Status| |Documentation Status| |Quality| |Versions|\n============================================================================\n\n``riprova`` (meaning ``retry`` in Italian) is a small, general-purpose and versatile `Python`_ library\nthat provides retry mechanisms with multiple backoff strategies for any sort of failed operations.\n\nIt's domain agnostic, highly customizable, extensible and provides a minimal API that's easy to instrument in any code base via decorators, context managers or raw API consumption.\n\nFor a brief introduction about backoff mechanisms for potential failed operations, `read this article`_.\n\n\nFeatures\n--------\n\n- Retry decorator for simple and idiomatic consumption.\n- Simple Pythonic programmatic interface.\n- Maximum retry timeout support.\n- Supports error `whitelisting`_ and `blacklisting`_.\n- Supports custom `error evaluation`_ retry logic (useful to retry only in specific cases).\n- Automatically retry operations on raised exceptions.\n- Supports `asynchronous coroutines`_ with both ``async/await`` and ``yield from`` syntax.\n- Configurable maximum number of retry attempts.\n- Highly configurable supporting max retries, timeouts or retry notifier callback.\n- Built-in backoff strategies: constant, `fibonacci`_ and `exponential`_ backoffs.\n- Supports sync/async context managers.\n- Pluggable custom backoff strategies.\n- Lightweight library with almost zero embedding cost.\n- Works with Python +2.6, 3.0+ and PyPy.\n\n\nBackoff strategies\n------------------\n\nList of built-in backoff strategies.\n\n- `Constant backoff`_\n- `Fibonacci backoff`_\n- `Exponential backoff`_\n\nYou can also implement your own one easily.\nSee `ConstantBackoff`_ for an implementation reference.\n\n\nInstallation\n------------\n\nUsing ``pip`` package manager (requires pip 1.9+. Upgrade it running: ``pip install -U pip``):\n\n.. code-block:: bash\n\n pip install -U riprova\n\nOr install the latest sources from Github:\n\n.. code-block:: bash\n\n pip install -e git+git://github.com/h2non/riprova.git#egg=riprova\n\n\nAPI\n---\n\n- riprova.retry_\n- riprova.Retrier_\n- riprova.AsyncRetrier_\n- riprova.Backoff_\n- riprova.ConstantBackoff_\n- riprova.FibonacciBackoff_\n- riprova.ExponentialBackoff_\n- riprova.ErrorWhitelist_\n- riprova.ErrorBlacklist_\n- riprova.add_whitelist_error_\n- riprova.RetryError_\n- riprova.RetryTimeoutError_\n- riprova.MaxRetriesExceeded_\n- riprova.NotRetriableError_\n\n\n.. _riprova.retry: http://riprova.readthedocs.io/en/latest/api.html#riprova.retry\n.. _riprova.Retrier: http://riprova.readthedocs.io/en/latest/api.html#riprova.Retrier\n.. _riprova.AsyncRetrier: http://riprova.readthedocs.io/en/latest/api.html#riprova.AsyncRetrier\n.. _riprova.Backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.Backoff\n.. _riprova.ConstantBackoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ConstantBackoff\n.. _riprova.FibonacciBackoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.FibonacciBackoff\n.. _riprova.ExponentialBackoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ExponentialBackoff\n.. _riprova.ErrorWhitelist: http://riprova.readthedocs.io/en/latest/api.html#riprova.ErrorWhitelist\n.. _riprova.ErrorBlacklist: http://riprova.readthedocs.io/en/latest/api.html#riprova.ErrorBlacklist\n.. _riprova.add_whitelist_error: http://riprova.readthedocs.io/en/latest/api.html#riprova.add_whitelist_error\n.. _riprova.RetryError: http://riprova.readthedocs.io/en/latest/api.html#riprova.RetryError\n.. _riprova.RetryTimeoutError: http://riprova.readthedocs.io/en/latest/api.html#riprova.RetryTimeoutError\n.. _riprova.MaxRetriesExceeded: http://riprova.readthedocs.io/en/latest/api.html#riprova.MaxRetriesExceeded\n.. _riprova.NotRetriableError: http://riprova.readthedocs.io/en/latest/api.html#riprova.NotRetriableError\n\n\nExamples\n^^^^^^^^\n\nYou can see more featured examples from the `documentation` site.\n\n**Basic usage examples**:\n\n.. code-block:: python\n\n import riprova\n\n @riprova.retry\n def task():\n \"\"\"Retry operation if it fails with constant backoff (default)\"\"\"\n\n @riprova.retry(backoff=riprova.ConstantBackoff(retries=5))\n def task():\n \"\"\"Retry operation if it fails with custom max number of retry attempts\"\"\"\n\n @riprova.retry(backoff=riprova.ExponentialBackOff(factor=0.5))\n def task():\n \"\"\"Retry operation if it fails using exponential backoff\"\"\"\n\n @riprova.retry(timeout=10)\n def task():\n \"\"\"Raises a TimeoutError if the retry loop exceeds from 10 seconds\"\"\"\n\n def on_retry(err, next_try):\n print('Operation error: {}'.format(err))\n print('Next try in: {}ms'.format(next_try))\n\n @riprova.retry(on_retry=on_retry)\n def task():\n \"\"\"Subscribe via function callback to every retry attempt\"\"\"\n\n def evaluator(response):\n # Force retry operation if not a valid response\n if response.status >= 400:\n raise RuntimeError('invalid response status') # or simple return True\n # Otherwise return False, meaning no retry\n return False\n\n @riprova.retry(evaluator=evaluator)\n def task():\n \"\"\"Use a custom evaluator function to determine if the operation failed or not\"\"\"\n\n @riprova.retry\n async def task():\n \"\"\"Asynchronous coroutines are also supported :)\"\"\"\n\n\n**Retry failed HTTP requests**:\n\n.. code-block:: python\n\n import pook\n import requests\n from riprova import retry\n\n # Define HTTP mocks to simulate failed requests\n pook.get('server.com').times(3).reply(503)\n pook.get('server.com').times(1).reply(200).json({'hello': 'world'})\n\n\n # Retry evaluator function used to determine if the operated failed or not\n def evaluator(response):\n if response != 200:\n return Exception('failed request') # you can also simply return True\n return False\n\n\n # On retry even subscriptor\n def on_retry(err, next_try):\n print('Operation error {}'.format(err))\n print('Next try in {}ms'.format(next_try))\n\n\n # Register retriable operation\n @retry(evaluator=evaluator, on_retry=on_retry)\n def fetch(url):\n return requests.get(url)\n\n\n # Run task that might fail\n fetch('http://server.com')\n\n\n\nLicense\n-------\n\nMIT - Tomas Aparicio\n\n.. _exponential: https://en.wikipedia.org/wiki/Exponential_backoff\n.. _fibonacci: https://en.wikipedia.org/wiki/Fibonacci_number\n.. _asyncio: https://docs.python.org/3.5/library/asyncio.html\n.. _Python: http://python.org\n.. _annotated API reference: https://h2non.github.io/paco\n.. _async/await: https://www.python.org/dev/peps/pep-0492/\n.. _yield from: https://www.python.org/dev/peps/pep-0380/\n.. _documentation: http://riprova.readthedocs.io/en/latest/examples.html\n.. _read this article: http://dthain.blogspot.ie/2009/02/exponential-backoff-in-distributed.html\n.. _Constant backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ConstantBackoff\n.. _Fibonacci backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.FibonacciBackoff\n.. _Exponential backoff: http://riprova.readthedocs.io/en/latest/api.html#riprova.ExponentialBackOff\n.. _ConstantBackoff: https://github.com/h2non/riprova/blob/master/riprova/strategies/constant.py\n.. _whitelisting: https://github.com/h2non/riprova/blob/master/examples/whitelisting_errors.py\n.. _blacklisting: https://github.com/h2non/riprova/blob/master/examples/blacklisting_errors.py\n.. _error evaluation: https://github.com/h2non/riprova/blob/master/examples/http_request.py\n.. _asynchronous coroutines: https://github.com/h2non/riprova/blob/master/examples/http_asyncio.py\n\n.. |PyPI| image:: https://img.shields.io/pypi/v/riprova.svg?maxAge=2592000?style=flat-square\n :target: https://pypi.python.org/pypi/riprova\n.. |Coverage Status| image:: https://coveralls.io/repos/github/h2non/riprova/badge.svg?branch=master\n :target: https://coveralls.io/github/h2non/riprova?branch=master\n.. |Documentation Status| image:: https://img.shields.io/badge/docs-latest-green.svg?style=flat\n :target: http://riprova.readthedocs.io/en/latest/?badge=latest\n.. |Quality| image:: https://codeclimate.com/github/h2non/riprova/badges/gpa.svg\n :target: https://codeclimate.com/github/h2non/riprova\n.. |Stability| image:: https://img.shields.io/pypi/status/riprova.svg\n :target: https://pypi.python.org/pypi/riprova\n.. |Versions| image:: https://img.shields.io/pypi/pyversions/riprova.svg\n :target: https://pypi.python.org/pypi/riprova\n\n\n\nv0.3.0 / 2023-05-20\n-------------------\n\n * Deprecate asyncio.corouting\n * Drop Python 2 and 3.4 support\n\nv0.2.7 / 2018-08-24\n-------------------\n\n * Merge pull request #20 from ffix/forward-exception-instance\n * Correct linter warnings\n * Re-raise exception instance instead of new exception with no args\n * Merge pull request #19 from EdwardBetts/spelling\n * Correct spelling mistakes.\n * feat(setup): support Python 3.7\n * feat(History): add version changes\n\nv0.2.6 / 2018-04-14\n-------------------\n\n* fix(#17): handle as legit retriable error Timeout exceptions.\n\nv0.2.5 / 2018-03-21\n-------------------\n\n* Merge pull request #15 from jstasiak/allow-newer-six\n* Allow newer six\n* feat(History): update changes\n\nv0.2.5 / 2018-03-21\n-------------------\n\n* Merge pull request #15 from jstasiak/allow-newer-six\n* Allow newer six\n* feat(History): update changes\n\nv0.2.4 / 2018-03-20\n-------------------\n\n* merge(#14): Allow subsecond maxtimes for ExponentialBackoff\n\nv0.2.3 / 2017-01-13\n-------------------\n\n* refactor(retry): remove unnecessary partial function\n* fix(retry): rename keyword param for partial application\n* feat(docs): improve description\n* refactor(Makefile): update publish task\n\nv0.2.2 / 2017-01-06\n-------------------\n\n* feat(package): add wheel distribution\n\nv0.2.1 / 2017-01-04\n-------------------\n\n* fix(retrier): remove debug print statement\n\nv0.2.0 / 2017-01-02\n-------------------\n\n* feat(core): use seconds as default time unit (introduces API breaking changes)\n* refactor(examples): update examples to use new time unit\n* feat(contextmanager): adds context manager support\n* feat(examples): add context manager example\n* feat: add context managers support\n\nv0.1.3 / 2016-12-30\n-------------------\n\n* refactor(async_retrier): simplify coroutine wrapper\n* feat(whitelist): add whitelist and blacklist support\n* feat(tests): add missing test cases for whitelist\n* feat(retry): pass error_evaluator param\n* fix(retrier): cast delay to float\n* fix(tests): use valid exception for Python 2.7\n* feat(#6): add custom error whilelist and custom error evaluator function\n* Merge pull request #8 from tsarpaul/master\n* refactor(decorator): do not expose retrier instance\n\nv0.1.2 / 2016-12-27\n-------------------\n\n* fix(decorator): wrap retries instance per function call\n\nv0.1.1 / 2016-12-27\n-------------------\n\n* fix(`#2`_): handle and forward ``asyncio.CancelledError`` as non-retriable error\n\nv0.1.0 / 2016-12-25\n-------------------\n\n* First version\n\n\n.. _#2: https://github.com/h2non/riprova/issues/2\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Small and versatile library to retry failed operations using different backoff strategies",
"version": "0.3.1",
"project_urls": {
"Homepage": "https://github.com/h2non/riprova"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "176139b608b848bd1f4028f2fd3be1b1e38da625eecb248f19416af8fd2a7e20",
"md5": "fa151734b279a0be8e9e0af1dcfaa187",
"sha256": "fc1bd9bfd8befd453e322b2111839ecb3a0ccabb8af6ff10c5942f1a2143f807"
},
"downloads": -1,
"filename": "riprova-0.3.1-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "fa151734b279a0be8e9e0af1dcfaa187",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 21931,
"upload_time": "2023-08-07T09:23:43",
"upload_time_iso_8601": "2023-08-07T09:23:43.983199Z",
"url": "https://files.pythonhosted.org/packages/17/61/39b608b848bd1f4028f2fd3be1b1e38da625eecb248f19416af8fd2a7e20/riprova-0.3.1-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2af7b163b617abc6057221eec8e37daf437a6b81db5279bee368748be8e2e5b1",
"md5": "d0bc0b180bd04f93b61f23244cb043d9",
"sha256": "16017249bbc18dc654d9b8e8e34ff53bb82573aa05596d398e29c439f3163152"
},
"downloads": -1,
"filename": "riprova-0.3.1.tar.gz",
"has_sig": false,
"md5_digest": "d0bc0b180bd04f93b61f23244cb043d9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 20156,
"upload_time": "2023-08-07T09:23:46",
"upload_time_iso_8601": "2023-08-07T09:23:46.791822Z",
"url": "https://files.pythonhosted.org/packages/2a/f7/b163b617abc6057221eec8e37daf437a6b81db5279bee368748be8e2e5b1/riprova-0.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-07 09:23:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "h2non",
"github_project": "riprova",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"tox": true,
"lcname": "riprova"
}