diff --git a/pkgs/development/python-modules/slowapi/default.nix b/pkgs/development/python-modules/slowapi/default.nix index 4edaf8921aee..3847051bca32 100644 --- a/pkgs/development/python-modules/slowapi/default.nix +++ b/pkgs/development/python-modules/slowapi/default.nix @@ -25,6 +25,11 @@ buildPythonPackage (finalAttrs: { hash = "sha256-YNL/xfs8fmkAGagMhqJX3tXoltjHznZjUrF/a2RWCDs="; }; + patches = [ + # https://github.com/laurentS/slowapi/pull/279 + ./starlette-1.0-compat.patch + ]; + build-system = [ poetry-core ]; dependencies = [ diff --git a/pkgs/development/python-modules/slowapi/starlette-1.0-compat.patch b/pkgs/development/python-modules/slowapi/starlette-1.0-compat.patch new file mode 100644 index 000000000000..b13d38936be9 --- /dev/null +++ b/pkgs/development/python-modules/slowapi/starlette-1.0-compat.patch @@ -0,0 +1,103 @@ +From 8c5f6165b7a66712f3e7e3ceab502069a5c5939a Mon Sep 17 00:00:00 2001 +From: Leonardo Rayner +Date: Wed, 10 Jun 2026 02:21:55 -0400 +Subject: [PATCH 1/3] fix: Replace deprecated @app.route with app.add_route for + Starlette 1.0 compatibility + +--- + tests/test_starlette_extension.py | 25 ++++++++++++++++--------- + 2 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/tests/test_starlette_extension.py b/tests/test_starlette_extension.py +index 0e26baa..c086f75 100644 +--- a/tests/test_starlette_extension.py ++++ b/tests/test_starlette_extension.py +@@ -175,15 +175,17 @@ def test_headers_no_breach(self, build_starlette_app): + headers_enabled=True, key_func=get_remote_address + ) + +- @app.route("/t1") + @limiter.limit("10/minute") + def t1(request: Request): + return PlainTextResponse("test") ++ ++ app.add_route("/t1", t1) + +- @app.route("/t2") + @limiter.limit("2/second; 5 per minute; 10/hour") + def t2(request: Request): + return PlainTextResponse("test") ++ ++ app.add_route("/t2", t2) + + with hiro.Timeline().freeze(): + with TestClient(app) as cli: +@@ -208,10 +210,11 @@ def test_headers_breach(self, build_starlette_app): + headers_enabled=True, key_func=get_remote_address + ) + +- @app.route("/t1") + @limiter.limit("2/second; 10 per minute; 20/hour") + def t(request: Request): + return PlainTextResponse("test") ++ ++ app.add_route("/t1", t) + + with hiro.Timeline().freeze() as timeline: + with TestClient(app) as cli: +@@ -233,10 +236,11 @@ def test_retry_after(self, build_starlette_app): + headers_enabled=True, key_func=get_remote_address + ) + +- @app.route("/t1") + @limiter.limit("1/minute") + def t(request: Request): + return PlainTextResponse("test") ++ ++ app.add_route("/t1", t) + + with hiro.Timeline().freeze() as timeline: + with TestClient(app) as cli: +@@ -254,9 +258,10 @@ def test_exempt_decorator(self, build_starlette_app): + default_limits=["1/minute"], + ) + +- @app.route("/t1") + def t1(request: Request): + return PlainTextResponse("test") ++ ++ app.add_route("/t1", t1) + + with TestClient(app) as cli: + resp = cli.get("/t1", headers={"X_FORWARDED_FOR": "127.0.0.10"}) +@@ -264,11 +269,12 @@ def t1(request: Request): + resp2 = cli.get("/t1", headers={"X_FORWARDED_FOR": "127.0.0.10"}) + assert resp2.status_code == 429 + +- @app.route("/t2") +- @limiter.exempt + def t2(request: Request): + """Exempt a sync route""" + return PlainTextResponse("test") ++ ++ limiter.exempt(t2) ++ app.add_route("/t2", t2) + + with TestClient(app) as cli: + resp = cli.get("/t2", headers={"X_FORWARDED_FOR": "127.0.0.10"}) +@@ -276,11 +282,12 @@ def t2(request: Request): + resp2 = cli.get("/t2", headers={"X_FORWARDED_FOR": "127.0.0.10"}) + assert resp2.status_code == 200 + +- @app.route("/t3") +- @limiter.exempt + async def t3(request: Request): + """Exempt an async route""" + return PlainTextResponse("test") ++ ++ limiter.exempt(t3) ++ app.add_route("/t3", t3) + + with TestClient(app) as cli: + resp = cli.get("/t3", headers={"X_FORWARDED_FOR": "127.0.0.10"}) +