Compare commits

1 Commits
main ... 1.1

6 changed files with 46 additions and 404 deletions

BIN
falcon-3.1.1.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

BIN
falcon-4.0.2.tar.gz (Stored with Git LFS)

Binary file not shown.

View File

@@ -0,0 +1,13 @@
Index: falcon-3.1.1/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
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'github'
+pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []

View File

@@ -1,147 +1,3 @@
-------------------------------------------------------------------
Tue Mar 25 15:51:05 UTC 2025 - Markéta Machová <mmachova@suse.com>
- Add websockets.patch to fix test failure
-------------------------------------------------------------------
Thu Jan 9 11:57:38 UTC 2025 - Daniel Garcia <daniel.garcia@suse.com>
- Build doc package just for tumbleweed to remove
pydata-sphinx-theme requirement
-------------------------------------------------------------------
Tue Nov 12 10:49:26 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com>
- Update to 4.0.2
* Running Mypy on code that uses parts of falcon.testing would
previously lead to errors like:
"Name "falcon.testing.TestClient" is not defined"
This has been fixed by explicitly exporting the names that
are imported into the falcon.testing namespace. (#2387)
* The printable PDF version of our documentation was enabled
on Read the Docs. (#2365)
-------------------------------------------------------------------
Sat Nov 2 06:33:44 UTC 2024 - Steve Kowalik <steven.kowalik@suse.com>
- Update to 4.0.1:
* Overview
+ CPython 3.11 - 3.13 is now fully supported.
+ End-of-life Python 3.5, 3.6 & 3.7 are no longer supported.
+ End-of-life Python 3.8 is no longer actively supported.
+ Type checking support was introduced.
+ Falcon is no longer vendoring the python-mimeparse library.
+ A number of undocumented internal helpers were renamed to start with an
underscore.
+ A number of previously deprecated methods, attributes and classes have
now been removed.
+ We decided, on the other hand, to keep the deprecated falcon.API alias
until Falcon 5.0.
+ The deprecated api_helpers was removed in favor of the app_helpers
module.
+ The function falcon.http_date_to_dt now validates HTTP dates to have
the correct timezone set. It now also returns timezone-aware
datetime.datetime objects.
+ setup.cfg was dropped in favor of consolidating all static project
configuration in pyproject.toml
* New & Improved
+ A new path converter falcon.routing.PathConverter
capable of matching segments that include / was added.
+ Similar to the existing falcon.routing.IntConverter, a new
falcon.routing.FloatConverter has been added, allowing to convert
path segments to float.
+ A new method falcon.Request.get_header_as_int was implemented.
+ A new property, falcon.Request.headers_lower, was added to provide a
unified, self-documenting way to get a copy of all request headers with
lowercase names to facilitate case-insensitive matching.
+ In Python 3.13, the cgi module is removed entirely from the stdlib,
including its parse_header() method. Falcon addresses the issue by
shipping an own implementation.
+ The falcon.CORSMiddleware now properly handles the missing Allow
header case, by denying the preflight CORS request.
+ Added falcon.testing.Result.content_type and
falcon.testing.StreamedResult.content_type as a utility accessor
for the Content-Type header.
+ A new flag, falcon.ResponseOptions.xml_error_serialization, has been
added to falcon.ResponseOptions that can be used to disable automatic
XML serialization of falcon.HTTPError when using the default error
serializer (and the client prefers it).
* Fixed
+ The web servers used for tests are now run through sys.executable.
* Dropped patches, no longer required:
- python-falcon-sphinx-pygments-style.patch
- support-new-uvicorn.patch
-------------------------------------------------------------------
Tue Apr 2 01:45:24 UTC 2024 - Steve Kowalik <steven.kowalik@suse.com>
- 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 <daniel.garcia@suse.com>
- 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 <code@bnavigator.de>
- 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 <code@bnavigator.de>
- 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)
* Falcons 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á <mmachova@suse.com>
- remove unneeded build dependency python-ujson
-------------------------------------------------------------------
Tue Jan 2 23:52:59 UTC 2024 - Jiri Srain <jsrain@suse.com>

View File

@@ -1,7 +1,7 @@
#
# spec file for package python-falcon
#
# Copyright (c) 2025 SUSE LLC
# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -16,35 +16,26 @@
#
%if 0%{?suse_version} > 1600
%bcond_without doc
%else
%bcond_with doc
%endif
%{?sle15_python_module_pythons}
Name: python-falcon
Version: 4.0.2
Version: 3.1.1
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://files.pythonhosted.org/packages/source/f/falcon/falcon-%{version}.tar.gz
# PATCH-FIX-UPSTREAM https://github.com/falconry/falcon/pull/2406 chore(tests/asgi): migrate to the new websockets async client
Patch: websockets.patch
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
# github pygments style is not available
Patch0: python-falcon-sphinx-pygments-style.patch
BuildRequires: %{python_module PyYAML}
BuildRequires: %{python_module Sphinx}
BuildRequires: %{python_module base >= 3.8}
BuildRequires: %{python_module ddt}
BuildRequires: %{python_module httpx}
BuildRequires: %{python_module myst-parser >= 2}
BuildRequires: %{python_module pip}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module sphinx-design}
BuildRequires: %{python_module sphinx-tabs}
BuildRequires: %{python_module sphinxcontrib-copybutton}
BuildRequires: %{python_module websockets}
BuildRequires: %{python_module wheel}
# TODO: Cython support
#BuildRequires: %%{python_module Cython}
# SECTION test requirements
@@ -55,26 +46,25 @@ 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)}
BuildRequires: %{python_module websockets >= 13.1 if (%python-base without python36-base)}
%endif
%if %{with doc}
BuildRequires: %{python_module pydata-sphinx-theme}
BuildRequires: %{python_module websockets if (%python-base without python36-base)}
%endif
# /SECTION
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
@@ -86,41 +76,42 @@ as little as possible while remaining effective.
HTML documentation including API documentation and changelog for %{name}.
%prep
%autosetup -p1 -n falcon-%{version}
%setup -q -n falcon-%{version}
%patch0 -p1
# 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"
%pyproject_wheel
%if %{with doc}
%python_build
export PYTHONPATH="$(pwd)"
pushd docs
make html
rm _build/html/.buildinfo
popd
%endif
%install
%pyproject_install
%python_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 %fdupes %{buildroot}%{$python_sitelib}
%if %{with doc}
mkdir -p %{buildroot}%{_defaultdocdir}/%{name}-doc
cp -ar docs/_build/html examples %{buildroot}%{_defaultdocdir}/%{name}-doc/
%fdupes %{buildroot}%{_defaultdocdir}/%{name}-doc/
%endif
%{python_expand rm -rf %{buildroot}%{$python_sitelib}/examples
%fdupes %{buildroot}%{$python_sitelib}
}
%check
export LANG=en_US.UTF8
%pytest
# 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
%post
%{python_install_alternative falcon-bench falcon-inspect-app falcon-print-routes}
@@ -129,17 +120,15 @@ export LANG=en_US.UTF8
%python_uninstall_alternative falcon-bench
%files %{python_files}
%doc README.rst
%doc README.rst CHANGES.rst examples/
%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}.dist-info
%{python_sitelib}/falcon-%{version}*-info
%if %{with doc}
%files -n %{name}-doc
%doc %{_defaultdocdir}/%{name}-doc
%endif
%doc docs/_build/html
%changelog

View File

@@ -1,216 +0,0 @@
From cf51816a2f7cd7a23d3e1129fe9418a5fc85d8be Mon Sep 17 00:00:00 2001
From: Vytautas Liuolia <vytautas.liuolia@gmail.com>
Date: Mon, 11 Nov 2024 08:43:02 +0100
Subject: [PATCH] chore(tests/asgi): migrate to the new `websockets` async
client (#2406)
* chore(tests/asgi): migrate to the new `websockets` async client
* chore: update the unsupported WS protocol exception for Daphne/Hypercorn
---
requirements/tests | 2 +-
tests/asgi/test_asgi_servers.py | 67 +++++++++++++++++----------------
2 files changed, 35 insertions(+), 34 deletions(-)
diff --git a/requirements/tests b/requirements/tests
index ada7c3729..36825fd23 100644
--- a/requirements/tests
+++ b/requirements/tests
@@ -13,7 +13,7 @@ testtools; python_version < '3.10'
aiofiles
httpx
uvicorn >= 0.17.0
-websockets
+websockets >= 13.1
# Handler Specific
cbor2
diff --git a/tests/asgi/test_asgi_servers.py b/tests/asgi/test_asgi_servers.py
index eb35ac62d..044d46a38 100644
--- a/tests/asgi/test_asgi_servers.py
+++ b/tests/asgi/test_asgi_servers.py
@@ -24,6 +24,7 @@
try:
import websockets
+ import websockets.asyncio.client
import websockets.exceptions
except ImportError:
websockets = None # type: ignore
@@ -232,9 +233,9 @@ async def test_hello(
if close_code:
extra_headers['X-Close-Code'] = str(close_code)
- async with websockets.connect(
+ async with websockets.asyncio.client.connect(
server_url_events_ws,
- extra_headers=extra_headers,
+ additional_headers=extra_headers,
) as ws:
got_message = False
@@ -273,22 +274,22 @@ async def test_rejected(self, explicit_close, close_code, server_url_events_ws):
if close_code:
extra_headers['X-Close-Code'] = str(close_code)
- with pytest.raises(websockets.exceptions.InvalidStatusCode) as exc_info:
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ with pytest.raises(websockets.exceptions.InvalidStatus) as exc_info:
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
):
pass
- assert exc_info.value.status_code == 403
+ assert exc_info.value.response.status_code == 403
async def test_missing_responder(self, server_url_events_ws):
server_url_events_ws += '/404'
- with pytest.raises(websockets.exceptions.InvalidStatusCode) as exc_info:
- async with websockets.connect(server_url_events_ws):
+ with pytest.raises(websockets.exceptions.InvalidStatus) as exc_info:
+ async with websockets.asyncio.client.connect(server_url_events_ws):
pass
- assert exc_info.value.status_code == 403
+ assert exc_info.value.response.status_code == 403
@pytest.mark.parametrize(
'subprotocol, expected',
@@ -301,9 +302,9 @@ async def test_select_subprotocol_known(
self, subprotocol, expected, server_url_events_ws
):
extra_headers = {'X-Subprotocol': subprotocol}
- async with websockets.connect(
+ async with websockets.asyncio.client.connect(
server_url_events_ws,
- extra_headers=extra_headers,
+ additional_headers=extra_headers,
subprotocols=['amqp', 'wamp'],
) as ws:
assert ws.subprotocol == expected
@@ -312,9 +313,9 @@ async def test_select_subprotocol_unknown(self, server_url_events_ws):
extra_headers = {'X-Subprotocol': 'xmpp'}
try:
- async with websockets.connect(
+ async with websockets.asyncio.client.connect(
server_url_events_ws,
- extra_headers=extra_headers,
+ additional_headers=extra_headers,
subprotocols=['amqp', 'wamp'],
):
pass
@@ -329,8 +330,8 @@ async def test_select_subprotocol_unknown(self, server_url_events_ws):
except websockets.exceptions.NegotiationError as ex:
assert 'unsupported subprotocol: xmpp' in str(ex)
- # Daphne
- except websockets.exceptions.InvalidMessage:
+ # Daphne, Hypercorn
+ except EOFError:
pass
# NOTE(kgriffs): When executing this test under pytest with the -s
@@ -340,8 +341,8 @@ async def test_select_subprotocol_unknown(self, server_url_events_ws):
# but the usual ways of capturing stdout/stderr with pytest do
# not work.
async def test_disconnecting_client_early(self, server_url_events_ws):
- ws = await websockets.connect(
- server_url_events_ws, extra_headers={'X-Close': 'True'}
+ ws = await websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers={'X-Close': 'True'}
)
await asyncio.sleep(0.2)
@@ -361,8 +362,8 @@ async def test_disconnecting_client_early(self, server_url_events_ws):
async def test_send_before_accept(self, server_url_events_ws):
extra_headers = {'x-accept': 'skip'}
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
) as ws:
message = await ws.recv()
assert message == 'OperationNotAllowed'
@@ -370,8 +371,8 @@ async def test_send_before_accept(self, server_url_events_ws):
async def test_recv_before_accept(self, server_url_events_ws):
extra_headers = {'x-accept': 'skip', 'x-command': 'recv'}
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
) as ws:
message = await ws.recv()
assert message == 'OperationNotAllowed'
@@ -379,8 +380,8 @@ async def test_recv_before_accept(self, server_url_events_ws):
async def test_invalid_close_code(self, server_url_events_ws):
extra_headers = {'x-close': 'True', 'x-close-code': 42}
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
) as ws:
start = time.time()
@@ -395,22 +396,22 @@ async def test_invalid_close_code(self, server_url_events_ws):
async def test_close_code_on_unhandled_error(self, server_url_events_ws):
extra_headers = {'x-raise-error': 'generic'}
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
) as ws:
await ws.wait_closed()
- assert ws.close_code in {3011, 1011}
+ assert ws.protocol.close_code in {3011, 1011}
async def test_close_code_on_unhandled_http_error(self, server_url_events_ws):
extra_headers = {'x-raise-error': 'http'}
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
) as ws:
await ws.wait_closed()
- assert ws.close_code == 3400
+ assert ws.protocol.close_code == 3400
@pytest.mark.parametrize('mismatch', ['send', 'recv'])
@pytest.mark.parametrize('mismatch_type', ['text', 'data'])
@@ -420,8 +421,8 @@ async def test_type_mismatch(self, mismatch, mismatch_type, server_url_events_ws
'X-Mismatch-Type': mismatch_type,
}
- async with websockets.connect(
- server_url_events_ws, extra_headers=extra_headers
+ async with websockets.asyncio.client.connect(
+ server_url_events_ws, additional_headers=extra_headers
) as ws:
if mismatch == 'recv':
if mismatch_type == 'text':
@@ -431,13 +432,13 @@ async def test_type_mismatch(self, mismatch, mismatch_type, server_url_events_ws
await ws.wait_closed()
- assert ws.close_code in {3011, 1011}
+ assert ws.protocol.close_code in {3011, 1011}
async def test_passing_path_params(self, server_base_url_ws):
expected_feed_id = '1ee7'
url = f'{server_base_url_ws}feeds/{expected_feed_id}'
- async with websockets.connect(url) as ws:
+ async with websockets.asyncio.client.connect(url) as ws:
feed_id = await ws.recv()
assert feed_id == expected_feed_id