Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-doggart authored Jul 24, 2024
2 parents ebb33d0 + 29dd1fa commit 1a4dcd7
Show file tree
Hide file tree
Showing 26 changed files with 241 additions and 56 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,22 @@ jobs:
unit-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "pypy3.8"]
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy3.8", "3.12"]
flask: ["<3.0.0", ">=3.0.0"]
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Checkout code
uses: actions/checkout@v3
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "flask${{ matrix.flask }}"
pip install ".[test]"
- name: Test with inv
run: inv cover qa
Expand Down
54 changes: 54 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,60 @@ Releases prior to 0.3.0 were “best effort” filled out, but are missing
some info. If you see your contribution missing info, please open a PR
on the Changelog!

.. _section-1.3.1:
1.3.1
-----
.. _bug_fixes-1.3.1
Bug Fixes
~~~~~~~~~

::

* Add python version requirement on setup.py (#586) [jason-the-j]


.. _section-1.3.0:
1.3.0
-----
.. _bug_fixes-1.3.0
Bug Fixes
~~~~~~~~~

::

* Fixing werkzeug 3 deprecated version import. Import is replaced by new style version check with importlib (#573) [Ryu-CZ]
* Fixing flask 3.0+ compatibility of `ModuleNotFoundError: No module named 'flask.scaffold'` Import error. (#567) [Ryu-CZ]
* Fix wrong status code and message on responses when handling `HTTPExceptions` (#569) [lkk7]
* Add flask 2 and flask 3 to testing matrix. [foarsitter]
* Update internally pinned pytest-flask to 1.3.0 for Flask >=3.0.0 support. [peter-doggart]
* Python 3.12 support. [foarsitter]
* Fix wrong status code and message on responses when handling HTTPExceptions. [ikk7]
* Update changelog Flask version table. [peter-doggart]
* Remove temporary package version restrictions for flask < 3.0.0, werkzeug and jsonschema (jsonschema future deprecation warning remains. See #553). [peter-doggart]

.. _section-1.2.0:
1.2.0
-----
.. _bug_fixes-1.2.0
Bug Fixes
~~~~~~~~~

::

* Fixing test as HTTP Header MIMEAccept expects quality-factor number in form of `X.X` (#547) [chipndell]
* Introduce temporary restrictions on some package versions. (`flask<3.0.0`, `werkzeug<3.0.0`, `jsonschema<=4.17.3`) [peter-doggart]


.. _enhancements-1.2.0:

Enhancements
~~~~~~~~~~~~

::

* Drop support for python 3.7


.. _section-1.1.0:
1.1.0
-----
Expand Down
12 changes: 9 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ and expose its documentation properly using `Swagger`_.
Compatibility
=============

Flask-RESTX requires Python 3.7+.
Flask-RESTX requires Python 3.8+.

On Flask Compatibility
======================
Expand All @@ -60,10 +60,16 @@ Flask and Werkzeug moved to versions 2.0 in March 2020. This caused a breaking c
- < 2.0.0
- pinned in Flask-RESTX.
* - >= 0.5.0
- All (For Now)
- < 3.0.0
- unpinned, import statements wrapped for compatibility
* - == 1.2.0
- < 3.0.0
- pinned in Flask-RESTX.
* - >= 1.3.0
- >= 2.0.0 (Flask >= 3.0.0 support)
- unpinned, import statements wrapped for compatibility
* - trunk branch in Github
- All (and updated more often)
- >= 2.0.0 (Flask >= 3.0.0 support)
- unpinned, will address issues faster than releases.

Installation
Expand Down
2 changes: 1 addition & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ development and to support our users.
Compatibility
=============

Flask-RESTX requires Python 3.7+.
Flask-RESTX requires Python 3.8+.


Installation
Expand Down
2 changes: 1 addition & 1 deletion doc/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ The development version can be downloaded from
pip install -e .[dev,test]
Flask-RESTX requires Python version 2.7, 3.5, 3.6, 3.7, or 3.8.
Flask-RESTX requires Python version 3.8+.
It's also working with PyPy and PyPy3.
2 changes: 1 addition & 1 deletion doc/marshalling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ use :class:`~fields.Wildcard` ::
>>> '{"Jane": "68", "bob": "42", "John": "12"}'

The name you give to your :class:`~fields.Wildcard` acts as a real glob as
shown bellow ::
shown below ::

>>> from flask_restx import fields, marshal
>>> import json
Expand Down
2 changes: 1 addition & 1 deletion doc/parsing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ And your args will look like this :
args = parser.parse_args()
args['name'] # ['bob', 'sue', 'joe']
If you expect a coma separated list, use the ``action='split'``:
If you expect a comma-separated list, use the ``action='split'``:

.. code-block:: python
Expand Down
2 changes: 1 addition & 1 deletion doc/swagger.rst
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ Documenting authorizations
You can use the ``authorizations`` keyword argument to document authorization information.
See `Swagger Authentication documentation <https://swagger.io/docs/specification/2-0/authentication/>`_
for configuration details.
- ``authorizations`` is a Python dictionary representation of the Swagger ``securityDefinitions`` configuration.
- ``authorizations`` is a Python dictionary representation of the Swagger ``securityDefinitions`` configuration.

.. code-block:: python
Expand Down
2 changes: 1 addition & 1 deletion flask_restx/__about__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
__version__ = "1.1.1.dev"
__version__ = "1.3.1.dev"
__description__ = (
"Fully featured framework for fast, easy and documented API development with Flask"
)
32 changes: 17 additions & 15 deletions flask_restx/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
from flask import url_for, request, current_app
from flask import make_response as original_flask_make_response

try:
from flask.helpers import _endpoint_from_view_func
except ImportError:
from flask.scaffold import _endpoint_from_view_func
from flask.signals import got_request_exception

from jsonschema import RefResolver
Expand All @@ -32,23 +28,25 @@
InternalServerError,
)

from werkzeug import __version__ as werkzeug_version

if werkzeug_version.split(".")[0] >= "2":
from werkzeug.wrappers import Response as BaseResponse
else:
from werkzeug.wrappers import BaseResponse

from . import apidoc
from .mask import ParseError, MaskError
from .namespace import Namespace
from .postman import PostmanCollectionV1
from .resource import Resource
from .swagger import Swagger
from .utils import default_id, camel_to_dash, unpack
from .utils import (
default_id,
camel_to_dash,
unpack,
import_check_view_func,
BaseResponse,
)
from .representations import output_json
from ._http import HTTPStatus

endpoint_from_view_func = import_check_view_func()


RE_RULES = re.compile("(<.*>)")

# List headers that should never be handled by Flask-RESTX
Expand Down Expand Up @@ -726,9 +724,13 @@ def handle_error(self, e):
got_request_exception.send(current_app._get_current_object(), exception=e)

if isinstance(e, HTTPException):
code = HTTPStatus(e.code)
code = None
if e.code is not None:
code = HTTPStatus(e.code)
elif e.response is not None:
code = HTTPStatus(e.response.status_code)
if include_message_in_response:
default_data = {"message": getattr(e, "description", code.phrase)}
default_data = {"message": e.description or code.phrase}
headers = e.get_response().headers
elif self._default_error_handler:
result = self._default_error_handler(e)
Expand Down Expand Up @@ -850,7 +852,7 @@ def _blueprint_setup_add_url_rule_patch(
rule = blueprint_setup.url_prefix + rule
options.setdefault("subdomain", blueprint_setup.subdomain)
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
endpoint = endpoint_from_view_func(view_func)
defaults = blueprint_setup.url_defaults
if "defaults" in options:
defaults = dict(defaults, **options.pop("defaults"))
Expand Down
8 changes: 5 additions & 3 deletions flask_restx/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,11 @@ def is_attr(val):
return [
self.container.output(
idx,
val
if (isinstance(val, dict) or is_attr(val)) and not is_nested
else value,
(
val
if (isinstance(val, dict) or is_attr(val)) and not is_nested
else value
),
)
for idx, val in enumerate(value)
]
Expand Down
8 changes: 5 additions & 3 deletions flask_restx/marshalling.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,11 @@ def __format_field(key, val):
return (key, value)

items = (
(k, marshal(data, v, skip_none=skip_none, ordered=ordered))
if isinstance(v, dict)
else __format_field(k, v)
(
(k, marshal(data, v, skip_none=skip_none, ordered=ordered))
if isinstance(v, dict)
else __format_field(k, v)
)
for k, v in fields.items()
)

Expand Down
8 changes: 5 additions & 3 deletions flask_restx/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,11 @@ def marshal_with(
def wrapper(func):
doc = {
"responses": {
str(code): (description, [fields], kwargs)
if as_list
else (description, fields, kwargs)
str(code): (
(description, [fields], kwargs)
if as_list
else (description, fields, kwargs)
)
},
"__mask__": kwargs.get(
"mask", True
Expand Down
7 changes: 1 addition & 6 deletions flask_restx/resource.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
from flask import request
from flask.views import MethodView
from werkzeug import __version__ as werkzeug_version

if werkzeug_version.split(".")[0] >= "2":
from werkzeug.wrappers import Response as BaseResponse
else:
from werkzeug.wrappers import BaseResponse

from .model import ModelBase

from .utils import unpack
from .utils import unpack, BaseResponse


class Resource(MethodView):
Expand Down
9 changes: 6 additions & 3 deletions flask_restx/schemas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
.. versionadded:: 0.12.1
"""

import io
import json
import pkg_resources

import importlib_resources

from collections.abc import Mapping
from jsonschema import Draft4Validator
Expand Down Expand Up @@ -56,8 +58,9 @@ def __init__(self, filename, validator=Draft4Validator):

def _load(self):
if not self._schema:
filename = pkg_resources.resource_filename(__name__, self.filename)
with io.open(filename) as infile:
ref = importlib_resources.files(__name__) / self.filename

with io.open(ref) as infile:
self._schema = json.load(infile)

def __getitem__(self, key):
Expand Down
Loading

0 comments on commit 1a4dcd7

Please sign in to comment.