Skip to content

Commit 4308d12

Browse files
committed
Bump framework versions
1 parent c25f908 commit 4308d12

9 files changed

Lines changed: 58 additions & 155 deletions

File tree

pyproject.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ Tidelift = "https://tidelift.com/subscription/pkg/pypi-webargs?utm_source=pypi-w
5757

5858
[project.optional-dependencies]
5959
frameworks = [
60-
"Flask>=0.12.5",
61-
"Django>=2.2.0",
60+
"Flask>=3.1.0",
61+
"Django>=5.2.0",
6262
"bottle>=0.13.0",
63-
"tornado>=6.0.0",
64-
"pyramid>=1.9.1",
65-
"falcon>=2.0.0",
66-
"aiohttp>=3.0.8",
63+
"tornado>=6.5.0",
64+
"pyramid>=2.0.2",
65+
"falcon>=4.1.0",
66+
"aiohttp>=3.13.0",
6767
]
6868
tests = [
6969
"webargs[frameworks]",

tests/apps/django_app/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
import importlib.metadata
21

3-
DJANGO_MAJOR_VERSION = int(importlib.metadata.version("django").split(".")[0])
4-
DJANGO_SUPPORTS_ASYNC = DJANGO_MAJOR_VERSION >= 3

tests/apps/falcon_app.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import importlib.metadata
2-
31
import falcon
42
import marshmallow as ma
53

@@ -10,9 +8,6 @@
108
hello_args = {"name": fields.Str(load_default="World", validate=validate.Length(min=3))}
119
hello_multiple = {"name": fields.List(fields.Str())}
1210

13-
FALCON_MAJOR_VERSION = int(importlib.metadata.version("falcon").split(".")[0])
14-
FALCON_SUPPORTS_ASYNC = FALCON_MAJOR_VERSION >= 3
15-
1611

1712
class HelloSchema(ma.Schema):
1813
name = fields.Str(load_default="World", validate=validate.Length(min=3))
@@ -25,10 +20,7 @@ class HelloSchema(ma.Schema):
2520

2621

2722
def set_text(resp, value):
28-
if FALCON_MAJOR_VERSION >= 3:
29-
resp.text = value
30-
else:
31-
resp.body = value
23+
resp.text = value
3224

3325

3426
class Echo:
@@ -191,11 +183,7 @@ def on_get(self, req, resp):
191183

192184

193185
def create_app():
194-
if FALCON_MAJOR_VERSION >= 3:
195-
app = falcon.App()
196-
else:
197-
app = falcon.API()
198-
186+
app = falcon.App()
199187
app.add_route("/echo", Echo())
200188
app.add_route("/echo_form", EchoForm())
201189
app.add_route("/echo_json", EchoJSON())

tests/apps/flask_app.py

Lines changed: 42 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import importlib.metadata
2-
31
import marshmallow as ma
42
from flask import Flask, Response, request
53
from flask import jsonify as J
@@ -13,9 +11,6 @@
1311
use_kwargs,
1412
)
1513

16-
FLASK_MAJOR_VERSION = int(importlib.metadata.version("flask").split(".")[0])
17-
FLASK_SUPPORTS_ASYNC = FLASK_MAJOR_VERSION >= 2
18-
1914

2015
class TestAppConfig:
2116
TESTING = True
@@ -138,12 +133,10 @@ def echo_headers_raising(args):
138133
return J(args)
139134

140135

141-
if FLASK_SUPPORTS_ASYNC:
142-
143-
@app.route("/echo_headers_raising_async")
144-
@use_args(HelloSchema(), location="headers", unknown=None)
145-
async def echo_headers_raising_async(args):
146-
return J(args)
136+
@app.route("/echo_headers_raising_async")
137+
@use_args(HelloSchema(), location="headers", unknown=None)
138+
async def echo_headers_raising_async(args):
139+
return J(args)
147140

148141

149142
@app.route("/echo_cookie")
@@ -165,14 +158,12 @@ def echo_view_arg(view_arg):
165158
return J(parser.parse({"view_arg": fields.Int()}, location="view_args"))
166159

167160

168-
if FLASK_SUPPORTS_ASYNC:
169-
170-
@app.route("/echo_view_arg_async/<view_arg>")
171-
async def echo_view_arg_async(view_arg):
172-
parsed_view_arg = await parser.async_parse(
173-
{"view_arg": fields.Int()}, location="view_args"
174-
)
175-
return J(parsed_view_arg)
161+
@app.route("/echo_view_arg_async/<view_arg>")
162+
async def echo_view_arg_async(view_arg):
163+
parsed_view_arg = await parser.async_parse(
164+
{"view_arg": fields.Int()}, location="view_args"
165+
)
166+
return J(parsed_view_arg)
176167

177168

178169
@app.route("/echo_view_arg_use_args/<view_arg>")
@@ -181,12 +172,10 @@ def echo_view_arg_with_use_args(args, **kwargs):
181172
return J(args)
182173

183174

184-
if FLASK_SUPPORTS_ASYNC:
185-
186-
@app.route("/echo_view_arg_use_args_async/<view_arg>")
187-
@use_args({"view_arg": fields.Int()}, location="view_args")
188-
async def echo_view_arg_with_use_args_async(args, **kwargs):
189-
return J(args)
175+
@app.route("/echo_view_arg_use_args_async/<view_arg>")
176+
@use_args({"view_arg": fields.Int()}, location="view_args")
177+
async def echo_view_arg_with_use_args_async(args, **kwargs):
178+
return J(args)
190179

191180

192181
@app.route("/echo_nested", methods=["POST"])
@@ -211,16 +200,12 @@ def echo_nested_many_with_data_key():
211200
return J(parser.parse(args))
212201

213202

214-
if FLASK_SUPPORTS_ASYNC:
215-
216-
@app.route("/echo_nested_many_data_key_async", methods=["POST"])
217-
async def echo_nested_many_with_data_key_async():
218-
args = {
219-
"x_field": fields.Nested(
220-
{"id": fields.Int()}, many=True, data_key="X-Field"
221-
)
222-
}
223-
return J(await parser.async_parse(args))
203+
@app.route("/echo_nested_many_data_key_async", methods=["POST"])
204+
async def echo_nested_many_with_data_key_async():
205+
args = {
206+
"x_field": fields.Nested({"id": fields.Int()}, many=True, data_key="X-Field")
207+
}
208+
return J(await parser.async_parse(args))
224209

225210

226211
class EchoMethodViewUseArgs(MethodView):
@@ -235,17 +220,16 @@ def post(self, args):
235220
)
236221

237222

238-
if FLASK_SUPPORTS_ASYNC:
223+
class EchoMethodViewUseArgsAsync(MethodView):
224+
@use_args({"val": fields.Int()})
225+
async def post(self, args):
226+
return J(args)
239227

240-
class EchoMethodViewUseArgsAsync(MethodView):
241-
@use_args({"val": fields.Int()})
242-
async def post(self, args):
243-
return J(args)
244228

245-
app.add_url_rule(
246-
"/echo_method_view_use_args_async",
247-
view_func=EchoMethodViewUseArgsAsync.as_view("echo_method_view_use_args_async"),
248-
)
229+
app.add_url_rule(
230+
"/echo_method_view_use_args_async",
231+
view_func=EchoMethodViewUseArgsAsync.as_view("echo_method_view_use_args_async"),
232+
)
249233

250234

251235
class EchoMethodViewUseKwargs(MethodView):
@@ -259,19 +243,17 @@ def post(self, val):
259243
view_func=EchoMethodViewUseKwargs.as_view("echo_method_view_use_kwargs"),
260244
)
261245

262-
if FLASK_SUPPORTS_ASYNC:
263246

264-
class EchoMethodViewUseKwargsAsync(MethodView):
265-
@use_kwargs({"val": fields.Int()})
266-
async def post(self, val):
267-
return J({"val": val})
247+
class EchoMethodViewUseKwargsAsync(MethodView):
248+
@use_kwargs({"val": fields.Int()})
249+
async def post(self, val):
250+
return J({"val": val})
268251

269-
app.add_url_rule(
270-
"/echo_method_view_use_kwargs_async",
271-
view_func=EchoMethodViewUseKwargsAsync.as_view(
272-
"echo_method_view_use_kwargs_async"
273-
),
274-
)
252+
253+
app.add_url_rule(
254+
"/echo_method_view_use_kwargs_async",
255+
view_func=EchoMethodViewUseKwargsAsync.as_view("echo_method_view_use_kwargs_async"),
256+
)
275257

276258

277259
@app.route("/echo_use_kwargs_missing", methods=["post"])
@@ -281,13 +263,11 @@ def echo_use_kwargs_missing(username, **kwargs):
281263
return J({"username": username})
282264

283265

284-
if FLASK_SUPPORTS_ASYNC:
285-
286-
@app.route("/echo_use_kwargs_missing_async", methods=["post"])
287-
@use_kwargs({"username": fields.Str(required=True), "password": fields.Str()})
288-
async def echo_use_kwargs_missing_async(username, **kwargs):
289-
assert "password" not in kwargs
290-
return J({"username": username})
266+
@app.route("/echo_use_kwargs_missing_async", methods=["post"])
267+
@use_kwargs({"username": fields.Str(required=True), "password": fields.Str()})
268+
async def echo_use_kwargs_missing_async(username, **kwargs):
269+
assert "password" not in kwargs
270+
return J({"username": username})
291271

292272

293273
# Return validation errors as JSON

tests/test_djangoparser.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import pytest
22

3-
from tests.apps.django_app import DJANGO_SUPPORTS_ASYNC
43
from tests.apps.django_app.base.wsgi import application
54
from webargs.testing import CommonTestCase
65

@@ -29,14 +28,8 @@ def test_use_args_in_class_based_view_with_path_param(self, testapp):
2928
res = testapp.get("/echo_use_args_with_path_param_cbv/42?name=Fred")
3029
assert res.json == {"name": "Fred"}
3130

32-
@pytest.mark.skipif(
33-
not DJANGO_SUPPORTS_ASYNC, reason="requires a django version with async support"
34-
)
3531
def test_parse_querystring_args_async(self, testapp):
3632
assert testapp.get("/async_echo?name=Fred").json == {"name": "Fred"}
3733

38-
@pytest.mark.skipif(
39-
not DJANGO_SUPPORTS_ASYNC, reason="requires a django version with async support"
40-
)
4134
def test_async_use_args_decorator(self, testapp):
4235
assert testapp.get("/async_echo_use_args?name=Fred").json == {"name": "Fred"}

tests/test_falconparser.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import falcon.testing
22
import pytest
33

4-
from tests.apps.falcon_app import FALCON_SUPPORTS_ASYNC, create_app, create_async_app
4+
from tests.apps.falcon_app import create_app, create_async_app
55
from webargs.testing import CommonTestCase
66

77

@@ -73,17 +73,11 @@ def test_body_parsing_works_with_simulate(self):
7373
)
7474
assert res.json == {"name": "Fred"}
7575

76-
@pytest.mark.skipif(
77-
not FALCON_SUPPORTS_ASYNC, reason="requires a falcon version with async support"
78-
)
7976
def test_parse_querystring_args_async(self):
8077
app = create_async_app()
8178
client = falcon.testing.TestClient(app)
8279
assert client.simulate_get("/async_echo?name=Fred").json == {"name": "Fred"}
8380

84-
@pytest.mark.skipif(
85-
not FALCON_SUPPORTS_ASYNC, reason="requires a falcon version with async support"
86-
)
8781
def test_async_use_args_decorator(self):
8882
app = create_async_app()
8983
client = falcon.testing.TestClient(app)

tests/test_flaskparser.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from webargs.flaskparser import abort, parser
1111
from webargs.testing import CommonTestCase
1212

13-
from .apps.flask_app import FLASK_SUPPORTS_ASYNC, app
13+
from .apps.flask_app import app
1414

1515

1616
class TestFlaskParser(CommonTestCase):
@@ -71,53 +71,32 @@ class TestFlaskAsyncParser(CommonTestCase):
7171
def create_app(self):
7272
return app
7373

74-
@pytest.mark.skipif(
75-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
76-
)
7774
def test_parsing_view_args_async(self, testapp):
7875
res = testapp.get("/echo_view_arg_async/42")
7976
assert res.json == {"view_arg": 42}
8077

81-
@pytest.mark.skipif(
82-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
83-
)
8478
def test_parsing_invalid_view_arg_async(self, testapp):
8579
res = testapp.get("/echo_view_arg_async/foo", expect_errors=True)
8680
assert res.status_code == 422
8781
assert res.json == {"view_args": {"view_arg": ["Not a valid integer."]}}
8882

89-
@pytest.mark.skipif(
90-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
91-
)
9283
def test_use_args_with_view_args_parsing_async(self, testapp):
9384
res = testapp.get("/echo_view_arg_use_args_async/42")
9485
assert res.json == {"view_arg": 42}
9586

96-
@pytest.mark.skipif(
97-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
98-
)
9987
def test_use_args_on_a_method_view_async(self, testapp):
10088
res = testapp.post_json("/echo_method_view_use_args_async", {"val": 42})
10189
assert res.json == {"val": 42}
10290

103-
@pytest.mark.skipif(
104-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
105-
)
10691
def test_use_kwargs_on_a_method_view_async(self, testapp):
10792
res = testapp.post_json("/echo_method_view_use_kwargs_async", {"val": 42})
10893
assert res.json == {"val": 42}
10994

110-
@pytest.mark.skipif(
111-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
112-
)
11395
def test_use_kwargs_with_missing_data_async(self, testapp):
11496
res = testapp.post_json("/echo_use_kwargs_missing_async", {"username": "foo"})
11597
assert res.json == {"username": "foo"}
11698

11799
# regression test for https://github.com/marshmallow-code/webargs/issues/145
118-
@pytest.mark.skipif(
119-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
120-
)
121100
def test_nested_many_with_data_key_async(self, testapp):
122101
post_with_raw_fieldname_args = (
123102
"/echo_nested_many_data_key_async",
@@ -135,9 +114,6 @@ def test_nested_many_with_data_key_async(self, testapp):
135114
assert res.json == {}
136115

137116
# regression test for https://github.com/marshmallow-code/webargs/issues/500
138-
@pytest.mark.skipif(
139-
not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask"
140-
)
141117
def test_parsing_unexpected_headers_when_raising_async(self, testapp):
142118
res = testapp.get(
143119
"/echo_headers_raising_async",
@@ -178,7 +154,6 @@ def validate(x):
178154

179155

180156
@pytest.mark.asyncio
181-
@pytest.mark.skipif(not FLASK_SUPPORTS_ASYNC, reason="requires async support in flask")
182157
async def test_abort_called_on_validation_error_async():
183158
with mock.patch("webargs.flaskparser.abort") as mock_abort:
184159
# error handling must raise an error to be valid

tests/test_tornadoparser.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,6 @@ class BaseAsyncTestCase(tornado.testing.AsyncHTTPTestCase):
2525
# this isn't a real test case itself
2626
__test__ = False
2727

28-
# Workaround for https://github.com/pytest-dev/pytest/issues/12263.
29-
#
30-
# this was suggested by one of the pytest maintainers while a patch
31-
# for Tornado is pending
32-
#
33-
# we may need it even after the patch, since we want to support testing on
34-
# older Tornado versions until we drop support for them
35-
def runTest(self):
36-
pass
37-
3828

3929
name = "name"
4030
value = "value"

0 commit comments

Comments
 (0)