[packages/python-flask-restful] - new, with dozen of patches to make it compatible with recent python 3/flask 3
qboosh
qboosh at pld-linux.org
Thu Dec 25 20:23:03 CET 2025
commit 07408285ee9e6644637eac91bd022ec36f76793a
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date: Thu Dec 25 20:22:40 2025 +0100
- new, with dozen of patches to make it compatible with recent python 3/flask 3
Flask-RESTful-encoding.patch | 7 ++
Flask-RESTful-flask-app.patch | 31 +++++++
Flask-RESTful-flask.patch | 15 ++++
Flask-RESTful-mock.patch | 27 ++++++
Flask-RESTful-pynose.patch | 20 +++++
Flask-RESTful-pytz.patch | 49 +++++++++++
Flask-RESTful-werkzeug-json.patch | 63 ++++++++++++++
python-flask-restful.spec | 177 ++++++++++++++++++++++++++++++++++++++
8 files changed, 389 insertions(+)
---
diff --git a/python-flask-restful.spec b/python-flask-restful.spec
new file mode 100644
index 0000000..952d731
--- /dev/null
+++ b/python-flask-restful.spec
@@ -0,0 +1,177 @@
+#
+# Conditional build:
+%bcond_with doc # Sphinx documentation (_themes dir is missing in sdist)
+%bcond_without tests # unit tests
+%bcond_without python2 # CPython 2.x module
+%bcond_without python3 # CPython 3.x module
+
+Summary: Simple framework for creating REST APIs
+Summary(pl.UTF-8): Prosty szkielet do tworzenia API REST-owych
+Name: python-flask-restful
+Version: 0.3.10
+Release: 1
+License: BSD
+Group: Libraries/Python
+#Source0Download: https://pypi.org/simple/flask-restful/
+Source0: https://files.pythonhosted.org/packages/source/F/Flask-RESTful/Flask-RESTful-%{version}.tar.gz
+# Source0-md5: 2a1f17e91c526a03bf721e178d8fce94
+Patch0: Flask-RESTful-encoding.patch
+Patch1: Flask-RESTful-pytz.patch
+Patch2: Flask-RESTful-mock.patch
+Patch3: Flask-RESTful-flask.patch
+Patch4: Flask-RESTful-pynose.patch
+# https://github.com/flask-restful/flask-restful/pull/983
+Patch5: Flask-RESTful-werkzeug-json.patch
+# https://github.com/flask-restful/flask-restful/pull/972
+Patch6: Flask-RESTful-flask-app.patch
+URL: https://pypi.org/project/Flask-RESTful/
+%if %{with python2}
+BuildRequires: python-modules >= 1:2.7
+BuildRequires: python-setuptools
+%if %{with tests}
+BuildRequires: python-aniso8601 >= 0.82
+BuildRequires: python-blinker
+BuildRequires: python-flask >= 0.8
+BuildRequires: python-mock >= 0.8
+BuildRequires: python-nose >= 1.1.2
+BuildRequires: python-pytz
+BuildRequires: python-six >= 1.3.0
+%endif
+%endif
+%if %{with python3}
+BuildRequires: python3-modules >= 1:3.4
+BuildRequires: python3-setuptools
+%if %{with tests}
+BuildRequires: python3-aniso8601 >= 0.82
+BuildRequires: python3-blinker
+BuildRequires: python3-flask >= 0.8
+BuildRequires: python3-pynose >= 1.1.2
+BuildRequires: python3-pytz
+BuildRequires: python3-six >= 1.3.0
+%endif
+%endif
+BuildRequires: rpm-pythonprov
+BuildRequires: rpmbuild(macros) >= 1.714
+%if %{with doc}
+BuildRequires: sphinx-pdg-3
+%endif
+Requires: python-modules >= 1:2.7
+BuildArch: noarch
+BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+Flask-RESTful provides the building blocks for creating a great REST
+API.
+
+%description -l pl.UTF-8
+Flask-RESTful dostarcza elementy do budowania dobrych API REST-owych.
+
+%package -n python3-flask-restful
+Summary: Simple framework for creating REST APIs
+Summary(pl.UTF-8): Prosty szkielet do tworzenia API REST-owych
+Group: Libraries/Python
+Requires: python3-modules >= 1:3.4
+
+%description -n python3-flask-restful
+Flask-RESTful provides the building blocks for creating a great REST
+API.
+
+%description -n python3-flask-restful -l pl.UTF-8
+Flask-RESTful dostarcza elementy do budowania dobrych API REST-owych.
+
+%package apidocs
+Summary: API documentation for Python flask_restful module
+Summary(pl.UTF-8): Dokumentacja API modułu Pythona flask_restful
+Group: Documentation
+
+%description apidocs
+API documentation for Python flask_restful module.
+
+%description apidocs -l pl.UTF-8
+Dokumentacja API modułu Pythona flask_restful.
+
+%prep
+%setup -q -n Flask-RESTful-%{version}
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
+%patch -P4 -p1
+%patch -P5 -p1
+%patch -P6 -p1
+
+%build
+%if %{with python2}
+%py_build
+
+%if %{with tests}
+# test_api uses types.SimpleNamespace added in Python 3.3
+PYTHONPATH=$(pwd) \
+nosetests-%{py_ver} -w tests --ignore-files test_api.py
+%endif
+%endif
+
+%if %{with python3}
+%py3_build
+
+%if %{with tests}
+# some tests fail (not ready for Flask 3 yet)
+PYTHONPATH=$(pwd) \
+nosetests-%{py3_ver} -w tests \
+ -e test_exception_header_forwarded \
+ -e test_media_types_method \
+ -e test_media_types_q \
+ -e test_redirect
+%endif
+%endif
+
+%if %{with doc}
+%{__make} -C docs html \
+ SPHINXBUILD=sphinx-build-3
+%endif
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+%if %{with python2}
+%py_install
+
+%py_postclean
+
+install -d $RPM_BUILD_ROOT%{_examplesdir}/python-flask-restful-%{version}
+cp -p examples/*.py $RPM_BUILD_ROOT%{_examplesdir}/python-flask-restful-%{version}
+%endif
+
+%if %{with python3}
+%py3_install
+
+install -d $RPM_BUILD_ROOT%{_examplesdir}/python3-flask-restful-%{version}
+cp -p examples/*.py $RPM_BUILD_ROOT%{_examplesdir}/python3-flask-restful-%{version}
+%endif
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%if %{with python2}
+%files
+%defattr(644,root,root,755)
+%doc AUTHORS.md LICENSE README.md
+%{py_sitescriptdir}/flask_restful
+%{py_sitescriptdir}/Flask_RESTful-%{version}-py*.egg-info
+%{_examplesdir}/python-flask-restful-%{version}
+%endif
+
+%if %{with python3}
+%files -n python3-flask-restful
+%defattr(644,root,root,755)
+%doc AUTHORS.md LICENSE README.md
+%{py3_sitescriptdir}/flask_restful
+%{py3_sitescriptdir}/Flask_RESTful-%{version}-py*.egg-info
+%{_examplesdir}/python3-flask-restful-%{version}
+%endif
+
+%if %{with doc}
+%files apidocs
+%defattr(644,root,root,755)
+%doc docs/_build/html/*
+%endif
diff --git a/Flask-RESTful-encoding.patch b/Flask-RESTful-encoding.patch
new file mode 100644
index 0000000..4ea5fa1
--- /dev/null
+++ b/Flask-RESTful-encoding.patch
@@ -0,0 +1,7 @@
+--- Flask-RESTful-0.3.10/flask_restful/__init__.py.orig 2023-05-21 05:45:44.000000000 +0200
++++ Flask-RESTful-0.3.10/flask_restful/__init__.py 2025-12-21 10:28:00.938410239 +0100
+@@ -1,3 +1,4 @@
++# -*- coding: utf-8 -*-
+ from __future__ import absolute_import
+ from functools import wraps, partial
+ from flask import request, url_for, current_app
diff --git a/Flask-RESTful-flask-app.patch b/Flask-RESTful-flask-app.patch
new file mode 100644
index 0000000..370e3e6
--- /dev/null
+++ b/Flask-RESTful-flask-app.patch
@@ -0,0 +1,31 @@
+From 923c3938ed9ba6eb81bd8b2b966fd64ae988a042 Mon Sep 17 00:00:00 2001
+From: menglutao <azraeltml at gmail.com>
+Date: Wed, 27 Dec 2023 13:48:19 +0100
+Subject: [PATCH] Set self.app in init_app
+
+---
+ flask_restful/__init__.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/flask_restful/__init__.py b/flask_restful/__init__.py
+index 46915c8b..9d64dc86 100644
+--- a/flask_restful/__init__.py
++++ b/flask_restful/__init__.py
+@@ -118,8 +118,7 @@ def __init__(self, app=None, prefix='',
+ self.app = None
+ self.blueprint = None
+
+- if app is not None:
+- self.app = app
++ if app is not None:
+ self.init_app(app)
+
+ def init_app(self, app):
+@@ -137,6 +136,7 @@ def init_app(self, app):
+ api.init_app(app)
+
+ """
++ self.app = app # Set the app here
+ # If app is a blueprint, defer the initialization
+ try:
+ app.record(self._deferred_blueprint_init)
diff --git a/Flask-RESTful-flask.patch b/Flask-RESTful-flask.patch
new file mode 100644
index 0000000..1a0cf3f
--- /dev/null
+++ b/Flask-RESTful-flask.patch
@@ -0,0 +1,15 @@
+--- Flask-RESTful-0.3.10/tests/test_api.py.orig 2023-05-21 05:51:10.000000000 +0200
++++ Flask-RESTful-0.3.10/tests/test_api.py 2025-12-23 06:19:38.900011643 +0100
+@@ -1,7 +1,11 @@
+ import unittest
+ import json
+ from flask import Flask, Blueprint, redirect, views, abort as flask_abort
+-from flask.signals import got_request_exception, signals_available
++from flask.signals import got_request_exception
++try:
++ from flask.signals import signals_available
++except ImportError:
++ signals_available = True # Flask>=2.3.0
+ try:
+ from mock import Mock
+ except:
diff --git a/Flask-RESTful-mock.patch b/Flask-RESTful-mock.patch
new file mode 100644
index 0000000..aaecf76
--- /dev/null
+++ b/Flask-RESTful-mock.patch
@@ -0,0 +1,27 @@
+--- Flask-RESTful-0.3.10/tests/test_fields.py.orig 2025-12-22 05:35:25.708779441 +0100
++++ Flask-RESTful-0.3.10/tests/test_fields.py 2025-12-22 05:37:46.711348897 +0100
+@@ -2,7 +2,10 @@ from decimal import Decimal
+ from functools import partial
+ import pytz
+ import unittest
+-from mock import Mock
++try:
++ from mock import Mock
++except ImportError:
++ from unittest.mock import Mock
+ from flask_restful.fields import MarshallingException
+ from flask_restful.utils import OrderedDict
+ from flask_restful import fields
+--- Flask-RESTful-0.3.10/tests/test_reqparse.py.orig 2021-05-17 21:16:30.000000000 +0200
++++ Flask-RESTful-0.3.10/tests/test_reqparse.py 2025-12-22 05:38:12.091211403 +0100
+@@ -1,6 +1,9 @@
+ # -*- coding: utf-8 -*-
+ import unittest
+-from mock import Mock, patch
++try:
++ from mock import Mock, patch
++except ImportError:
++ from unittest.mock import Mock, patch
+ from flask import Flask
+ from werkzeug import exceptions
+ from werkzeug.wrappers import Request
diff --git a/Flask-RESTful-pynose.patch b/Flask-RESTful-pynose.patch
new file mode 100644
index 0000000..c15292a
--- /dev/null
+++ b/Flask-RESTful-pynose.patch
@@ -0,0 +1,20 @@
+pynose doesn't define PEP8'd assert_snake_case variants of TestCase.assertCamelCases in nose.tools
+--- Flask-RESTful-0.3.10/tests/test_fields.py.orig 2025-12-23 06:12:25.239117653 +0100
++++ Flask-RESTful-0.3.10/tests/test_fields.py 2025-12-23 06:27:01.096706053 +0100
+@@ -12,7 +12,15 @@ from flask_restful import fields
+ from datetime import datetime, timedelta, tzinfo
+ from flask import Flask, Blueprint
+ #noinspection PyUnresolvedReferences
+-from nose.tools import assert_equals # you need it for tests in form of continuations
++try:
++ from nose.tools import assert_equals # you need it for tests in form of continuations
++except ImportError:
++ class _FakeCase(unittest.TestCase):
++ def nop():
++ pass
++ _t = _FakeCase("nop")
++ def assert_equals(a, b):
++ return _t.assertEqual(a, b)
+
+
+ class Foo(object):
diff --git a/Flask-RESTful-pytz.patch b/Flask-RESTful-pytz.patch
new file mode 100644
index 0000000..3e1a5bb
--- /dev/null
+++ b/Flask-RESTful-pytz.patch
@@ -0,0 +1,49 @@
+pytz objects are not fully compatible with tzinfo datetime field, use localize() to get
+correct results with recent pytz/tzdata releases (after extending supported dates,
+the default tz offset is lunar time based).
+Due to wrong usage, two test cases expected result were wrong (assuming +0100 for CET,
+like in the beginning of the year, not +0200, taking DST in account on given date).
+--- Flask-RESTful-0.3.10/tests/test_fields.py.orig 2021-05-17 21:16:30.000000000 +0200
++++ Flask-RESTful-0.3.10/tests/test_fields.py 2025-12-21 17:54:34.773255578 +0100
+@@ -55,7 +55,7 @@ def test_rfc822_datetime_formatters():
+ "Sat, 01 Jan 2011 23:59:59 -0000"),
+ (datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.utc),
+ "Sat, 01 Jan 2011 23:59:59 -0000"),
+- (datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone('CET')),
++ (pytz.timezone('CET').localize(datetime(2011, 1, 1, 23, 59, 59)),
+ "Sat, 01 Jan 2011 22:59:59 -0000")
+ ]
+ for date_obj, expected in dates:
+@@ -73,7 +73,7 @@ def test_iso8601_datetime_formatters():
+ "2011-01-01T23:59:59+00:00"),
+ (datetime(2011, 1, 1, 23, 59, 59, 1000, tzinfo=pytz.utc),
+ "2011-01-01T23:59:59.001000+00:00"),
+- (datetime(2011, 1, 1, 23, 59, 59, tzinfo=pytz.timezone('CET')),
++ (pytz.timezone('CET').localize(datetime(2011, 1, 1, 23, 59, 59)),
+ "2011-01-01T23:59:59+01:00")
+ ]
+ for date_obj, expected in dates:
+@@ -364,9 +364,9 @@ class FieldsTestCase(unittest.TestCase):
+ self.assertEqual("Mon, 22 Aug 2011 20:58:45 -0000", field.output("bar", obj))
+
+ def test_rfc822_date_field_with_offset(self):
+- obj = {"bar": datetime(2011, 8, 22, 20, 58, 45, tzinfo=pytz.timezone('CET'))}
++ obj = {"bar": pytz.timezone('CET').localize(datetime(2011, 8, 22, 20, 58, 45))}
+ field = fields.DateTime()
+- self.assertEqual("Mon, 22 Aug 2011 19:58:45 -0000", field.output("bar", obj))
++ self.assertEqual("Mon, 22 Aug 2011 18:58:45 -0000", field.output("bar", obj))
+
+ def test_iso8601_date_field_without_offset(self):
+ obj = {"bar": datetime(2011, 8, 22, 20, 58, 45)}
+@@ -374,9 +374,9 @@ class FieldsTestCase(unittest.TestCase):
+ self.assertEqual("2011-08-22T20:58:45", field.output("bar", obj))
+
+ def test_iso8601_date_field_with_offset(self):
+- obj = {"bar": datetime(2011, 8, 22, 20, 58, 45, tzinfo=pytz.timezone('CET'))}
++ obj = {"bar": pytz.timezone('CET').localize(datetime(2011, 8, 22, 20, 58, 45))}
+ field = fields.DateTime(dt_format='iso8601')
+- self.assertEqual("2011-08-22T20:58:45+01:00", field.output("bar", obj))
++ self.assertEqual("2011-08-22T20:58:45+02:00", field.output("bar", obj))
+
+ def test_unsupported_datetime_format(self):
+ obj = {"bar": datetime(2011, 8, 22, 20, 58, 45)}
diff --git a/Flask-RESTful-werkzeug-json.patch b/Flask-RESTful-werkzeug-json.patch
new file mode 100644
index 0000000..3052199
--- /dev/null
+++ b/Flask-RESTful-werkzeug-json.patch
@@ -0,0 +1,63 @@
+From 51a6373d95918bd55bfede7918a2b71d28a32ee2 Mon Sep 17 00:00:00 2001
+From: Mark Wine <marcoxwine at gmail.com>
+Date: Wed, 5 Jun 2024 21:27:32 -0700
+Subject: [PATCH] remove json parsing if content type is not application/json
+
+---
+ flask_restful/reqparse.py | 8 +++++++-
+ tests/test_reqparse.py | 16 ++++++++++++++++
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/flask_restful/reqparse.py b/flask_restful/reqparse.py
+index 9bb30991..121c7be6 100644
+--- a/flask_restful/reqparse.py
++++ b/flask_restful/reqparse.py
+@@ -113,6 +113,12 @@ def source(self, request):
+ """Pulls values off the request in the provided location
+ :param request: The flask request object to parse arguments from
+ """
++ location = self.location
++ if getattr(request, "content_type", "") != "application/json":
++ if self.location == "json":
++ return MultiDict()
++ elif "json" in self.location:
++ location = tuple(loc for loc in self.location if loc != 'json')
+ if isinstance(self.location, six.string_types):
+ value = getattr(request, self.location, MultiDict())
+ if callable(value):
+@@ -121,7 +127,7 @@ def source(self, request):
+ return value
+ else:
+ values = MultiDict()
+- for l in self.location:
++ for l in location:
+ value = getattr(request, l, None)
+ if callable(value):
+ value = value()
+diff --git a/tests/test_reqparse.py b/tests/test_reqparse.py
+index 1d75e404..762cff59 100644
+--- a/tests/test_reqparse.py
++++ b/tests/test_reqparse.py
+@@ -811,6 +811,22 @@ def test_not_json_location_and_content_type_json(self):
+ content_type='application/json'):
+ parser.parse_args() # Should not raise a 400: BadRequest
+
++ def test_content_type_not_json(self):
++ app = Flask(__name__)
++
++ parser = RequestParser()
++ parser.add_argument("foo")
++
++ with app.test_request_context("/bubble", method="get", data=json.dumps({"foo": "bar"})):
++ args = parser.parse_args()
++ self.assertIsNone(args.get("foo"))
++
++ with app.test_request_context("/bubble", method="get",
++ content_type="application/json",
++ data=json.dumps({"foo": "bar"})):
++ args = parser.parse_args()
++ self.assertEqual(args["foo"], "bar")
++
+ def test_request_parser_remove_argument(self):
+ req = Request.from_values("/bubble?foo=baz")
+ parser = RequestParser()
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/python-flask-restful.git/commitdiff/07408285ee9e6644637eac91bd022ec36f76793a
More information about the pld-cvs-commit
mailing list