flask-marshmallow 0.15.0__tar.gz → 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/CHANGELOG.rst +32 -5
  2. {flask-marshmallow-0.15.0/src/flask_marshmallow.egg-info → flask_marshmallow-1.0.0}/PKG-INFO +26 -21
  3. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/README.rst +4 -8
  4. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_templates/side-primary.html +1 -1
  5. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_templates/side-secondary.html +1 -1
  6. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/conf.py +3 -5
  7. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/index.rst +5 -1
  8. flask_marshmallow-1.0.0/pyproject.toml +66 -0
  9. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/src/flask_marshmallow/__init__.py +17 -10
  10. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/src/flask_marshmallow/fields.py +76 -9
  11. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/src/flask_marshmallow/schema.py +0 -1
  12. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/src/flask_marshmallow/sqla.py +2 -1
  13. flask_marshmallow-1.0.0/src/flask_marshmallow/validate.py +183 -0
  14. flask_marshmallow-1.0.0/tests/conftest.py +112 -0
  15. flask_marshmallow-1.0.0/tests/markers.py +9 -0
  16. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/tests/test_fields.py +32 -2
  17. flask_marshmallow-1.0.0/tests/test_io.py +0 -0
  18. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/tests/test_sqla.py +4 -6
  19. flask_marshmallow-1.0.0/tests/test_validate.py +107 -0
  20. flask_marshmallow-1.0.0/tox.ini +40 -0
  21. flask-marshmallow-0.15.0/MANIFEST.in +0 -5
  22. flask-marshmallow-0.15.0/PKG-INFO +0 -166
  23. flask-marshmallow-0.15.0/setup.cfg +0 -19
  24. flask-marshmallow-0.15.0/setup.py +0 -77
  25. flask-marshmallow-0.15.0/src/flask_marshmallow/compat.py +0 -9
  26. flask-marshmallow-0.15.0/src/flask_marshmallow.egg-info/SOURCES.txt +0 -41
  27. flask-marshmallow-0.15.0/src/flask_marshmallow.egg-info/dependency_links.txt +0 -1
  28. flask-marshmallow-0.15.0/src/flask_marshmallow.egg-info/not-zip-safe +0 -1
  29. flask-marshmallow-0.15.0/src/flask_marshmallow.egg-info/requires.txt +0 -26
  30. flask-marshmallow-0.15.0/src/flask_marshmallow.egg-info/top_level.txt +0 -1
  31. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/CONTRIBUTING.rst +0 -0
  32. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/LICENSE +0 -0
  33. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/Makefile +0 -0
  34. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_static/logo.png +0 -0
  35. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/LICENSE +0 -0
  36. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/README +0 -0
  37. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask/layout.html +0 -0
  38. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask/relations.html +0 -0
  39. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask/static/flasky.css_t +0 -0
  40. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask/theme.conf +0 -0
  41. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask_small/layout.html +0 -0
  42. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask_small/static/flasky.css_t +0 -0
  43. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask_small/theme.conf +0 -0
  44. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/_themes/flask_theme_support.py +7 -7
  45. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/changelog.rst +0 -0
  46. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/license.rst +0 -0
  47. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/docs/make.bat +0 -0
  48. /flask-marshmallow-0.15.0/tests/test_io.py → /flask_marshmallow-1.0.0/tests/__init__.py +0 -0
  49. {flask-marshmallow-0.15.0 → flask_marshmallow-1.0.0}/tests/test_core.py +0 -0
@@ -1,12 +1,39 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 1.0.0 (2024-01-16)
5
+ ******************
6
+
7
+ Features:
8
+
9
+ * Add field ``fields.File``, ``validate.FileType``, and ``validate.FileSize``
10
+ for deserializing uploaded files (:issue:`280`, :pr:`282`).
11
+ Thanks :user:`uncle-lv` for the PR
12
+ * Add field ``Config`` for serializing Flask configuration values (:issue:`280`, :pr:`281`).
13
+ Thanks :user:`greyli` for the PR.
14
+
15
+ Support:
16
+
17
+ * Support marshmallow-sqlalchemy>=0.29.0.
18
+ * Test against Python 3.12.
19
+ * Drop support for Python 3.7.
20
+
21
+ Other changes:
22
+
23
+ * *Backwards-incompatible*: Remove ```flask_marshmallow.__version__``
24
+ and ``flask_marshmallow.__version_info__`` attributes (:pr:`284`).
25
+ Use feature detection or ``importlib.metadata.version("flask-marshmallow")`` instead.
26
+
4
27
  0.15.0 (2023-04-05)
5
28
  *******************
6
29
 
7
- * Only support Python>=3.6, marshmallow>=3.0.0, and
8
- marshmallow-sqlalchemy>=0.28.2
9
- * Add support for python3.11
30
+ * Changes to supported software versions.
31
+
32
+ * python3.6 or later and marshmallow>=3.0.0 are now required
33
+ * Add support for python3.11
34
+ * For ``sqlalchemy`` integration, marshmallow-sqlalchemy>=0.28.2 and
35
+ flask-sqlalchemy>=3.0.0 are now required
36
+
10
37
  * *Backwards-incompatible*: ``URLFor`` and ``AbsoluteURLFor`` now do not accept
11
38
  parameters for ``flask.url_for`` as top-level parameters. They must always be
12
39
  passed in the ``values`` dictionary, as explained in the v0.14.0 changelog.
@@ -20,8 +47,8 @@ Bug fixes:
20
47
  *******************
21
48
 
22
49
  * Add ``values`` argument to ``URLFor`` and ``AbsoluteURLFor`` for passing values to ``flask.url_for``.
23
- This prevents unrelated parameters from getting passed (:issue:`52`, :issue:`67`).
24
- Thanks :user:`AlrasheedA` for the PR.
50
+ This prevents unrelated parameters from getting passed (:issue:`52`, :issue:`67`).
51
+ Thanks :user:`AlrasheedA` for the PR.
25
52
 
26
53
  Deprecation:
27
54
 
@@ -1,38 +1,46 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flask-marshmallow
3
- Version: 0.15.0
3
+ Version: 1.0.0
4
4
  Summary: Flask + marshmallow for beautiful APIs
5
- Home-page: https://github.com/marshmallow-code/flask-marshmallow
6
- Author: Steven Loria
7
- Author-email: sloria1@gmail.com
8
- License: MIT
9
- Project-URL: Issues, https://github.com/marshmallow-code/flask-marshmallow/issues
10
- Project-URL: Funding, https://opencollective.com/marshmallow
11
- Keywords: flask-marshmallow
12
- Classifier: Development Status :: 4 - Beta
5
+ Maintainer-email: Steven Loria <sloria1@gmail.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/x-rst
13
8
  Classifier: Environment :: Web Environment
14
9
  Classifier: Intended Audience :: Developers
15
10
  Classifier: License :: OSI Approved :: MIT License
16
11
  Classifier: Natural Language :: English
17
12
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.7
19
13
  Classifier: Programming Language :: Python :: 3.8
20
14
  Classifier: Programming Language :: Python :: 3.9
21
15
  Classifier: Programming Language :: Python :: 3.10
22
16
  Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
23
18
  Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
24
- Requires-Python: >=3.7
25
- Provides-Extra: sqlalchemy
19
+ Requires-Dist: Flask
20
+ Requires-Dist: marshmallow>=3.0.0
21
+ Requires-Dist: packaging>=17.0
22
+ Requires-Dist: flask-marshmallow[tests] ; extra == "dev"
23
+ Requires-Dist: tox ; extra == "dev"
24
+ Requires-Dist: pre-commit~=3.5 ; extra == "dev"
25
+ Requires-Dist: marshmallow-sqlalchemy>=0.19.0 ; extra == "docs"
26
+ Requires-Dist: Sphinx==7.2.6 ; extra == "docs"
27
+ Requires-Dist: sphinx-issues==3.0.1 ; extra == "docs"
28
+ Requires-Dist: flask-sqlalchemy>=3.0.0 ; extra == "sqlalchemy"
29
+ Requires-Dist: marshmallow-sqlalchemy>=0.29.0 ; extra == "sqlalchemy"
30
+ Requires-Dist: flask-marshmallow[sqlalchemy] ; extra == "tests"
31
+ Requires-Dist: pytest ; extra == "tests"
32
+ Project-URL: Funding, https://opencollective.com/marshmallow
33
+ Project-URL: Issues, https://github.com/marshmallow-code/flask-marshmallow/issues
34
+ Provides-Extra: dev
26
35
  Provides-Extra: docs
36
+ Provides-Extra: sqlalchemy
27
37
  Provides-Extra: tests
28
- Provides-Extra: dev
29
- License-File: LICENSE
30
38
 
31
39
  *****************
32
40
  Flask-Marshmallow
33
41
  *****************
34
42
 
35
- |pypi-package| |build-status| |docs| |marshmallow3| |black|
43
+ |pypi-package| |build-status| |docs| |marshmallow3|
36
44
 
37
45
  Flask + marshmallow for beautiful APIs
38
46
  ======================================
@@ -133,7 +141,7 @@ Project Links
133
141
 
134
142
  - Docs: https://flask-marshmallow.readthedocs.io/
135
143
  - Changelog: http://flask-marshmallow.readthedocs.io/en/latest/changelog.html
136
- - PyPI: https://pypi.python.org/pypi/flask-marshmallow
144
+ - PyPI: https://pypi.org/project/flask-marshmallow/
137
145
  - Issues: https://github.com/marshmallow-code/flask-marshmallow/issues
138
146
 
139
147
  License
@@ -149,8 +157,8 @@ MIT licensed. See the bundled `LICENSE <https://github.com/marshmallow-code/flas
149
157
  :target: https://pypi.org/project/flask-marshmallow/
150
158
  :alt: Latest version
151
159
 
152
- .. |build-status| image:: https://github.com/marshmallow-code/flask-marshmallow/workflows/build/badge.svg?event=push
153
- :target: https://github.com/marshmallow-code/flask-marshmallow/actions?query=workflow%3Abuild
160
+ .. |build-status| image:: https://github.com/marshmallow-code/flask-marshmallow/actions/workflows/build-release.yml/badge.svg
161
+ :target: https://github.com/marshmallow-code/flask-marshmallow/actions/workflows/build-release.yml
154
162
  :alt: Build status
155
163
 
156
164
  .. |docs| image:: https://readthedocs.org/projects/flask-marshmallow/badge/
@@ -161,6 +169,3 @@ MIT licensed. See the bundled `LICENSE <https://github.com/marshmallow-code/flas
161
169
  :target: https://marshmallow.readthedocs.io/en/latest/upgrading.html
162
170
  :alt: marshmallow 3 compatible
163
171
 
164
- .. |black| image:: https://badgen.net/badge/code%20style/black/000
165
- :target: https://github.com/ambv/black
166
- :alt: code style: black
@@ -2,7 +2,7 @@
2
2
  Flask-Marshmallow
3
3
  *****************
4
4
 
5
- |pypi-package| |build-status| |docs| |marshmallow3| |black|
5
+ |pypi-package| |build-status| |docs| |marshmallow3|
6
6
 
7
7
  Flask + marshmallow for beautiful APIs
8
8
  ======================================
@@ -103,7 +103,7 @@ Project Links
103
103
 
104
104
  - Docs: https://flask-marshmallow.readthedocs.io/
105
105
  - Changelog: http://flask-marshmallow.readthedocs.io/en/latest/changelog.html
106
- - PyPI: https://pypi.python.org/pypi/flask-marshmallow
106
+ - PyPI: https://pypi.org/project/flask-marshmallow/
107
107
  - Issues: https://github.com/marshmallow-code/flask-marshmallow/issues
108
108
 
109
109
  License
@@ -119,8 +119,8 @@ MIT licensed. See the bundled `LICENSE <https://github.com/marshmallow-code/flas
119
119
  :target: https://pypi.org/project/flask-marshmallow/
120
120
  :alt: Latest version
121
121
 
122
- .. |build-status| image:: https://github.com/marshmallow-code/flask-marshmallow/workflows/build/badge.svg?event=push
123
- :target: https://github.com/marshmallow-code/flask-marshmallow/actions?query=workflow%3Abuild
122
+ .. |build-status| image:: https://github.com/marshmallow-code/flask-marshmallow/actions/workflows/build-release.yml/badge.svg
123
+ :target: https://github.com/marshmallow-code/flask-marshmallow/actions/workflows/build-release.yml
124
124
  :alt: Build status
125
125
 
126
126
  .. |docs| image:: https://readthedocs.org/projects/flask-marshmallow/badge/
@@ -130,7 +130,3 @@ MIT licensed. See the bundled `LICENSE <https://github.com/marshmallow-code/flas
130
130
  .. |marshmallow3| image:: https://badgen.net/badge/marshmallow/3
131
131
  :target: https://marshmallow.readthedocs.io/en/latest/upgrading.html
132
132
  :alt: marshmallow 3 compatible
133
-
134
- .. |black| image:: https://badgen.net/badge/code%20style/black/000
135
- :target: https://github.com/ambv/black
136
- :alt: code style: black
@@ -14,7 +14,7 @@ Flask + marshmallow for beautiful APIs
14
14
 
15
15
  <h3>Useful Links</h3>
16
16
  <ul>
17
- <li><a href="http://pypi.python.org/pypi/flask-marshmallow">Flask-Marshmallow @ PyPI</a></li>
17
+ <li><a href="https://pypi.org/project/flask-marshmallow/">Flask-Marshmallow @ PyPI</a></li>
18
18
  <li><a href="http://github.com/marshmallow-code/flask-marshmallow">Flask-Marshmallow @ GitHub</a></li>
19
19
  <li><a href="http://github.com/marshmallow-code/flask-marshmallow/issues">Issue Tracker</a></li>
20
20
  </ul>
@@ -18,7 +18,7 @@ Flask + marshmallow for beautiful APIs
18
18
 
19
19
  <h3>Useful Links</h3>
20
20
  <ul>
21
- <li><a href="http://pypi.python.org/pypi/flask-marshmallow">Flask-Marshmallow @ PyPI</a></li>
21
+ <li><a href="https://pypi.org/project/flask-marshmallow/">Flask-Marshmallow @ PyPI</a></li>
22
22
  <li><a href="http://github.com/marshmallow-code/flask-marshmallow">Flask-Marshmallow @ GitHub</a></li>
23
23
  <li><a href="http://github.com/marshmallow-code/flask-marshmallow/issues">Issue Tracker</a></li>
24
24
  </ul>
@@ -1,9 +1,7 @@
1
1
  import datetime as dt
2
- import sys
2
+ import importlib.metadata
3
3
  import os
4
-
5
- sys.path.insert(0, os.path.abspath(os.path.join("..", "src")))
6
- import flask_marshmallow # noqa: E402
4
+ import sys
7
5
 
8
6
  sys.path.append(os.path.abspath("_themes"))
9
7
  extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx_issues"]
@@ -39,7 +37,7 @@ copyright = "2014-{:%Y}".format(
39
37
  )
40
38
 
41
39
 
42
- version = release = flask_marshmallow.__version__
40
+ version = release = importlib.metadata.version("flask-marshmallow")
43
41
  exclude_patterns = ["_build"]
44
42
  # The name of the Pygments (syntax highlighting) style to use.
45
43
  pygments_style = "flask_theme_support.FlaskyStyle"
@@ -4,7 +4,7 @@ Flask-Marshmallow: Flask + marshmallow for beautiful APIs
4
4
 
5
5
  :ref:`changelog <changelog>` //
6
6
  `github <http://github.com/marshmallow-code/flask-marshmallow>`_ //
7
- `pypi <http://pypi.python.org/pypi/flask-marshmallow>`_ //
7
+ `pypi <https://pypi.org/project/flask-marshmallow/>`_ //
8
8
  `issues <http://github.com/marshmallow-code/flask-marshmallow/issues>`_
9
9
 
10
10
 
@@ -178,6 +178,7 @@ You can now use your schema to dump and load your ORM objects.
178
178
 
179
179
  - By default, `~flask_marshmallow.sqla.SQLAlchemySchema` uses the scoped session created by Flask-SQLAlchemy.
180
180
  - `~flask_marshmallow.sqla.SQLAlchemySchema` subclasses `flask_marshmallow.Schema`, so it includes the `~flask_marshmallow.Schema.jsonify` method.
181
+
181
182
  Note: By default, Flask's `jsonify` method sorts the list of keys and returns consistent results to ensure that external HTTP caches aren't trashed. As a side effect, this will override `ordered=True <https://marshmallow.readthedocs.io/en/latest/quickstart.html#ordering-output>`_
182
183
  in the SQLAlchemySchema's `class Meta` (if you set it). To disable this, set `JSON_SORT_KEYS=False` in your Flask app config. In production it's recommended to let `jsonify` sort the keys and not set `ordered=True` in your `~flask_marshmallow.sqla.SQLAlchemySchema` in order to minimize generation time and maximize cacheability of the results.
183
184
 
@@ -228,6 +229,9 @@ API
228
229
  .. automodule:: flask_marshmallow.fields
229
230
  :members:
230
231
 
232
+ .. automodule:: flask_marshmallow.validate
233
+ :members:
234
+
231
235
  .. automodule:: flask_marshmallow.sqla
232
236
  :members:
233
237
 
@@ -0,0 +1,66 @@
1
+ [project]
2
+ name = "flask-marshmallow"
3
+ version = "1.0.0"
4
+ description = "Flask + marshmallow for beautiful APIs"
5
+ readme = "README.rst"
6
+ license = { file = "LICENSE" }
7
+ maintainers = [{ name = "Steven Loria", email = "sloria1@gmail.com" }]
8
+ classifiers = [
9
+ "Environment :: Web Environment",
10
+ "Intended Audience :: Developers",
11
+ "License :: OSI Approved :: MIT License",
12
+ "Natural Language :: English",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.8",
15
+ "Programming Language :: Python :: 3.9",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
20
+ ]
21
+ requires-python = ">=3.8"
22
+ dependencies = ["Flask", "marshmallow>=3.0.0", "packaging>=17.0"]
23
+
24
+ [project.urls]
25
+ Issues = "https://github.com/marshmallow-code/flask-marshmallow/issues"
26
+ Funding = "https://opencollective.com/marshmallow"
27
+
28
+ [project.optional-dependencies]
29
+ docs = [
30
+ "marshmallow-sqlalchemy>=0.19.0",
31
+ "Sphinx==7.2.6",
32
+ "sphinx-issues==3.0.1",
33
+ ]
34
+ tests = ["flask-marshmallow[sqlalchemy]", "pytest"]
35
+ dev = ["flask-marshmallow[tests]", "tox", "pre-commit~=3.5"]
36
+ sqlalchemy = ["flask-sqlalchemy>=3.0.0", "marshmallow-sqlalchemy>=0.29.0"]
37
+
38
+ [build-system]
39
+ requires = ["flit_core<4"]
40
+ build-backend = "flit_core.buildapi"
41
+
42
+ [tool.flit.sdist]
43
+ include = ["docs/", "tests/", "CHANGELOG.rst", "CONTRIBUTING.rst", "tox.ini"]
44
+ exclude = ["docs/_build/"]
45
+
46
+ [tool.ruff]
47
+ src = ["src"]
48
+ fix = true
49
+ show-fixes = true
50
+ show-source = true
51
+
52
+ [tool.ruff.lint]
53
+ select = [
54
+ "B", # flake8-bugbear
55
+ "E", # pycodestyle error
56
+ "F", # pyflakes
57
+ "I", # isort
58
+ "UP", # pyupgrade
59
+ "W", # pycodestyle warning
60
+ ]
61
+
62
+ [tool.pytest.ini_options]
63
+ filterwarnings = [
64
+ "error",
65
+ "ignore:distutils Version classes are deprecated\\. Use packaging.version instead\\.:DeprecationWarning:marshmallow",
66
+ ]
@@ -6,9 +6,9 @@
6
6
  with your Flask application.
7
7
  """
8
8
  import warnings
9
- from packaging.version import Version
10
9
 
11
- from marshmallow import fields as base_fields, exceptions, pprint
10
+ from marshmallow import exceptions, pprint
11
+ from marshmallow import fields as base_fields
12
12
 
13
13
  from . import fields
14
14
  from .schema import Schema
@@ -24,14 +24,20 @@ else:
24
24
  except ImportError:
25
25
  warnings.warn(
26
26
  "Flask-SQLAlchemy integration requires "
27
- "marshmallow-sqlalchemy to be installed."
27
+ "marshmallow-sqlalchemy to be installed.",
28
+ stacklevel=2,
28
29
  )
29
30
  else:
30
31
  has_sqla = True
31
32
 
32
- __version__ = "0.15.0"
33
- __version_info__ = Version(__version__).release
34
- __all__ = ["EXTENSION_NAME", "Marshmallow", "Schema", "fields", "exceptions", "pprint"]
33
+ __all__ = [
34
+ "EXTENSION_NAME",
35
+ "Marshmallow",
36
+ "Schema",
37
+ "fields",
38
+ "exceptions",
39
+ "pprint",
40
+ ]
35
41
 
36
42
  EXTENSION_NAME = "flask-marshmallow"
37
43
 
@@ -75,14 +81,15 @@ class Marshmallow:
75
81
  })
76
82
 
77
83
 
78
- In order to integrate with Flask-SQLAlchemy, this extension must be initialized *after*
79
- `flask_sqlalchemy.SQLAlchemy`. ::
84
+ In order to integrate with Flask-SQLAlchemy, this extension must be initialized
85
+ *after* `flask_sqlalchemy.SQLAlchemy`. ::
80
86
 
81
87
  db = SQLAlchemy(app)
82
88
  ma = Marshmallow(app)
83
89
 
84
- This gives you access to `ma.SQLAlchemySchema` and `ma.SQLAlchemyAutoSchema`, which generate
85
- marshmallow `~marshmallow.Schema` classes based on the passed in model or table. ::
90
+ This gives you access to `ma.SQLAlchemySchema` and `ma.SQLAlchemyAutoSchema`, which
91
+ generate marshmallow `~marshmallow.Schema` classes
92
+ based on the passed in model or table. ::
86
93
 
87
94
  class AuthorSchema(ma.SQLAlchemyAutoSchema):
88
95
  class Meta:
@@ -9,12 +9,18 @@
9
9
  """
10
10
  import re
11
11
 
12
- from flask import url_for
13
- from marshmallow import fields
14
- from marshmallow import missing
12
+ from flask import current_app, url_for
13
+ from marshmallow import fields, missing
15
14
 
16
-
17
- __all__ = ["URLFor", "UrlFor", "AbsoluteURLFor", "AbsoluteUrlFor", "Hyperlinks"]
15
+ __all__ = [
16
+ "URLFor",
17
+ "UrlFor",
18
+ "AbsoluteURLFor",
19
+ "AbsoluteUrlFor",
20
+ "Hyperlinks",
21
+ "File",
22
+ "Config",
23
+ ]
18
24
 
19
25
 
20
26
  _tpl_pattern = re.compile(r"\s*<\s*(\S*)\s*>\s*")
@@ -69,7 +75,10 @@ class URLFor(fields.Field):
69
75
  Usage: ::
70
76
 
71
77
  url = URLFor('author_get', values=dict(id='<id>'))
72
- https_url = URLFor('author_get', values=dict(id='<id>', _scheme='https', _external=True))
78
+ https_url = URLFor(
79
+ 'author_get',
80
+ values=dict(id='<id>', _scheme='https', _external=True),
81
+ )
73
82
 
74
83
  :param str endpoint: Flask endpoint name.
75
84
  :param dict values: Same keyword arguments as Flask's url_for, except string
@@ -100,8 +109,7 @@ class URLFor(fields.Field):
100
109
  param_values[name] = attribute_value
101
110
  else:
102
111
  raise AttributeError(
103
- "{attr_name!r} is not a valid "
104
- "attribute of {obj!r}".format(attr_name=attr_name, obj=obj)
112
+ f"{attr_name!r} is not a valid " f"attribute of {obj!r}"
105
113
  )
106
114
  else:
107
115
  param_values[name] = attr_tpl
@@ -126,7 +134,9 @@ AbsoluteUrlFor = AbsoluteURLFor
126
134
 
127
135
 
128
136
  def _rapply(d, func, *args, **kwargs):
129
- """Apply a function to all values in a dictionary or list of dictionaries, recursively."""
137
+ """Apply a function to all values in a dictionary or
138
+ list of dictionaries, recursively.
139
+ """
130
140
  if isinstance(d, (tuple, list)):
131
141
  return [_rapply(each, func, *args, **kwargs) for each in d]
132
142
  if isinstance(d, dict):
@@ -178,3 +188,60 @@ class Hyperlinks(fields.Field):
178
188
 
179
189
  def _serialize(self, value, attr, obj):
180
190
  return _rapply(self.schema, _url_val, key=attr, obj=obj)
191
+
192
+
193
+ class File(fields.Field):
194
+ """A binary file field for uploaded files.
195
+
196
+ Examples: ::
197
+
198
+ class ImageSchema(Schema):
199
+ image = File(required=True)
200
+ """
201
+
202
+ def __init__(self, *args, **kwargs):
203
+ super().__init__(*args, **kwargs)
204
+ # Metadata used by apispec
205
+ self.metadata["type"] = "string"
206
+ self.metadata["format"] = "binary"
207
+
208
+ default_error_messages = {"invalid": "Not a valid file."}
209
+
210
+ def _deserialize(self, value, attr, data, **kwargs):
211
+ from werkzeug.datastructures import FileStorage
212
+
213
+ if not isinstance(value, FileStorage):
214
+ raise self.make_error("invalid")
215
+ return value
216
+
217
+
218
+ class Config(fields.Field):
219
+ """A field for Flask configuration values.
220
+
221
+ Examples: ::
222
+
223
+ from flask import Flask
224
+
225
+ app = Flask(__name__)
226
+ app.config['API_TITLE'] = 'Pet API'
227
+
228
+ class FooSchema(Schema):
229
+ user = String()
230
+ title = Config('API_TITLE')
231
+
232
+ This field should only be used in an output schema. A ``ValueError`` will
233
+ be raised if the config key is not found in the app config.
234
+
235
+ :param str key: The key of the configuration value.
236
+ """
237
+
238
+ _CHECK_ATTRIBUTE = False
239
+
240
+ def __init__(self, key: str, **kwargs):
241
+ fields.Field.__init__(self, **kwargs)
242
+ self.key = key
243
+
244
+ def _serialize(self, value, attr, obj, **kwargs):
245
+ if self.key not in current_app.config:
246
+ raise ValueError(f"The key {self.key!r} is not found in the app config.")
247
+ return current_app.config[self.key]
@@ -1,7 +1,6 @@
1
1
  import flask
2
2
  import marshmallow as ma
3
3
 
4
-
5
4
  sentinel = object()
6
5
 
7
6
 
@@ -7,9 +7,10 @@
7
7
  `SQLAlchemyAutoSchema <marshmallow_sqlalchemy.SQLAlchemyAutoSchema>` classes
8
8
  that use the scoped session from Flask-SQLAlchemy.
9
9
  """
10
- from flask import url_for, current_app
11
10
  from urllib import parse
11
+
12
12
  import marshmallow_sqlalchemy as msqla
13
+ from flask import current_app, url_for
13
14
  from marshmallow.exceptions import ValidationError
14
15
 
15
16
  from .schema import Schema