Skip to content

Commit

Permalink
Merge branch 'pgjones:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
iasukas authored Feb 4, 2023
2 parents aaed02c + 88aa047 commit a59fa9d
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 36 deletions.
28 changes: 6 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ jobs:
fail-fast: false
matrix:
include:
- {name: '3.11-dev', python: '3.11-dev', tox: py311}
- {name: '3.11', python: '3.11', tox: py311}
- {name: '3.10', python: '3.10', tox: py310}
- {name: '3.9', python: '3.9', tox: py39}
- {name: '3.8', python: '3.8', tox: py38}
- {name: '3.7', python: '3.7', tox: py37}
- {name: 'format', python: '3.10', tox: format}
- {name: 'mypy', python: '3.10', tox: mypy}
- {name: 'pep8', python: '3.10', tox: pep8}
- {name: 'package', python: '3.10', tox: package}
- {name: 'format', python: '3.11', tox: format}
- {name: 'mypy', python: '3.11', tox: mypy}
- {name: 'pep8', python: '3.11', tox: pep8}
- {name: 'package', python: '3.11', tox: package}

steps:
- uses: actions/checkout@v3
Expand All @@ -31,20 +31,14 @@ jobs:
with:
python-version: ${{ matrix.python }}

- name: update pip
run: |
pip install -U wheel
pip install -U setuptools
python -m pip install -U pip
- run: pip install tox

- run: tox -e ${{ matrix.tox }}

redis-tox:
runs-on: ubuntu-latest

container: python:3.10
container: python:3.11

services:
redis:
Expand All @@ -58,16 +52,6 @@ jobs:
steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v3
with:
python-version: '3.10'

- name: update pip
run: |
pip install -U wheel
pip install -U setuptools
python -m pip install -U pip
- run: pip install tox

- run: tox -e redis
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
0.8.0 2023-01-21
----------------

* Use redis rather than aioredis as the two have merged.
* Bugfix ensure the Content-Type header is present.
* Improve the typing for better type checking.
* Officially support Python 3.10, and Python 3.11.

0.7.0 2022-04-04
----------------

Expand Down
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "quart-rate-limiter"
version = "0.7.0"
version = "0.8.0"
description = "A Quart extension to provide rate limiting support"
authors = ["pgjones <philip.graham.jones@googlemail.com>"]
classifiers = [
Expand All @@ -15,6 +15,7 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development :: Libraries :: Python Modules",
]
Expand Down Expand Up @@ -55,6 +56,10 @@ warn_return_any = false
warn_unused_configs = true
warn_unused_ignores = true

[[tool.mypy.overrides]]
module =["redis.*"]
ignore_missing_imports = true

[tool.poetry.dependencies]
python = ">=3.7"
quart = ">=0.15"
Expand Down
23 changes: 16 additions & 7 deletions src/quart_rate_limiter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Any, Awaitable, Callable, Dict, List, Optional
from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, TypeVar, Union

from quart import Blueprint, current_app, Quart, request, Response
from quart.typing import RouteCallable, WebsocketCallable
from werkzeug.exceptions import TooManyRequests

from .store import MemoryStore, RateLimiterStoreABC
Expand All @@ -25,8 +26,10 @@ def __init__(self, retry_after: int) -> None:
super().__init__()
self.retry_after = retry_after

def get_headers(self, *_: Any) -> dict: # type: ignore
return {"Retry-After": str(self.retry_after)}
def get_headers(self, *args: Any) -> List[Tuple[str, str]]:
headers = super().get_headers(*args)
headers.append(("Retry-After", str(self.retry_after)))
return headers


@dataclass
Expand All @@ -44,13 +47,16 @@ def key(self) -> str:
return f"{self.count}-{self.period.total_seconds()}"


T = TypeVar("T", bound=Union[RouteCallable, WebsocketCallable])


def rate_limit(
limit: Optional[int] = None,
period: Optional[timedelta] = None,
key_function: Optional[KeyCallable] = None,
*,
limits: Optional[List[RateLimit]] = None,
) -> Callable:
) -> Callable[[T], T]:
"""A decorator to add a rate limit marker to the route.
This should be used to wrap a route handler (or view function) to
Expand Down Expand Up @@ -88,7 +94,7 @@ async def example_key_function() -> str:
if limits is None:
raise ValueError("No Rate Limit(s) set")

def decorator(func: Callable) -> Callable:
def decorator(func: T) -> T:
rate_limits = getattr(func, QUART_RATE_LIMITER_LIMITS_ATTRIBUTE, [])
rate_limits.extend(limits)
setattr(func, QUART_RATE_LIMITER_LIMITS_ATTRIBUTE, rate_limits)
Expand Down Expand Up @@ -116,14 +122,17 @@ async def index():
return func


U = TypeVar("U", bound=Blueprint)


def limit_blueprint(
blueprint: Blueprint,
blueprint: U,
limit: Optional[int] = None,
period: Optional[timedelta] = None,
key_function: Optional[KeyCallable] = None,
*,
limits: Optional[List[RateLimit]] = None,
) -> Blueprint:
) -> U:
"""A function to add a rate limit marker to the blueprint.
This should be used to apply a rate limit to all routes registered
Expand Down
1 change: 1 addition & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ async def test_rate_limit(app: Quart, fixed_datetime: datetime) -> None:
response = await test_client.get("/rate_limit/")
assert response.status_code == 429
assert response.headers["Retry-After"] == "2"
assert response.headers["Content-Type"] == "text/html; charset=utf-8"


async def test_rate_limit_unique_keys(app: Quart, fixed_datetime: datetime) -> None:
Expand Down
12 changes: 6 additions & 6 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = format,mypy,py37,py38,py39,py310,pep8,package
envlist = format,mypy,py37,py38,py39,py310,py311,pep8,package
isolated_build = True

[testenv]
Expand All @@ -12,7 +12,7 @@ deps =
commands = pytest --cov=quart_rate_limiter {posargs}

[testenv:redis]
basepython = python3.10
basepython = python3.11
deps =
redis
pytest
Expand All @@ -22,7 +22,7 @@ deps =
commands = pytest --cov=quart_rate_limiter --redis-host="redis" {posargs}

[testenv:format]
basepython = python3.10
basepython = python3.11
deps =
black
isort
Expand All @@ -31,15 +31,15 @@ commands =
isort --check --diff src/quart_rate_limiter/ tests

[testenv:pep8]
basepython = python3.10
basepython = python3.11
deps =
flake8
pep8-naming
flake8-print
commands = flake8 src/quart_rate_limiter/ tests/

[testenv:mypy]
basepython = python3.10
basepython = python3.11
deps =
redis
mypy
Expand All @@ -48,7 +48,7 @@ commands =
mypy src/quart_rate_limiter/ tests/

[testenv:package]
basepython = python3.10
basepython = python3.11
deps =
poetry
twine
Expand Down

0 comments on commit a59fa9d

Please sign in to comment.