Skip to content

Commit

Permalink
Merge pull request #2 from austind/develop
Browse files Browse the repository at this point in the history
Release v0.2.0
  • Loading branch information
austind authored Jul 2, 2024
2 parents 24e61d6 + f7b187c commit 8adc025
Show file tree
Hide file tree
Showing 17 changed files with 444 additions and 334 deletions.
92 changes: 92 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: CD Workflow

on:
push:
tags:
- 'release/v*.*.*'

jobs:
# build:
# name: Build package
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: actions/setup-python@v5
# with:
# python-version: "3.x"

# - name: Install dependencies
# run: python3 -m pip install build --user

# - name: Build package
# run: python3 -m build

# github-release:
# name: Publish GitHub release
# runs-on: ubuntu-latest
# needs:
# - build
# permissions:
# contents: write
# id-token: write

# steps:
# - name: Download dists
# uses: actions/download-artifact@v3
# with:
# name: python-package-distributions
# path: dist/

# - name: Create GitHub release
# id: create_release
# uses: actions/create-release@v1
# env:
# GITHUB_TOKEN: ${{ github.token }}
# with:
# tag_name: ${{ github.ref }}
# release_name: ${{ github.ref }}
# body: |
# See [changelog](https://retryhttp.readthedocs.io/changelog).
# draft: false
# prerelease: false

# - name: Upload release assets
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: ./dist
# asset_name: retryhttp_${{ github.ref }}.zip
# asset_content_type: application/zip

# publish-to-pypi:
# name: Publish to PyPI
# runs-on: ubuntu-latest
# needs:
# - build
# environment:
# name: pypi
# url: https://pypi.org/p/retryhttp
# permissions:
# id-token: write

# steps:
# - name: Download dists
# uses: actions/download-artifact@v3
# with:
# name: python-package-distributions
# path: dist/

# - name: Publish package to PyPI
# uses: pypa/gh-action-pypi-publish@release/v1.9
# with:
# password: ${{ secrets.PYPI_TOKEN }}
publish-to-rtd:
name: Publish to Read The Docs
runs-on: ubuntu-latest
steps:
- uses: rtfd/readthedocs-action@v1
with:
token: ${{ secrets.RTD_TOKEN }}
version: ${{ github.ref_name }}
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ Several HTTP errors are often transient, and might succeed if retried:
* Network errors
* Timeouts

This project aims to simplify retrying these, by extending [`tenacity`](https://github.com/jd/tenacity) with custom retry and wait strategies, as well as a custom decorator. Defaults are sensible for most use cases, but are fully customizable.
This project aims to simplify retrying these, by extending [`tenacity`](https://tenacity.readthedocs.io/) with custom retry and wait strategies, as well as a custom decorator. Defaults are sensible for most use cases, but are fully customizable.

Supports exceptions raised by both [`requests`](https://github.com/psf/requests) and [`httpx`](https://github.com/encode/httpx).
Supports exceptions raised by both [`requests`](https://docs.python-requests.org/en/latest/index.html) and [`httpx`](https://python-httpx.org/).

## Install

Install most recent stable release from PyPI:
## Install

Install from PyPI:

```sh
pip install retryhttp # Supports both HTTPX and requests
# Supports both HTTPX and requests
pip install retryhttp
```

You can also install support for only HTTPX or requests:
Expand All @@ -41,21 +44,23 @@ pip install retryhttp[requests] # Supports only requests
Or, install the latest development snapshot from git:

```sh
pip install git+https://github.com/austind/retryhttp.git@main
pip install git+https://github.com/austind/retryhttp.git@develop
```

## Quickstart

```python
import httpx
from retryhttp import retry_http_errors
from retryhttp import retry

# Retries all HTTP status codes, network errors, and timeouts listed above
# for a maximum of 3 attempts
@retry_http_errors()
def get_example():
# Retries retryable status codes (429, 500, 502, 503, 504), network errors,
# and timeouts, up to 3 times, with appropriate wait strategies for each
# type of error. All of these behaviors are customizable.
@retry
def example():
response = httpx.get("https://example.com/")
response.raise_for_status()
return response.text

```

Expand Down
12 changes: 6 additions & 6 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# API Reference

## Retry Decorator
## Decorator

Wraps [`tenacity.retry`][] with sensible defaults for most use cases.
This decorator wraps [`tenacity.retry`](https://tenacity.readthedocs.io/en/latest/api.html#tenacity.retry) with sensible defaults for retrying potentially transient HTTP errors. It's the most convenient way to leverage `retryhttp`.

::: retryhttp.retry_http_errors
::: retryhttp.retry

## Retry Strategies

If you'd rather use [`tenacity.retry`][] directly (without using [`retryhttp.retry_http_errors`][]), you can use these retry strategies.
If you'd rather use [`tenacity.retry`](https://tenacity.readthedocs.io/en/latest/api.html#tenacity.retry) directly (without using [`retryhttp.retry`][]), you can use these retry strategies.

::: retryhttp.retry_if_network_error

Expand All @@ -20,10 +20,10 @@ If you'd rather use [`tenacity.retry`][] directly (without using [`retryhttp.ret

## Wait Strategies

Wait strategies to use with [`tenacity.retry`][] or [`retryhttp.retry_http_errors`][].
Wait strategies to use with [`tenacity.retry`](https://tenacity.readthedocs.io/en/latest/api.html#tenacity.retry) or [`retryhttp.retry`][].

::: retryhttp.wait_from_header

::: retryhttp.wait_http_errors
::: retryhttp.wait_context_aware

::: retryhttp.wait_rate_limited
24 changes: 24 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Changelog

## v0.2.0

* Rename `retryhttp.retry_http_errors` to [`retryhttp.retry`][].
* Rename `retryhttp.wait_http_errors` to [`retryhttp.wait_context_aware`][].
* Restructure project so all members are part of the root namespace.
* Move type delcarations to `retryhttp._types`.
* Enable bare decorator syntax for [`retryhttp.retry`][] (i.e., `@retry` works as well as `@retry()`)

## v0.1.0

Initial release.

Added the following methods and classes:

* `retryhttp.retry_http_errors`
* [`retryhttp.retry_if_network_error`][]
* [`retryhttp.retry_if_rate_limited`][]
* [`retryhttp.retry_if_server_error`][]
* [`retryhttp.retry_if_timeout`][]
* [`retryhttp.wait_from_header`][]
* [`retryhttp.wait_rate_limited`][]
* [`retryhttp.wait_context_aware`][]
16 changes: 8 additions & 8 deletions docs/guide.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
## Overview

Under the hood, RetryHTTP is a convenience layer on top of the excellent retry library [`tenacity`](https://github.com/jd/tenacity).
Under the hood, RetryHTTP is a convenience layer on top of the excellent retry library [`tenacity`](https://tenacity.readthedocs.io/).

`tenacity` works by adding a decorator to functions that might fail. This decorator is configured with retry, wait, and stop strategies that configure what conditions to retry, how long to wait between retries, and when to stop retrying, respectively. Failures could be a raised exception, or a configurable return value. See [`tenacity` documentation](https://tenacity.readthedocs.io/en/latest/index.html) for details.

`retryhttp` provides new retry and stop strategies specific to potentially transient error conditions raised by `httpx` and `requests`. To make things as convenient as possible, `retryhttp` also provides a [retryhttp.retry_http_errors][custom decorator] that wraps [tenacity.retry][] with customizable defaults.
`retryhttp` provides new retry and stop strategies for potentially transient error conditions raised by `httpx` and `requests`. To make things as convenient as possible, `retryhttp` also provides a [new decorator][retryhttp.retry] that wraps [`tenacity.retry`](https://tenacity.readthedocs.io/en/latest/api.html#tenacity.retry) with sensible defaults, which are all customizable.

## Examples

```python
import httpx
from tenacity import wait_exponential, wait_rate_limited
from retryhttp import retry_http_errors
from retryhttp import retry

# Retry only 503 Service Unavailable and network errors up to 5 times
# with default wait strategies.
@retry_http_errors(
@retry(
max_attempt_number=5,
retry_timeouts=False,
retry_rate_limited=False,
Expand All @@ -26,7 +26,7 @@ def get_example():
response.raise_for_status()

# Retry only httpx.ConnectError and apply a custom wait strategy.
@retry_http_errors(
@retry(
retry_timeouts=False,
retry_rate_limited=False,
retry_server_errors=False,
Expand All @@ -41,7 +41,7 @@ def get_example():
# fallback wait strategy for rate limited (429 Too Many Requests). I.e.,
# we'll honor the Retry-After header if it exists, otherwise we'll use
# a custom wait_exponential
@retry_http_errors(
@retry(
max_attempt_number=5
wait_rate_limited=wait_rate_limited(
fallback=wait_exponential(multiplier=0.5, min=0.5, max=20)
Expand All @@ -54,10 +54,10 @@ def get_example():

## Advanced Usage

You don't have to use the [`retryhttp.retry_http_errors`][] decorator, which is provided purely for convenience. If you prefer, you can use [`tenacity.retry`][] and roll your own approach.
You don't have to use the [`retryhttp.retry`][] decorator, which is provided purely for convenience. If you prefer, you can use [`tenacity.retry`](https://tenacity.readthedocs.io/en/latest/api.html#tenacity.retry) and roll your own approach.

!!! note
If you want to apply different wait strategies to specific errors, you'll need to use [`retryhttp.wait_http_errors`][] as a wait strategy, or write your own context-aware wait strategy.
If you want to apply different wait strategies to specific errors, you'll need to use [`retryhttp.wait_context_aware`][] as a wait strategy, or write your own context-aware wait strategy.

```python
from tenacity import retry, wait_exponential, stop_after_delay
Expand Down
23 changes: 13 additions & 10 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ Several HTTP errors are often transient, and might succeed if retried:
* Network errors
* Timeouts

This project aims to simplify retrying these, by extending [`tenacity`](https://github.com/jd/tenacity) with custom retry and wait strategies, as well as a custom decorator. Defaults are sensible for most use cases, but are fully customizable.
This project aims to simplify retrying these, by extending [`tenacity`](https://tenacity.readthedocs.io/) with custom retry and wait strategies, as well as a custom decorator. Defaults are sensible for most use cases, but are fully customizable.

Supports exceptions raised by both [`requests`](https://github.com/psf/requests) and [`httpx`](https://github.com/encode/httpx).
Supports exceptions raised by both [`requests`](https://docs.python-requests.org/en/latest/index.html) and [`httpx`](https://python-httpx.org/).

## Install

Install most recent stable release from PyPI:
Install from PyPI:

```sh
pip install retryhttp # Supports both HTTPX and requests
# Supports both HTTPX and requests
pip install retryhttp
```

You can also install support for only HTTPX or requests:
Expand All @@ -40,20 +41,22 @@ pip install retryhttp[requests] # Supports only requests
Or, install the latest development snapshot from git:

```sh
pip install git+https://github.com/austind/retryhttp.git@main
pip install git+https://github.com/austind/retryhttp.git@develop
```

## Quickstart

```python
import httpx
from retryhttp import retry_http_errors
from retryhttp import retry

# Retries all HTTP status codes, network errors, and timeouts listed above
# for a maximum of 3 attempts
@retry_http_errors()
def get_example():
# Retries retryable status codes (429, 500, 502, 503, 504), network errors,
# and timeouts, up to 3 times, with appropriate wait strategies for each
# type of error. All of these behaviors are customizable.
@retry
def example():
response = httpx.get("https://example.com/")
response.raise_for_status()
return response.text

```
9 changes: 5 additions & 4 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
site_name: RetryHTTP
site_description: Retry commonly transient HTTP errors.
site_description: Retry potentially transient HTTP errors in Python.
site_url: https://retryhttp.readthedocs.io

theme:
Expand Down Expand Up @@ -27,9 +27,10 @@ repo_url: https://github.com/austind/retryhttp
edit_uri: ""

nav:
- Introduction: "index.md"
- User Guide: "guide.md"
- API Reference: "api.md"
- Introduction: index.md
- User Guide: guide.md
- API Reference: api.md
- Changelog: changelog.md

markdown_extensions:
- admonition
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ packages = ["retryhttp"]
line-length = 88
indent-width = 4
target-version = "py38"

[tool.ruff.lint]
select = ["E", "F", "W", "I"]
ignore = ["E501"]
Loading

0 comments on commit 8adc025

Please sign in to comment.