diff --git a/0001-Stop-using-deprecated-app-shortcut-in-httpx.AsyncCli.patch b/0001-Stop-using-deprecated-app-shortcut-in-httpx.AsyncCli.patch deleted file mode 100644 index 493e027..0000000 --- a/0001-Stop-using-deprecated-app-shortcut-in-httpx.AsyncCli.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 62e52f30f75b42290e32adb85dd1319b9c5a0072 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= -Date: Mon, 25 Mar 2024 21:48:07 +0100 -Subject: [PATCH] Stop using deprecated app shortcut in httpx.AsyncClient - -This keyword parameter has been deprecated with httpx 0.27 ---- - tests/middleware/test_message_logger.py | 8 ++++---- - tests/middleware/test_proxy_headers.py | 6 +++--- - tests/middleware/test_wsgi.py | 23 ++++++++--------------- - 3 files changed, 15 insertions(+), 22 deletions(-) - -diff --git a/tests/middleware/test_message_logger.py b/tests/middleware/test_message_logger.py -index 3f5c3af..d066e99 100644 ---- a/tests/middleware/test_message_logger.py -+++ b/tests/middleware/test_message_logger.py -@@ -17,8 +17,8 @@ async def test_message_logger(caplog): - caplog.set_level(TRACE_LOG_LEVEL, logger="uvicorn.asgi") - caplog.set_level(TRACE_LOG_LEVEL) - -- app = MessageLoggerMiddleware(app) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -+ transport = httpx.ASGITransport(MessageLoggerMiddleware(app)) -+ async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: - response = await client.get("/") - assert response.status_code == 200 - messages = [record.msg % record.args for record in caplog.records] -@@ -37,8 +37,8 @@ async def test_message_logger_exc(caplog): - with caplog_for_logger(caplog, "uvicorn.asgi"): - caplog.set_level(TRACE_LOG_LEVEL, logger="uvicorn.asgi") - caplog.set_level(TRACE_LOG_LEVEL) -- app = MessageLoggerMiddleware(app) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -+ transport = httpx.ASGITransport(MessageLoggerMiddleware(app)) -+ async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: - with pytest.raises(RuntimeError): - await client.get("/") - messages = [record.msg % record.args for record in caplog.records] -diff --git a/tests/middleware/test_proxy_headers.py b/tests/middleware/test_proxy_headers.py -index 6d7fc8c..e50defa 100644 ---- a/tests/middleware/test_proxy_headers.py -+++ b/tests/middleware/test_proxy_headers.py -@@ -49,7 +49,7 @@ async def app( - ) - async def test_proxy_headers_trusted_hosts(trusted_hosts: list[str] | str, response_text: str) -> None: - app_with_middleware = ProxyHeadersMiddleware(app, trusted_hosts=trusted_hosts) -- async with httpx.AsyncClient(app=app_with_middleware, base_url="http://testserver") as client: -+ async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app_with_middleware), base_url="http://testserver") as client: - headers = {"X-Forwarded-Proto": "https", "X-Forwarded-For": "1.2.3.4"} - response = await client.get("/", headers=headers) - -@@ -79,7 +79,7 @@ async def test_proxy_headers_trusted_hosts(trusted_hosts: list[str] | str, respo - ) - async def test_proxy_headers_multiple_proxies(trusted_hosts: list[str] | str, response_text: str) -> None: - app_with_middleware = ProxyHeadersMiddleware(app, trusted_hosts=trusted_hosts) -- async with httpx.AsyncClient(app=app_with_middleware, base_url="http://testserver") as client: -+ async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app_with_middleware), base_url="http://testserver") as client: - headers = { - "X-Forwarded-Proto": "https", - "X-Forwarded-For": "1.2.3.4, 10.0.2.1, 192.168.0.2", -@@ -93,7 +93,7 @@ async def test_proxy_headers_multiple_proxies(trusted_hosts: list[str] | str, re - @pytest.mark.anyio - async def test_proxy_headers_invalid_x_forwarded_for() -> None: - app_with_middleware = ProxyHeadersMiddleware(app, trusted_hosts="*") -- async with httpx.AsyncClient(app=app_with_middleware, base_url="http://testserver") as client: -+ async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app_with_middleware), base_url="http://testserver") as client: - headers = httpx.Headers( - { - "X-Forwarded-Proto": "https", -diff --git a/tests/middleware/test_wsgi.py b/tests/middleware/test_wsgi.py -index adc8e24..478dd84 100644 ---- a/tests/middleware/test_wsgi.py -+++ b/tests/middleware/test_wsgi.py -@@ -59,8 +59,8 @@ def wsgi_middleware(request: pytest.FixtureRequest) -> Callable: - - @pytest.mark.anyio - async def test_wsgi_get(wsgi_middleware: Callable) -> None: -- app = wsgi_middleware(hello_world) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -+ transport = httpx.ASGITransport(wsgi_middleware(hello_world)) -+ async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: - response = await client.get("/") - assert response.status_code == 200 - assert response.text == "Hello World!\n" -@@ -68,8 +68,8 @@ async def test_wsgi_get(wsgi_middleware: Callable) -> None: - - @pytest.mark.anyio - async def test_wsgi_post(wsgi_middleware: Callable) -> None: -- app = wsgi_middleware(echo_body) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -+ transport = httpx.ASGITransport(wsgi_middleware(echo_body)) -+ async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: - response = await client.post("/", json={"example": 123}) - assert response.status_code == 200 - assert response.text == '{"example": 123}' -@@ -81,8 +81,8 @@ async def test_wsgi_put_more_body(wsgi_middleware: Callable) -> None: - for _ in range(1024): - yield b"123456789abcdef\n" * 64 - -- app = wsgi_middleware(echo_body) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -+ transport = httpx.ASGITransport(wsgi_middleware(echo_body)) -+ async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: - response = await client.put("/", content=generate_body()) - assert response.status_code == 200 - assert response.text == "123456789abcdef\n" * 64 * 1024 -@@ -92,21 +92,14 @@ async def test_wsgi_put_more_body(wsgi_middleware: Callable) -> None: - async def test_wsgi_exception(wsgi_middleware: Callable) -> None: - # Note that we're testing the WSGI app directly here. - # The HTTP protocol implementations would catch this error and return 500. -- app = wsgi_middleware(raise_exception) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -+ transport = httpx.ASGITransport(wsgi_middleware(raise_exception)) -+ async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: - with pytest.raises(RuntimeError): - await client.get("/") - - - @pytest.mark.anyio - async def test_wsgi_exc_info(wsgi_middleware: Callable) -> None: -- # Note that we're testing the WSGI app directly here. -- # The HTTP protocol implementations would catch this error and return 500. -- app = wsgi_middleware(return_exc_info) -- async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: -- with pytest.raises(RuntimeError): -- response = await client.get("/") -- - app = wsgi_middleware(return_exc_info) - transport = httpx.ASGITransport( - app=app, --- -2.44.0 - diff --git a/fix-websocket-tests.patch b/fix-websocket-tests.patch deleted file mode 100644 index 84a8daa..0000000 --- a/fix-websocket-tests.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: uvicorn-0.22.0/tests/protocols/test_websocket.py -=================================================================== ---- uvicorn-0.22.0.orig/tests/protocols/test_websocket.py -+++ uvicorn-0.22.0/tests/protocols/test_websocket.py -@@ -584,7 +584,7 @@ async def test_asgi_return_value( - async with run_server(config): - with pytest.raises(websockets.exceptions.ConnectionClosed) as exc_info: - await connect(f"ws://127.0.0.1:{unused_tcp_port}") -- assert exc_info.value.code == 1006 -+ assert exc_info.value.code in {1000, 1006} - - - @pytest.mark.anyio diff --git a/python-uvicorn.changes b/python-uvicorn.changes index a46db61..f80d18c 100644 --- a/python-uvicorn.changes +++ b/python-uvicorn.changes @@ -1,3 +1,59 @@ +------------------------------------------------------------------- +Thu May 1 06:28:46 UTC 2025 - Steve Kowalik + +- Update to 0.34.2: + * Added + + Add content-length to 500 response in wsproto implementation + * Fixed + + Flush stdout buffer on Windows to trigger reload + + Drop ASGI spec version to 2.3 on HTTP scope + + Enable httptools lenient data on httptools >= 0.6.3 + * Deprecated + + Deprecate ServerState in the main module + * Removed + + Drop support for Python 3.8 + + Remove WatchGod support for --reload +- Add patch support-websockets-14+.patch: + * Ignore multiple classes of DeprecationWarnings. + +------------------------------------------------------------------- +Wed Oct 30 10:37:07 UTC 2024 - Dirk Müller + +- update to 0.32.0: + * Officially support Python 3.13 + * Warn when `max_request_limit` is exceeded + * Support WebSockets 0.13.1 + * Restore support for `[*]` in trusted hosts + * Add `PathLike[str]` type hint for `ssl_keyfile` + * Improve `ProxyHeadersMiddleware` (#2468) and (#2231): + * Fix the host for requests from clients running on the proxy + server itself. + * Fallback to host that was already set for empty x-forwarded- + for headers. + * Also allow to specify IP Networks as trusted hosts. This + greatly simplifies deployments + * on docker swarm/kubernetes, where the reverse proxy might + have a dynamic IP. + * This includes support for IPv6 Address/Networks. + * Don't warn when upgrade is not WebSocket and depedencies are + installed + * Don't close connection before receiving body on H11 + * Close connection when `h11` sets client state to `MUST_CLOSE` + * Suppress `KeyboardInterrupt` from CLI and programmatic usage + * `ClientDisconnect` inherits from `OSError` instead of + `IOError` + * Add `reason` support to `websocket.disconnect` event + * Iterate subprocesses in-place on the process manager + * Allow horizontal tabs ` ` in response header values + * New multiprocess manager + * Allow `ConfigParser` or a `io.IO[Any]` on `log_config` + * Suppress side-effects of signal propagation + * Send `content-length` header on 5xx + * Deprecate the `uvicorn.workers` module +- drop fix-websocket-tests.patch, + 0001-Stop-using-deprecated-app-shortcut-in-httpx.AsyncCli.patch: + upstream + ------------------------------------------------------------------- Mon Mar 25 20:19:46 UTC 2024 - Dan Čermák diff --git a/python-uvicorn.spec b/python-uvicorn.spec index b19dc62..68c34e8 100644 --- a/python-uvicorn.spec +++ b/python-uvicorn.spec @@ -1,7 +1,7 @@ # # spec file for package python-uvicorn # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,27 +18,23 @@ %{?sle15_python_module_pythons} Name: python-uvicorn -Version: 0.29.0 +Version: 0.34.2 Release: 0 Summary: An Asynchronous Server Gateway Interface server License: BSD-3-Clause URL: https://github.com/encode/uvicorn Source: https://github.com/encode/uvicorn/archive/%{version}.tar.gz#/uvicorn-%{version}.tar.gz -# PATCH-FIX-UPSTREAM fix-websocket-tests.patch -- gh#encode/uvicorn#1929 -Patch0: fix-websocket-tests.patch -# https://github.com/encode/uvicorn/pull/2288 -Patch1: 0001-Stop-using-deprecated-app-shortcut-in-httpx.AsyncCli.patch +# PATCH-FIX-OPENSUSE Ignore the large amount of DeprecationWarnings that websockets 14 gave us +Patch0: support-websockets-14+.patch BuildRequires: %{python_module base >= 3.8} BuildRequires: %{python_module hatchling} BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} -BuildRequires: %{python_module typing-extensions >= 4 if %python-base < 3.11} BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-click >= 7.0 Requires: python-h11 >= 0.8.0 -Requires: (python-typing-extensions >= 4 if python-base < 3.11) Recommends: python-PyYAML >= 5.1 Recommends: python-httptools >= 0.4.0 Recommends: python-websockets >= 8.0 @@ -53,6 +49,7 @@ BuildRequires: %{python_module httptools >= 0.4.0} BuildRequires: %{python_module httpx >= 0.27} BuildRequires: %{python_module pytest-asyncio} BuildRequires: %{python_module pytest-mock} +BuildRequires: %{python_module pytest-xdist} BuildRequires: %{python_module pytest} BuildRequires: %{python_module python-dotenv} BuildRequires: %{python_module requests} @@ -97,13 +94,14 @@ ignore="--ignore tests/middleware/test_wsgi.py" %if "%{_arch}" == "s390x" ignore+=" --ignore tests/protocols/test_websocket.py" %endif -%pytest $ignore +# no longer raises an exception with Websockets 14+ +%pytest $ignore -k 'not test_send_binary_data_to_server_bigger_than_default_on_websockets' %files %{python_files} %doc README.md %license LICENSE.md %python_alternative %{_bindir}/uvicorn %{python_sitelib}/uvicorn -%{python_sitelib}/uvicorn-%{version}*-info +%{python_sitelib}/uvicorn-%{version}.dist-info %changelog diff --git a/support-websockets-14+.patch b/support-websockets-14+.patch new file mode 100644 index 0000000..0581c0a --- /dev/null +++ b/support-websockets-14+.patch @@ -0,0 +1,16 @@ +Index: uvicorn-0.34.2/pyproject.toml +=================================================================== +--- uvicorn-0.34.2.orig/pyproject.toml ++++ uvicorn-0.34.2/pyproject.toml +@@ -92,6 +92,11 @@ filterwarnings = [ + "ignore:Uvicorn's native WSGI implementation is deprecated.*:DeprecationWarning", + "ignore: 'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning", + "ignore: remove second argument of ws_handler:DeprecationWarning:websockets", ++ # Websockets 14+ ++ "ignore: websockets.server.WebSocketServerProtocol is deprecated:DeprecationWarning", ++ "ignore: websockets.legacy is deprecated.*:DeprecationWarning", ++ "ignore: websockets.client.connect is deprecated:DeprecationWarning", ++ "ignore: websockets.exceptions.InvalidStatusCode is deprecated:DeprecationWarning", + ] + + [tool.coverage.run] diff --git a/uvicorn-0.29.0.tar.gz b/uvicorn-0.29.0.tar.gz deleted file mode 100644 index 8a2bd93..0000000 --- a/uvicorn-0.29.0.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b12a6866e7bc70fb89bd54c2d1a6b0382183657e369deed3a2d0535c280e46c9 -size 719202 diff --git a/uvicorn-0.34.2.tar.gz b/uvicorn-0.34.2.tar.gz new file mode 100644 index 0000000..7bfd42f --- /dev/null +++ b/uvicorn-0.34.2.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea0a4b037cbb5135344b52f21eb286630b8d5d4be7661981860f3dd11e6fdaa0 +size 709898