Skip to content

Commit 5730306

Browse files
author
Tomáš Trval
committed
Merge branch 'master' into werkzeug-importlib-573
2 parents 84b893d + e912d3d commit 5730306

File tree

7 files changed

+85
-13
lines changed

7 files changed

+85
-13
lines changed

CHANGELOG.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ Releases prior to 0.3.0 were “best effort” filled out, but are missing
2525
some info. If you see your contribution missing info, please open a PR
2626
on the Changelog!
2727

28+
.. _section-1.2.1:
29+
1.2.1
30+
-----
31+
.. _bug_fixes-1.2.1
32+
Bug Fixes
33+
~~~~~~~~~
34+
35+
::
36+
* Fixing werkzeug 3 deprecated version import. Import is replaced by new style version check with importlib (#573) [Ryu-CZ]
37+
38+
2839
.. _section-1.2.0:
2940
1.2.0
3041
-----
@@ -35,7 +46,7 @@ Bug Fixes
3546
::
3647

3748
* Fixing test as HTTP Header MIMEAccept expects quality-factor number in form of `X.X` (#547) [chipndell]
38-
* Fixing werkzeug 3 deprecated version import. Import is replaced by new style version check with importlib (#573) [Ryu-CZ]
49+
* Introduce temporary restrictions on some package versions. (`flask<3.0.0`, `werkzeug<3.0.0`, `jsonschema<=4.17.3`) [peter-doggart]
3950

4051

4152
.. _enhancements-1.2.0:

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ Flask and Werkzeug moved to versions 2.0 in March 2020. This caused a breaking c
6060
- < 2.0.0
6161
- pinned in Flask-RESTX.
6262
* - >= 0.5.0
63-
- All (For Now)
63+
- < 3.0.0
6464
- unpinned, import statements wrapped for compatibility
6565
* - trunk branch in Github
66-
- All (and updated more often)
66+
- < 3.0.0 (Flask >=3.0.0 support is in progress, see https://github.com/python-restx/flask-restx/issues/566)
6767
- unpinned, will address issues faster than releases.
6868

6969
Installation

flask_restx/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
__version__ = "1.1.1.dev"
2+
__version__ = "1.2.1.dev"
33
__description__ = (
44
"Fully featured framework for fast, easy and documented API development with Flask"
55
)

flask_restx/api.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
from flask import url_for, request, current_app
1515
from flask import make_response as original_flask_make_response
1616

17-
try:
18-
from flask.helpers import _endpoint_from_view_func
19-
except ImportError:
20-
from flask.scaffold import _endpoint_from_view_func
2117
from flask.signals import got_request_exception
2218

2319
from jsonschema import RefResolver
@@ -38,10 +34,15 @@
3834
from .postman import PostmanCollectionV1
3935
from .resource import Resource
4036
from .swagger import Swagger
41-
from .utils import default_id, camel_to_dash, unpack, BaseResponse
37+
38+
from .utils import default_id, camel_to_dash, unpack, import_check_view_func, BaseResponse
39+
4240
from .representations import output_json
4341
from ._http import HTTPStatus
4442

43+
endpoint_from_view_func = import_check_view_func()
44+
45+
4546
RE_RULES = re.compile("(<.*>)")
4647

4748
# List headers that should never be handled by Flask-RESTX
@@ -843,7 +844,7 @@ def _blueprint_setup_add_url_rule_patch(
843844
rule = blueprint_setup.url_prefix + rule
844845
options.setdefault("subdomain", blueprint_setup.subdomain)
845846
if endpoint is None:
846-
endpoint = _endpoint_from_view_func(view_func)
847+
endpoint = endpoint_from_view_func(view_func)
847848
defaults = blueprint_setup.url_defaults
848849
if "defaults" in options:
849850
defaults = dict(defaults, **options.pop("defaults"))

flask_restx/utils.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import re
2+
import warnings
3+
import typing
24

35
from collections import OrderedDict
46
from copy import deepcopy
@@ -40,6 +42,10 @@ def import_werkzeug_response():
4042
BaseResponse = import_werkzeug_response()
4143

4244

45+
class FlaskCompatibilityWarning(DeprecationWarning):
46+
pass
47+
48+
4349
def merge(first, second):
4450
"""
4551
Recursively merges two dictionaries.
@@ -138,3 +144,43 @@ def unpack(response, default_code=HTTPStatus.OK):
138144
return data, code or default_code, headers
139145
else:
140146
raise ValueError("Too many response values")
147+
148+
149+
def to_view_name(view_func: typing.Callable) -> str:
150+
"""Helper that returns the default endpoint for a given
151+
function. This always is the function name.
152+
153+
Note: copy of simple flask internal helper
154+
"""
155+
assert view_func is not None, "expected view func if endpoint is not provided."
156+
return view_func.__name__
157+
158+
159+
def import_check_view_func():
160+
"""
161+
Resolve import flask _endpoint_from_view_func.
162+
163+
Show warning if function cannot be found and provide copy of last known implementation.
164+
165+
Note: This helper method exists because reoccurring problem with flask function, but
166+
actual method body remaining the same in each flask version.
167+
"""
168+
import importlib.metadata
169+
170+
flask_version = importlib.metadata.version("flask").split(".")
171+
try:
172+
if flask_version[0] == "1":
173+
from flask.helpers import _endpoint_from_view_func
174+
elif flask_version[0] == "2":
175+
from flask.scaffold import _endpoint_from_view_func
176+
elif flask_version[0] == "3":
177+
from flask.sansio.scaffold import _endpoint_from_view_func
178+
else:
179+
warnings.simplefilter("once", FlaskCompatibilityWarning)
180+
_endpoint_from_view_func = None
181+
except ImportError:
182+
warnings.simplefilter("once", FlaskCompatibilityWarning)
183+
_endpoint_from_view_func = None
184+
if _endpoint_from_view_func is None:
185+
_endpoint_from_view_func = to_view_name
186+
return _endpoint_from_view_func

requirements/install.pip

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
aniso8601>=0.82
2-
jsonschema
3-
Flask>=0.8, !=2.0.0
4-
werkzeug !=2.0.0
2+
jsonschema<=4.17.3
3+
Flask>=0.8, !=2.0.0, <3.0.0
4+
werkzeug!=2.0.0, <3.0.0
55
pytz
66
importlib_resources

tests/test_utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,17 @@ def test_value_headers_default_code(self):
103103
def test_too_many_values(self):
104104
with pytest.raises(ValueError):
105105
utils.unpack((None, None, None, None))
106+
107+
108+
class ToViewNameTest(object):
109+
def test_none(self):
110+
with pytest.raises(AssertionError):
111+
_ = utils.to_view_name(None)
112+
113+
def test_name(self):
114+
assert self.test_none == self.test_none.__name__
115+
116+
117+
class ImportCheckViewFuncTest(object):
118+
def test_callable(self):
119+
assert callable(utils.import_check_view_func())

0 commit comments

Comments
 (0)