diff --git a/falcon-3.1.1.tar.gz b/falcon-3.1.1.tar.gz deleted file mode 100644 index e14b7ea..0000000 --- a/falcon-3.1.1.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eebf5717c5cea69cb75d23f560816236bcdcf7339e887f7465ea166b5d6f7a43 -size 1320543 diff --git a/falcon-3.1.3.tar.gz b/falcon-3.1.3.tar.gz new file mode 100644 index 0000000..8d5592b --- /dev/null +++ b/falcon-3.1.3.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23335dbccd44f29e85ec55f2f35d5a0bc12bd7a509f641ab81f5c64b65626263 +size 577770 diff --git a/python-falcon-sphinx-pygments-style.patch b/python-falcon-sphinx-pygments-style.patch index 4144e18..f074978 100644 --- a/python-falcon-sphinx-pygments-style.patch +++ b/python-falcon-sphinx-pygments-style.patch @@ -1,8 +1,8 @@ -Index: falcon-3.1.1/docs/conf.py +Index: falcon-3.1.3/docs/conf.py =================================================================== ---- falcon-3.1.1.orig/docs/conf.py -+++ falcon-3.1.1/docs/conf.py -@@ -134,7 +134,7 @@ exclude_patterns = ['_build', '_newsfrag +--- falcon-3.1.3.orig/docs/conf.py ++++ falcon-3.1.3/docs/conf.py +@@ -132,7 +132,7 @@ exclude_patterns = ['_build', '_newsfrag # show_authors = False # The name of the Pygments (syntax highlighting) style to use. diff --git a/python-falcon.changes b/python-falcon.changes index e09403b..b2eac75 100644 --- a/python-falcon.changes +++ b/python-falcon.changes @@ -1,3 +1,73 @@ +------------------------------------------------------------------- +Tue Apr 2 01:45:24 UTC 2024 - Steve Kowalik + +- Remove skipping asgi for Python 3.9. +- Add patch support-new-uvicorn.patch: + * Support new uvicorn, which now propagates its exit code. + +------------------------------------------------------------------- +Tue Mar 19 18:32:56 UTC 2024 - Daniel Garcia + +- Ignore "tests/asgi" for python 3.9, some ws tests stalls with this + python version + +------------------------------------------------------------------- +Tue Feb 6 17:06:48 UTC 2024 - Ben Greiner + +- Update source file +- Replace deprecated %patch0 +- Move to PEP517 +- Remove old TW python36 flavor directives +- Install examples into doc package and properly fdup + +------------------------------------------------------------------- +Sun Feb 4 14:45:28 UTC 2024 - Ben Greiner + +- Update to 3.1.3 + * This is a minor bugfix release that only pins the + pytest-asyncio test dependency in order to prevent an + incompatible version from interfering with the build workflow. + * This release is otherwise identical to Falcon 3.1.2. +- Update to 3.1.2 + ## Summary + * This is a minor point release fixing a couple of high impact + bugs, as well as publishing binary wheels for the recently + released CPython 3.12. + ## Changes to Supported Platforms + * Falcon is now supported (including binary wheels) on CPython + 3.12. A couple of remaining stdlib deprecations from 3.11 and + 3.12 will be addressed in Falcon 4.0. + * As with the previous release, Python 3.5 & 3.6 remain + deprecated and will no longer be supported in Falcon 4.0. + * EOL Python 3.7 will no longer be actively supported in 4.0, but + the framework should still continue to install from source. We + may remove the support for 3.7 altogether later in the 4.x + series if we are faced with incompatible ecosystem changes in + typing, Cython, etc. + ## Fixed + * Some essential files were unintentionally omitted from the + source distribution archive, rendering it unsuitable to run the + test suite off. This has been fixed, and the sdist tarball + should now be usable as a base for packaging Falcon in OS + distributions. (#2051) + * WebSocket implementation has been fixed to properly handle + HTTPError and HTTPStatus exceptions raised by custom error + handlers. The WebSocket connection is now correctly closed with + an appropriate code instead of bubbling up an unhandled error + to the application server. (#2146) + * Falcon’s TestClient mimics the behavior of real WSGI servers + (and the WSGI spec) by presenting the PATH_INFO CGI variable + already in the percent-decoded form. However, the client also + used to indiscriminately set the non-standard RAW_URI CGI + variable to /, which made writing tests for apps decoding raw + URL path cumbersome. This has been fixed, and the raw path of a + simulated request is now preserved in RAW_URI. (#2157) + +------------------------------------------------------------------- +Thu Jan 18 09:33:52 UTC 2024 - Markéta Machová + +- remove unneeded build dependency python-ujson + ------------------------------------------------------------------- Tue Jan 2 23:52:59 UTC 2024 - Jiri Srain diff --git a/python-falcon.spec b/python-falcon.spec index e16aecd..e0ea976 100644 --- a/python-falcon.spec +++ b/python-falcon.spec @@ -18,24 +18,25 @@ %{?sle15_python_module_pythons} Name: python-falcon -Version: 3.1.1 +Version: 3.1.3 Release: 0 Summary: A web framework for building APIs and app backends License: Apache-2.0 -Group: Development/Languages/Python URL: http://falconframework.org -Source: https://github.com/falconry/falcon/archive/%{version}.tar.gz#./falcon-%{version}.tar.gz -# The file on pypi misses docs/ext, should be fixed in next version -# Source: https://files.pythonhosted.org/packages/source/f/falcon/falcon-%%{version}.tar.gz +Source: https://files.pythonhosted.org/packages/source/f/falcon/falcon-%{version}.tar.gz # github pygments style is not available Patch0: python-falcon-sphinx-pygments-style.patch +# PATCH-FIX-UPSTREAM Based on gh#falconry/falcon#2216 +Patch1: support-new-uvicorn.patch BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module Sphinx} BuildRequires: %{python_module ddt} BuildRequires: %{python_module httpx} +BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} BuildRequires: %{python_module sphinx-tabs} BuildRequires: %{python_module websockets} +BuildRequires: %{python_module wheel} # TODO: Cython support #BuildRequires: %%{python_module Cython} # SECTION test requirements @@ -46,7 +47,6 @@ BuildRequires: %{python_module pytest-asyncio} BuildRequires: %{python_module pytest} BuildRequires: %{python_module requests} BuildRequires: %{python_module testtools} -BuildRequires: %{python_module ujson} %if 0%{?suse_version} >= 1550 BuildRequires: %{python_module httpx if (%python-base without python36-base)} BuildRequires: %{python_module uvicorn if (%python-base without python36-base)} @@ -57,14 +57,13 @@ BuildRequires: fdupes BuildRequires: python-rpm-macros #Requires: python-Cython Requires(post): update-alternatives -Requires(postun):update-alternatives +Requires(postun): update-alternatives Suggests: %{name}-doc BuildArch: noarch %python_subpackages %package -n %{name}-doc Summary: Documentation files for %{name} -Group: Documentation/HTML Provides: %{python_module falcon-doc = %{version}} %description @@ -76,19 +75,16 @@ as little as possible while remaining effective. HTML documentation including API documentation and changelog for %{name}. %prep -%setup -q -n falcon-%{version} -%patch0 -p1 +%autosetup -p1 -n falcon-%{version} # remove unwanted shebang sed -i '1s/^#!.*//' falcon/bench/bench.py falcon/cmd/inspect_app.py falcon/bench/dj/manage.py chmod a-x falcon/bench/dj/manage.py # we don't want to require rapidjson just for testing rm tests/test_media_handlers.py -# Hidden files are evil -rm examples/asgilook/.coveragerc %build export CFLAGS="%{optflags} -fno-strict-aliasing" -%python_build +%pyproject_wheel export PYTHONPATH="$(pwd)" pushd docs make html @@ -96,22 +92,18 @@ rm _build/html/.buildinfo popd %install -%python_install +%pyproject_install %python_clone -a %{buildroot}%{_bindir}/falcon-bench %python_clone -a %{buildroot}%{_bindir}/falcon-inspect-app %python_clone -a %{buildroot}%{_bindir}/falcon-print-routes -%{python_expand rm -rf %{buildroot}%{$python_sitelib}/examples - %fdupes %{buildroot}%{$python_sitelib} -} +%python_expand %fdupes %{buildroot}%{$python_sitelib} +mkdir -p %{buildroot}%{_defaultdocdir}/%{name}-doc +cp -ar docs/_build/html examples %{buildroot}%{_defaultdocdir}/%{name}-doc/ +%fdupes %{buildroot}%{_defaultdocdir}/%{name}-doc/ %check export LANG=en_US.UTF8 -# there are no websockets and httpx for python 3.6 -python36_donttest=("--ignore" "tests/asgi") -if [ %{python3_version_nodots} -eq 36 ]; then - python3_donttest=("--ignore" "tests/asgi") -fi -%pytest "${$python_donttest[@]}" tests +%pytest tests %post %{python_install_alternative falcon-bench falcon-inspect-app falcon-print-routes} @@ -120,15 +112,15 @@ fi %python_uninstall_alternative falcon-bench %files %{python_files} -%doc README.rst CHANGES.rst examples/ +%doc README.rst %license LICENSE %python_alternative %{_bindir}/falcon-bench %python_alternative %{_bindir}/falcon-inspect-app %python_alternative %{_bindir}/falcon-print-routes %{python_sitelib}/falcon -%{python_sitelib}/falcon-%{version}*-info +%{python_sitelib}/falcon-%{version}.dist-info %files -n %{name}-doc -%doc docs/_build/html +%doc %{_defaultdocdir}/%{name}-doc %changelog diff --git a/support-new-uvicorn.patch b/support-new-uvicorn.patch new file mode 100644 index 0000000..517d0ea --- /dev/null +++ b/support-new-uvicorn.patch @@ -0,0 +1,192 @@ +From 13da50949751de6683b57221c2ab5f1fdce8eb50 Mon Sep 17 00:00:00 2001 +From: Vytautas Liuolia +Date: Wed, 13 Mar 2024 16:31:00 +0100 +Subject: [PATCH 1/7] chore(asyncio): replace `get_event_loop()` -> + `get_running_loop()` where applicable + +--- + tests/asgi/test_scope.py | 6 +++--- + tests/dump_asgi.py | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +Index: falcon-3.1.3/tests/asgi/test_scope.py +=================================================================== +--- falcon-3.1.3.orig/tests/asgi/test_scope.py ++++ falcon-3.1.3/tests/asgi/test_scope.py +@@ -70,7 +70,7 @@ def test_supported_asgi_version(version, + resp_event_collector = testing.ASGIResponseEventCollector() + + async def task(): +- coro = asyncio.get_event_loop().create_task( ++ coro = asyncio.get_running_loop().create_task( + app(scope, req_event_emitter, resp_event_collector) + ) + +@@ -142,7 +142,7 @@ def test_lifespan_scope_default_version( + scope = {'type': 'lifespan'} + + async def t(): +- t = asyncio.get_event_loop().create_task( ++ t = asyncio.get_running_loop().create_task( + app(scope, req_event_emitter, resp_event_collector) + ) + +@@ -196,7 +196,7 @@ def test_lifespan_scope_version(spec_ver + return + + async def t(): +- t = asyncio.get_event_loop().create_task( ++ t = asyncio.get_running_loop().create_task( + app(scope, req_event_emitter, resp_event_collector) + ) + +Index: falcon-3.1.3/tests/dump_asgi.py +=================================================================== +--- falcon-3.1.3.orig/tests/dump_asgi.py ++++ falcon-3.1.3/tests/dump_asgi.py +@@ -23,5 +23,5 @@ async def app(scope, receive, send): + } + ) + +- loop = asyncio.get_event_loop() ++ loop = asyncio.get_running_loop() + loop.create_task(_say_hi()) +Index: falcon-3.1.3/falcon/util/sync.py +=================================================================== +--- falcon-3.1.3.orig/falcon/util/sync.py ++++ falcon-3.1.3/falcon/util/sync.py +@@ -4,7 +4,9 @@ from functools import partial + from functools import wraps + import inspect + import os ++from typing import Awaitable + from typing import Callable ++from typing import TypeVar + + + __all__ = [ +@@ -18,6 +20,42 @@ __all__ = [ + ] + + ++Result = TypeVar('Result') ++ ++ ++class _DummyRunner: ++ def run(self, coro: Awaitable[Result]) -> Result: # pragma: nocover ++ # NOTE(vytas): Work around get_event_loop deprecation in 3.10 by going ++ # via get_event_loop_policy(). This should be equivalent for ++ # async_to_sync's use case as it is currently impossible to invoke ++ # run_until_complete() from a running loop anyway. ++ return self.get_loop().run_until_complete(coro) ++ ++ def get_loop(self) -> asyncio.AbstractEventLoop: # pragma: nocover ++ return asyncio.get_event_loop_policy().get_event_loop() ++ ++ def close(self) -> None: # pragma: nocover ++ pass ++ ++ ++class _ActiveRunner: ++ def __init__(self, runner_cls: type): ++ self._runner_cls = runner_cls ++ self._runner = runner_cls() ++ ++ # TODO(vytas): This typing is wrong on py311+, but mypy accepts it. ++ # It doesn't, OTOH, accept any of my ostensibly valid attempts to ++ # describe it. ++ def __call__(self) -> _DummyRunner: ++ # NOTE(vytas): Sometimes our runner's loop can get picked and consumed ++ # by other utilities and test methods. If that happens, recreate the runner. ++ if self._runner.get_loop().is_closed(): ++ # NOTE(vytas): This condition is never hit on _DummyRunner. ++ self._runner = self._runner_cls() # pragma: nocover ++ return self._runner ++ ++ ++_active_runner = _ActiveRunner(getattr(asyncio, 'Runner', _DummyRunner)) + _one_thread_to_rule_them_all = ThreadPoolExecutor(max_workers=1) + + +@@ -207,8 +245,13 @@ def async_to_sync(coroutine, *args, **kw + one will be created. + + Warning: +- This method is very inefficient and is intended primarily for testing +- and prototyping. ++ Executing async code in this manner is inefficient since it involves ++ synchronization via threading primitives, and is intended primarily for ++ testing, prototyping or compatibility purposes. ++ ++ Note: ++ On Python 3.11+, this function leverages a module-wide ++ ``asyncio.Runner``. + + Args: + coroutine: A coroutine function to invoke. +@@ -217,17 +260,7 @@ def async_to_sync(coroutine, *args, **kw + Keyword Args: + **kwargs: Additional args are passed through to the coroutine function. + """ +- +- # TODO(vytas): The canonical way of doing this for simple use cases is +- # asyncio.run(), but that would be a breaking change wrt the above +- # documented behaviour; breaking enough to break some of our own tests. +- +- # NOTE(vytas): Work around get_event_loop deprecation in 3.10 by going via +- # get_event_loop_policy(). This should be equivalent for async_to_sync's +- # use case as it is currently impossible to invoke run_until_complete() +- # from a running loop anyway. +- loop = asyncio.get_event_loop_policy().get_event_loop() +- return loop.run_until_complete(coroutine(*args, **kwargs)) ++ return _active_runner().run(coroutine(*args, **kwargs)) + + + def runs_sync(coroutine): +Index: falcon-3.1.3/pyproject.toml +=================================================================== +--- falcon-3.1.3.orig/pyproject.toml ++++ falcon-3.1.3/pyproject.toml +@@ -63,7 +63,6 @@ filterwarnings = [ + "ignore:.cgi. is deprecated and slated for removal:DeprecationWarning", + "ignore:path is deprecated\\. Use files\\(\\) instead:DeprecationWarning", + "ignore:This process \\(.+\\) is multi-threaded", +- "ignore:There is no current event loop", + ] + testpaths = [ + "tests" +Index: falcon-3.1.3/tests/asgi/test_asgi_servers.py +=================================================================== +--- falcon-3.1.3.orig/tests/asgi/test_asgi_servers.py ++++ falcon-3.1.3/tests/asgi/test_asgi_servers.py +@@ -4,6 +4,7 @@ import hashlib + import os + import platform + import random ++import signal + import subprocess + import sys + import time +@@ -27,7 +28,9 @@ _WIN32 = sys.platform.startswith('win') + _SERVER_HOST = '127.0.0.1' + _SIZE_1_KB = 1024 + _SIZE_1_MB = _SIZE_1_KB**2 +- ++# NOTE(vytas): Windows specific: {Application Exit by CTRL+C}. ++# The application terminated as a result of a CTRL+C. ++_STATUS_CONTROL_C_EXIT = 0xC000013A + + _REQUEST_TIMEOUT = 10 + +@@ -610,7 +613,10 @@ def server_base_url(request): + + yield base_url + +- assert server.returncode == 0 ++ # NOTE(vytas): Starting with 0.29.0, Uvicorn will propagate signal ++ # values into the return code (which is a good practice in Unix); ++ # see also https://github.com/encode/uvicorn/pull/1600 ++ assert server.returncode in (0, -signal.SIGTERM, _STATUS_CONTROL_C_EXIT) + + break +