From c784c6937df936fc35c40709d42b679efcd9d4a3 Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Mon, 16 Oct 2023 15:50:49 -0400 Subject: [PATCH] python3-Flask-Login: patch for Flask and Werzeug 3 --- .../patches/00.flask-3.0.patch | 46 +++ .../patches/01.flask-3.0.patch | 317 ++++++++++++++++++ srcpkgs/python3-Flask-Login/template | 5 +- 3 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 srcpkgs/python3-Flask-Login/patches/00.flask-3.0.patch create mode 100644 srcpkgs/python3-Flask-Login/patches/01.flask-3.0.patch diff --git a/srcpkgs/python3-Flask-Login/patches/00.flask-3.0.patch b/srcpkgs/python3-Flask-Login/patches/00.flask-3.0.patch new file mode 100644 index 00000000000..9c445f769c4 --- /dev/null +++ b/srcpkgs/python3-Flask-Login/patches/00.flask-3.0.patch @@ -0,0 +1,46 @@ +From 7b170bf4e5e0240fe084166c9ca6ec4fba258dcd Mon Sep 17 00:00:00 2001 +From: Hiromasa Ihara +Date: Mon, 2 Oct 2023 20:14:40 +0900 +Subject: [PATCH] fix: avoid DeprecationWarning 'werkzeug.urls.url_decode' is + deprecated (#746) + +--- + src/flask_login/utils.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/flask_login/utils.py b/src/flask_login/utils.py +index c3c46846..45a7e279 100644 +--- a/src/flask_login/utils.py ++++ b/src/flask_login/utils.py +@@ -3,6 +3,8 @@ + from hashlib import sha512 + from urllib.parse import urlparse + from urllib.parse import urlunparse ++from urllib.parse import parse_qs ++from urllib.parse import urlencode + + from flask import current_app + from flask import g +@@ -11,8 +13,6 @@ + from flask import session + from flask import url_for + from werkzeug.local import LocalProxy +-from werkzeug.urls import url_decode +-from werkzeug.urls import url_encode + + from .config import COOKIE_NAME + from .config import EXEMPT_METHODS +@@ -123,11 +123,11 @@ def login_url(login_view, next_url=None, next_field="next"): + return base + + parsed_result = urlparse(base) +- md = url_decode(parsed_result.query) ++ md = parse_qs(parsed_result.query) + md[next_field] = make_next_param(base, next_url) + netloc = current_app.config.get("FORCE_HOST_FOR_REDIRECTS") or parsed_result.netloc + parsed_result = parsed_result._replace( +- netloc=netloc, query=url_encode(md, sort=True) ++ netloc=netloc, query=urlencode(md, doseq=True) + ) + return urlunparse(parsed_result) + diff --git a/srcpkgs/python3-Flask-Login/patches/01.flask-3.0.patch b/srcpkgs/python3-Flask-Login/patches/01.flask-3.0.patch new file mode 100644 index 00000000000..d2bc4858207 --- /dev/null +++ b/srcpkgs/python3-Flask-Login/patches/01.flask-3.0.patch @@ -0,0 +1,317 @@ +From 7d98a49bc38d0849367b348bfe37a2b689323419 Mon Sep 17 00:00:00 2001 +From: Sha +Date: Mon, 2 Oct 2023 07:00:12 -0500 +Subject: [PATCH] flask 3.0 compatibility (#778) + +* Werkzeug 3.0 compatible + +* python3.7 compatibility + +* troubleshooting version compatibility + +* update constrain + +* package version troubleshooting + +* troubleshooting package version + +* troubleshoot package version + +* package tuning + +* troubleshoot package version + +* troubleshooting package version + +* troubleshoot test cases + +* troubleshoot python package version + +* Update tox.ini + +* version troubleshoot + +* version fix + +* package version + +* package version + +* Update setup.py + +* Update setup.py + +* package version + +* package version + +* package version + +* Update setup.cfg + +* version fix + +* package version + +* package version + +* package version + +* package version + +* deprecate python3.7 + +* package version + +* merge conflicts + +* pylint fix +--- + .github/workflows/tests.yaml | 4 +- + requirements/ci-release.txt | 83 +++++++++------------ + requirements/ci-tests.in | 5 +- + requirements/ci-tests.txt | 61 +++++++++------- + requirements/dev.txt | 138 ++++++----------------------------- + requirements/docs.txt | 50 +++++++------ + requirements/style.txt | 25 +++---- + requirements/tests-min.in | 8 +- + requirements/tests-min.txt | 34 ++++----- + requirements/tests.in | 6 +- + requirements/tests.txt | 28 +++---- + setup.cfg | 2 +- + setup.py | 5 +- + src/flask_login/utils.py | 4 +- + tests/test_login.py | 26 ++++--- + tox.ini | 2 +- + 16 files changed, 198 insertions(+), 283 deletions(-) + +diff --git a/src/flask_login/utils.py b/src/flask_login/utils.py +index 45a7e279..0fde23f4 100644 +--- a/src/flask_login/utils.py ++++ b/src/flask_login/utils.py +@@ -1,10 +1,10 @@ + import hmac + from functools import wraps + from hashlib import sha512 +-from urllib.parse import urlparse +-from urllib.parse import urlunparse + from urllib.parse import parse_qs + from urllib.parse import urlencode ++from urllib.parse import urlparse ++from urllib.parse import urlunparse + + from flask import current_app + from flask import g +diff --git a/tests/test_login.py b/tests/test_login.py +--- a/tests/test_login.py ++++ b/tests/test_login.py +@@ -328,7 +328,7 @@ + def empty_session(): + return f"modified={session.modified}" + +- # This will help us with the possibility of typoes in the tests. Now ++ # This will help us with the possibility of typos in the tests. Now + # we shouldn't have to check each response to help us set up state + # (such as login pages) to make sure it worked: we will always + # get an exception raised (rather than return a 404 response) +@@ -669,24 +669,17 @@ + name = self.app.config["REMEMBER_COOKIE_NAME"] = "myname" + duration = self.app.config["REMEMBER_COOKIE_DURATION"] = timedelta(days=2) + path = self.app.config["REMEMBER_COOKIE_PATH"] = "/mypath" +- domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = ".localhost.local" ++ domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = "localhost.local" + + with self.app.test_client() as c: + c.get("/login-notch-remember") + +- # TODO: Is there a better way to test this? +- self.assertIn( +- domain, +- c.cookie_jar._cookies, +- "Custom domain not found as cookie domain", ++ cookie = c.get_cookie(key=name, domain=domain, path=path) ++ self.assertIsNotNone( ++ cookie, "Custom domain, path and name not found in cookies" + ) +- domain_cookie = c.cookie_jar._cookies[domain] +- self.assertIn(path, domain_cookie, "Custom path not found as cookie path") +- path_cookie = domain_cookie[path] +- self.assertIn(name, path_cookie, "Custom name not found as cookie name") +- cookie = path_cookie[name] + +- expiration_date = datetime.utcfromtimestamp(cookie.expires) ++ expiration_date = datetime.utcfromtimestamp(cookie.expires.timestamp()) + expected_date = datetime.utcnow() + duration + difference = expected_date - expiration_date + +@@ -702,24 +695,17 @@ + self.app.config["REMEMBER_COOKIE_DURATION"] = 172800 + duration = timedelta(hours=7) + path = self.app.config["REMEMBER_COOKIE_PATH"] = "/mypath" +- domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = ".localhost.local" ++ domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = "localhost.local" + + with self.app.test_client() as c: + c.get("/login-notch-remember-custom") + +- # TODO: Is there a better way to test this? +- self.assertIn( +- domain, +- c.cookie_jar._cookies, +- "Custom domain not found as cookie domain", ++ cookie = c.get_cookie(key=name, domain=domain, path=path) ++ self.assertIsNotNone( ++ cookie, "Custom domain, path and name not found in cookies" + ) +- domain_cookie = c.cookie_jar._cookies[domain] +- self.assertIn(path, domain_cookie, "Custom path not found as cookie path") +- path_cookie = domain_cookie[path] +- self.assertIn(name, path_cookie, "Custom name not found as cookie name") +- cookie = path_cookie[name] + +- expiration_date = datetime.utcfromtimestamp(cookie.expires) ++ expiration_date = datetime.utcfromtimestamp(cookie.expires.timestamp()) + expected_date = datetime.utcnow() + duration + difference = expected_date - expiration_date + +@@ -734,15 +720,15 @@ + self.app.config["REMEMBER_COOKIE_DURATION"] = 172800 + duration = timedelta(seconds=172800) + name = self.app.config["REMEMBER_COOKIE_NAME"] = "myname" +- domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = ".localhost.local" ++ domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = "localhost.local" + + with self.app.test_client() as c: + result = c.get("/login-notch-remember") + self.assertEqual(result.status_code, 200) + +- cookie = c.cookie_jar._cookies[domain]["/"][name] ++ cookie = c.get_cookie(key=name, domain=domain, path="/") + +- expiration_date = datetime.utcfromtimestamp(cookie.expires) ++ expiration_date = datetime.utcfromtimestamp(cookie.expires.timestamp()) + expected_date = datetime.utcnow() + duration + difference = expected_date - expiration_date + +@@ -794,25 +780,22 @@ + self.assertIn(expected_exception_message, str(cm.exception)) + + def test_remember_me_refresh_every_request(self): +- domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = ".localhost.local" ++ domain = self.app.config["REMEMBER_COOKIE_DOMAIN"] = "localhost.local" + path = self.app.config["REMEMBER_COOKIE_PATH"] = "/" + + # No refresh + self.app.config["REMEMBER_COOKIE_REFRESH_EACH_REQUEST"] = False + with self.app.test_client() as c: + c.get("/login-notch-remember") +- self.assertIn("remember", c.cookie_jar._cookies[domain][path]) +- expiration_date_1 = datetime.utcfromtimestamp( +- c.cookie_jar._cookies[domain][path]["remember"].expires +- ) +- +- self._delete_session(c) ++ cookie = c.get_cookie(key="remember", domain=domain, path=path) ++ self.assertIsNotNone(cookie) ++ expiration_date_1 = datetime.utcfromtimestamp(cookie.expires.timestamp()) + ++ # self._delete_session(c) + c.get("/username") +- self.assertIn("remember", c.cookie_jar._cookies[domain][path]) +- expiration_date_2 = datetime.utcfromtimestamp( +- c.cookie_jar._cookies[domain][path]["remember"].expires +- ) ++ cookie = c.get_cookie(key="remember", domain=domain, path=path) ++ self.assertIsNotNone(cookie) ++ expiration_date_2 = datetime.utcfromtimestamp(cookie.expires.timestamp()) + self.assertEqual(expiration_date_1, expiration_date_2) + + # With refresh (mock datetime's `utcnow`) +@@ -820,22 +803,24 @@ + self.app.config["REMEMBER_COOKIE_REFRESH_EACH_REQUEST"] = True + now = datetime.utcnow() + mock_dt.utcnow = Mock(return_value=now) +- ++ mock_utcnow1 = mock_dt.utcnow + with self.app.test_client() as c: + c.get("/login-notch-remember") +- self.assertIn("remember", c.cookie_jar._cookies[domain][path]) ++ cookie = c.get_cookie(key="remember", domain=domain, path=path) + expiration_date_1 = datetime.utcfromtimestamp( +- c.cookie_jar._cookies[domain][path]["remember"].expires ++ cookie.expires.timestamp() + ) + self.assertIsNotNone(expiration_date_1) + +- self._delete_session(c) ++ # self._delete_session(c) + + mock_dt.utcnow = Mock(return_value=now + timedelta(seconds=1)) ++ mock_utcnow2 = mock_dt.utcnow ++ self.assertNotEqual(mock_utcnow1, mock_utcnow2) + c.get("/username") +- self.assertIn("remember", c.cookie_jar._cookies[domain][path]) ++ cookie = c.get_cookie(key="remember", domain=domain, path=path) + expiration_date_2 = datetime.utcfromtimestamp( +- c.cookie_jar._cookies[domain][path]["remember"].expires ++ cookie.expires.timestamp() + ) + self.assertIsNotNone(expiration_date_2) + self.assertNotEqual(expiration_date_1, expiration_date_2) +@@ -1016,7 +1001,7 @@ + c.get("/login-notch-remember") + with c.session_transaction() as sess: + sess["_user_id"] = None +- c.set_cookie(domain, self.remember_cookie_name, "foo") ++ c.set_cookie(self.remember_cookie_name, "foo", domain=domain) + result = c.get("/username") + self.assertEqual("Anonymous", result.data.decode("utf-8")) + +@@ -1315,7 +1300,7 @@ + pass + return USERS.get(user_id) + +- # This will help us with the possibility of typoes in the tests. Now ++ # This will help us with the possibility of typos in the tests. Now + # we shouldn't have to check each response to help us set up state + # (such as login pages) to make sure it worked: we will always + # get an exception raised (rather than return a 404 response) +@@ -1426,9 +1411,10 @@ + result = login_url("https://auth.localhost/login", PROTECTED) + self.assertEqual(expected, result) + ++ url = login_url("/login?affil=cgnu", PROTECTED) + self.assertEqual( + "/login?affil=cgnu&next=%2Fprotected", +- login_url("/login?affil=cgnu", PROTECTED), ++ url, + ) + + def test_login_url_generation_with_view(self): +@@ -1590,7 +1576,7 @@ + def load_user(user_id): + return USERS[str(user_id)] + +- # This will help us with the possibility of typoes in the tests. Now ++ # This will help us with the possibility of typos in the tests. Now + # we shouldn't have to check each response to help us set up state + # (such as login pages) to make sure it worked: we will always + # get an exception raised (rather than return a 404 response) +@@ -1646,7 +1632,7 @@ + def load_user(user_id): + return USERS[str(user_id)] + +- # This will help us with the possibility of typoes in the tests. Now ++ # This will help us with the possibility of typos in the tests. Now + # we shouldn't have to check each response to help us set up state + # (such as login pages) to make sure it worked: we will always + # get an exception raised (rather than return a 404 response) +@@ -1742,7 +1728,7 @@ + def load_user(user_id): + return USERS[int(user_id)] + +- # This will help us with the possibility of typoes in the tests. Now ++ # This will help us with the possibility of typos in the tests. Now + # we shouldn't have to check each response to help us set up state + # (such as login pages) to make sure it worked: we will always + # get an exception raised (rather than return a 404 response) diff --git a/srcpkgs/python3-Flask-Login/template b/srcpkgs/python3-Flask-Login/template index 1e1989fcbb7..c1b662043f4 100644 --- a/srcpkgs/python3-Flask-Login/template +++ b/srcpkgs/python3-Flask-Login/template @@ -1,11 +1,12 @@ # Template file for 'python3-Flask-Login' pkgname=python3-Flask-Login version=0.6.2 -revision=3 +revision=4 build_style=python3-module +make_check_args="-p no:warnings" hostmakedepends="python3-setuptools" depends="python3-Flask" -checkdepends="python3-Werkzeug python3-Flask" +checkdepends="python3-semanticversion python3-pytest python3-asgiref $depends" short_desc="User session management for Flask (Python3)" maintainer="pulux " license="MIT"