Repository: marshmallow-code/flask-marshmallow

Issue:
DeprecationWarning from Flask-SQLAlchemy for app.extensions["sqlalchemy"]
Flask-SQLAlchemy has rewritten the way to load the extension. No longer `app.extensions["sqlalchemy"].db` but simply `app.extensions["sqlalchemy"]` see https://github.com/pallets-eco/flask-sqlalchemy/issues/698.

This is used here: https://github.com/marshmallow-code/flask-marshmallow/blob/13f673979937bc5b366863eeff4eefadfb8433d1/src/flask_marshmallow/__init__.py#L114

This is a breaking change and would require to also pin Flask-SQLAlchemy to `>3.0` in https://github.com/marshmallow-code/flask-marshmallow/blob/13f673979937bc5b366863eeff4eefadfb8433d1/setup.py#L7

Discussion:

Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 95aebfa..103c30d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -3,9 +3,9 @@ repos:
   rev: v2.31.0
   hooks:
   - id: pyupgrade
-    args: [--py36-plus]
+    args: [--py37-plus]
 - repo: https://github.com/python/black
-  rev: 22.1.0
+  rev: 22.3.0
   hooks:
   - id: black
     language_version: python3
@@ -13,9 +13,9 @@ repos:
   rev: 3.9.2
   hooks:
   - id: flake8
-    additional_dependencies: [flake8-bugbear==22.1.11]
+    additional_dependencies: [flake8-bugbear==22.1.11, importlib-metadata==4.12.0]
 - repo: https://github.com/asottile/blacken-docs
   rev: v1.12.1
   hooks:
   - id: blacken-docs
-    additional_dependencies: [black==22.1.0]
+    additional_dependencies: [black==22.3.0]
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 6412833..b766d1c 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -27,10 +27,10 @@ jobs:
     toxenvs:
       - lint
 
-      - py36-marshmallow3
       - py37-marshmallow3
       - py38-marshmallow3
       - py39-marshmallow3
+      - py310-marshmallow3
 
       - py39-lowest
       - py39-marshmallowdev
diff --git a/setup.py b/setup.py
index 49c56dc..fd39157 100644
--- a/setup.py
+++ b/setup.py
@@ -4,10 +4,10 @@ from setuptools import setup, find_packages
 
 EXTRAS_REQUIRE = {
     "sqlalchemy": [
-        "flask-sqlalchemy",
+        "flask-sqlalchemy>=3.0.0",
         "marshmallow-sqlalchemy>=0.24.0",
     ],
-    "docs": ["marshmallow-sqlalchemy>=0.13.0", "Sphinx==3.5.4", "sphinx-issues==1.2.0"],
+    "docs": ["marshmallow-sqlalchemy>=0.13.0", "Sphinx==4.5.0", "sphinx-issues==3.0.1"],
     "lint": [
         "flake8==3.9.2",
         "flake8-bugbear==20.11.1",
@@ -59,7 +59,7 @@ setup(
     license="MIT",
     zip_safe=False,
     keywords="flask-marshmallow",
-    python_requires=">=3.6",
+    python_requires=">=3.7",
     classifiers=[
         "Development Status :: 4 - Beta",
         "Environment :: Web Environment",
diff --git a/src/flask_marshmallow/__init__.py b/src/flask_marshmallow/__init__.py
index a0f0f1c..a3afa4d 100755
--- a/src/flask_marshmallow/__init__.py
+++ b/src/flask_marshmallow/__init__.py
@@ -111,7 +111,7 @@ class Marshmallow:
 
         # If using Flask-SQLAlchemy, attach db.session to SQLAlchemySchema
         if has_sqla and "sqlalchemy" in app.extensions:
-            db = app.extensions["sqlalchemy"].db
+            db = app.extensions["sqlalchemy"]
             if self.SQLAlchemySchema:
                 self.SQLAlchemySchema.OPTIONS_CLASS.session = db.session
             if self.SQLAlchemyAutoSchema:
diff --git a/tox.ini b/tox.ini
index 24608a1..d91a53f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
 [tox]
 envlist=
     lint
-    py{36,37,38,39}-marshmallow3
+    py{37,38,39,310}-marshmallow3
     py39-lowest
     py39-marshmallowdev
     docs


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
index 0dfebd9..f74d30e 100755
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1,7 +1,7 @@
 import json
 
 from flask import Flask, url_for
-from werkzeug.wrappers import BaseResponse
+from werkzeug.wrappers import Response
 
 from flask_marshmallow import Marshmallow
 from tests.markers import flask_1_req
@@ -29,7 +29,7 @@ def test_schema(app, schemas, mockauthor):
 def test_jsonify_instance(app, schemas, mockauthor):
     s = schemas.AuthorSchema()
     resp = s.jsonify(mockauthor)
-    assert isinstance(resp, BaseResponse)
+    assert isinstance(resp, Response)
     assert resp.content_type == "application/json"
     obj = json.loads(resp.get_data(as_text=True))
     assert isinstance(obj, dict)
@@ -39,7 +39,7 @@ def test_jsonify_instance(app, schemas, mockauthor):
 def test_jsonify_collection(app, schemas, mockauthorlist):
     s = schemas.AuthorSchema()
     resp = s.jsonify(mockauthorlist, many=True)
-    assert isinstance(resp, BaseResponse)
+    assert isinstance(resp, Response)
     assert resp.content_type == "application/json"
     obj = json.loads(resp.get_data(as_text=True))
     assert isinstance(obj, list)
@@ -49,7 +49,7 @@ def test_jsonify_collection(app, schemas, mockauthorlist):
 def test_jsonify_collection_via_schema_attr(app, schemas, mockauthorlist):
     s = schemas.AuthorSchema(many=True)
     resp = s.jsonify(mockauthorlist)
-    assert isinstance(resp, BaseResponse)
+    assert isinstance(resp, Response)
     assert resp.content_type == "application/json"
     obj = json.loads(resp.get_data(as_text=True))
     assert isinstance(obj, list)
diff --git a/tests/test_sqla.py b/tests/test_sqla.py
index 2bf138f..5f11e4e 100644
--- a/tests/test_sqla.py
+++ b/tests/test_sqla.py
@@ -1,7 +1,7 @@
 import pytest
 from flask import Flask, url_for
 from flask_sqlalchemy import SQLAlchemy
-from werkzeug.wrappers import BaseResponse
+from werkzeug.wrappers import Response
 
 from flask_marshmallow import Marshmallow
 from flask_marshmallow.sqla import HyperlinkRelated
@@ -130,7 +130,7 @@ class TestSQLAlchemy:
         assert book_result["author_id"] == book.author_id
 
         resp = author_schema.jsonify(author)
-        assert isinstance(resp, BaseResponse)
+        assert isinstance(resp, Response)
 
     @requires_sqlalchemyschema
     def test_can_declare_sqla_auto_schemas(self, extma, models, db):
@@ -168,7 +168,7 @@ class TestSQLAlchemy:
         assert book_result["author_id"] == book.author_id
 
         resp = author_schema.jsonify(author)
-        assert isinstance(resp, BaseResponse)
+        assert isinstance(resp, Response)
 
     @requires_sqlalchemyschema
     def test_hyperlink_related_field(self, extma, models, db, extapp):