flask-marshmallow 1.2.1__py3-none-any.whl → 1.4.0__py3-none-any.whl
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.
- flask_marshmallow/__init__.py +21 -7
- flask_marshmallow/fields.py +10 -10
- flask_marshmallow/schema.py +4 -2
- flask_marshmallow/sqla.py +2 -0
- flask_marshmallow/validate.py +7 -5
- {flask_marshmallow-1.2.1.dist-info → flask_marshmallow-1.4.0.dist-info}/METADATA +15 -15
- flask_marshmallow-1.4.0.dist-info/RECORD +10 -0
- {flask_marshmallow-1.2.1.dist-info → flask_marshmallow-1.4.0.dist-info}/WHEEL +1 -1
- flask_marshmallow-1.2.1.dist-info/RECORD +0 -10
- {flask_marshmallow-1.2.1.dist-info → flask_marshmallow-1.4.0.dist-info/licenses}/LICENSE +0 -0
flask_marshmallow/__init__.py
CHANGED
|
@@ -9,7 +9,15 @@ with your Flask application.
|
|
|
9
9
|
import typing
|
|
10
10
|
import warnings
|
|
11
11
|
|
|
12
|
-
from marshmallow import exceptions
|
|
12
|
+
from marshmallow import exceptions
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
# Available in marshmallow 3 only
|
|
16
|
+
from marshmallow import pprint # noqa: F401
|
|
17
|
+
except ImportError:
|
|
18
|
+
_has_pprint = False
|
|
19
|
+
else:
|
|
20
|
+
_has_pprint = True
|
|
13
21
|
from marshmallow import fields as base_fields
|
|
14
22
|
|
|
15
23
|
from . import fields
|
|
@@ -41,8 +49,9 @@ __all__ = [
|
|
|
41
49
|
"Schema",
|
|
42
50
|
"fields",
|
|
43
51
|
"exceptions",
|
|
44
|
-
"pprint",
|
|
45
52
|
]
|
|
53
|
+
if _has_pprint:
|
|
54
|
+
__all__.append("pprint")
|
|
46
55
|
|
|
47
56
|
EXTENSION_NAME = "flask-marshmallow"
|
|
48
57
|
|
|
@@ -75,9 +84,8 @@ class Marshmallow:
|
|
|
75
84
|
You can declare schema like so::
|
|
76
85
|
|
|
77
86
|
class BookSchema(ma.Schema):
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
id = ma.Integer(dump_only=True)
|
|
88
|
+
title = ma.String(required=True)
|
|
81
89
|
author = ma.Nested(AuthorSchema)
|
|
82
90
|
|
|
83
91
|
links = ma.Hyperlinks(
|
|
@@ -126,6 +134,12 @@ class Marshmallow:
|
|
|
126
134
|
# If using Flask-SQLAlchemy, attach db.session to SQLAlchemySchema
|
|
127
135
|
if has_sqla and "sqlalchemy" in app.extensions:
|
|
128
136
|
db = app.extensions["sqlalchemy"]
|
|
129
|
-
|
|
130
|
-
|
|
137
|
+
SQLAlchemySchemaOpts = typing.cast(
|
|
138
|
+
sqla.SQLAlchemySchemaOpts, self.SQLAlchemySchema.OPTIONS_CLASS
|
|
139
|
+
)
|
|
140
|
+
SQLAlchemySchemaOpts.session = db.session
|
|
141
|
+
SQLAlchemyAutoSchemaOpts = typing.cast(
|
|
142
|
+
sqla.SQLAlchemyAutoSchemaOpts, self.SQLAlchemySchema.OPTIONS_CLASS
|
|
143
|
+
)
|
|
144
|
+
SQLAlchemyAutoSchemaOpts.session = db.session
|
|
131
145
|
app.extensions[EXTENSION_NAME] = self
|
flask_marshmallow/fields.py
CHANGED
|
@@ -8,6 +8,8 @@ See the `marshmallow.fields` module for the list of all fields available from th
|
|
|
8
8
|
marshmallow library.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
11
13
|
import re
|
|
12
14
|
import typing
|
|
13
15
|
from collections.abc import Sequence
|
|
@@ -29,7 +31,7 @@ __all__ = [
|
|
|
29
31
|
_tpl_pattern = re.compile(r"\s*<\s*(\S*)\s*>\s*")
|
|
30
32
|
|
|
31
33
|
|
|
32
|
-
def _tpl(val: str) ->
|
|
34
|
+
def _tpl(val: str) -> str | None:
|
|
33
35
|
"""Return value within ``< >`` if possible, else return ``None``."""
|
|
34
36
|
match = _tpl_pattern.match(val)
|
|
35
37
|
if match:
|
|
@@ -95,7 +97,7 @@ class URLFor(fields.Field):
|
|
|
95
97
|
def __init__(
|
|
96
98
|
self,
|
|
97
99
|
endpoint: str,
|
|
98
|
-
values:
|
|
100
|
+
values: dict[str, typing.Any] | None = None,
|
|
99
101
|
**kwargs,
|
|
100
102
|
):
|
|
101
103
|
self.endpoint = endpoint
|
|
@@ -117,7 +119,7 @@ class URLFor(fields.Field):
|
|
|
117
119
|
param_values[name] = attribute_value
|
|
118
120
|
else:
|
|
119
121
|
raise AttributeError(
|
|
120
|
-
f"{attr_name!r} is not a valid
|
|
122
|
+
f"{attr_name!r} is not a valid attribute of {obj!r}"
|
|
121
123
|
)
|
|
122
124
|
else:
|
|
123
125
|
param_values[name] = attr_tpl
|
|
@@ -133,7 +135,7 @@ class AbsoluteURLFor(URLFor):
|
|
|
133
135
|
def __init__(
|
|
134
136
|
self,
|
|
135
137
|
endpoint: str,
|
|
136
|
-
values:
|
|
138
|
+
values: dict[str, typing.Any] | None = None,
|
|
137
139
|
**kwargs,
|
|
138
140
|
):
|
|
139
141
|
if values:
|
|
@@ -146,9 +148,7 @@ class AbsoluteURLFor(URLFor):
|
|
|
146
148
|
AbsoluteUrlFor = AbsoluteURLFor
|
|
147
149
|
|
|
148
150
|
|
|
149
|
-
def _rapply(
|
|
150
|
-
d: typing.Union[dict, typing.Iterable], func: typing.Callable, *args, **kwargs
|
|
151
|
-
):
|
|
151
|
+
def _rapply(d: dict | typing.Iterable, func: typing.Callable, *args, **kwargs):
|
|
152
152
|
"""Apply a function to all values in a dictionary or
|
|
153
153
|
list of dictionaries, recursively.
|
|
154
154
|
"""
|
|
@@ -201,7 +201,7 @@ class Hyperlinks(fields.Field):
|
|
|
201
201
|
|
|
202
202
|
_CHECK_ATTRIBUTE = False
|
|
203
203
|
|
|
204
|
-
def __init__(self, schema:
|
|
204
|
+
def __init__(self, schema: dict[str, URLFor | str], **kwargs):
|
|
205
205
|
self.schema = schema
|
|
206
206
|
fields.Field.__init__(self, **kwargs)
|
|
207
207
|
|
|
@@ -229,8 +229,8 @@ class File(fields.Field):
|
|
|
229
229
|
def deserialize(
|
|
230
230
|
self,
|
|
231
231
|
value: typing.Any,
|
|
232
|
-
attr:
|
|
233
|
-
data: typing.
|
|
232
|
+
attr: str | None = None,
|
|
233
|
+
data: typing.Mapping[str, typing.Any] | None = None,
|
|
234
234
|
**kwargs,
|
|
235
235
|
):
|
|
236
236
|
if isinstance(value, Sequence) and len(value) == 0:
|
flask_marshmallow/schema.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import typing
|
|
2
4
|
|
|
3
5
|
import flask
|
|
@@ -14,8 +16,8 @@ class Schema(ma.Schema):
|
|
|
14
16
|
"""
|
|
15
17
|
|
|
16
18
|
def jsonify(
|
|
17
|
-
self, obj: typing.Any, many:
|
|
18
|
-
) ->
|
|
19
|
+
self, obj: typing.Any, many: bool | None = None, *args, **kwargs
|
|
20
|
+
) -> Response:
|
|
19
21
|
"""Return a JSON response containing the serialized data.
|
|
20
22
|
|
|
21
23
|
|
flask_marshmallow/sqla.py
CHANGED
flask_marshmallow/validate.py
CHANGED
|
@@ -5,6 +5,8 @@ flask_marshmallow.validate
|
|
|
5
5
|
Custom validation classes for various types of data.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
8
10
|
import io
|
|
9
11
|
import os
|
|
10
12
|
import re
|
|
@@ -91,11 +93,11 @@ class FileSize(Validator):
|
|
|
91
93
|
|
|
92
94
|
def __init__(
|
|
93
95
|
self,
|
|
94
|
-
min:
|
|
95
|
-
max:
|
|
96
|
+
min: str | None = None,
|
|
97
|
+
max: str | None = None,
|
|
96
98
|
min_inclusive: bool = True,
|
|
97
99
|
max_inclusive: bool = True,
|
|
98
|
-
error:
|
|
100
|
+
error: str | None = None,
|
|
99
101
|
):
|
|
100
102
|
self.min = min
|
|
101
103
|
self.max = max
|
|
@@ -171,14 +173,14 @@ class FileType(Validator):
|
|
|
171
173
|
def __init__(
|
|
172
174
|
self,
|
|
173
175
|
accept: typing.Iterable[str],
|
|
174
|
-
error:
|
|
176
|
+
error: str | None = None,
|
|
175
177
|
):
|
|
176
178
|
self.allowed_types = {ext.lower() for ext in accept}
|
|
177
179
|
self.error = error or self.default_message
|
|
178
180
|
|
|
179
181
|
def _format_error(self, value):
|
|
180
182
|
return (self.error or self.default_message).format(
|
|
181
|
-
input=value, extensions="".join(self.allowed_types)
|
|
183
|
+
input=value, extensions=",".join(self.allowed_types)
|
|
182
184
|
)
|
|
183
185
|
|
|
184
186
|
def __call__(self, value):
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: flask-marshmallow
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Flask + marshmallow for beautiful APIs
|
|
5
|
-
Maintainer-email: Steven Loria <
|
|
6
|
-
Requires-Python: >=3.
|
|
5
|
+
Maintainer-email: Steven Loria <oss@stevenloria.com>, Stephen Rosen <sirosen0@gmail.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/x-rst
|
|
8
8
|
Classifier: Environment :: Web Environment
|
|
9
9
|
Classifier: Intended Audience :: Developers
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
11
|
Classifier: Natural Language :: English
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
18
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
19
|
+
License-File: LICENSE
|
|
19
20
|
Requires-Dist: Flask>=2.2
|
|
20
21
|
Requires-Dist: marshmallow>=3.0.0
|
|
21
22
|
Requires-Dist: flask-marshmallow[tests] ; extra == "dev"
|
|
22
23
|
Requires-Dist: tox ; extra == "dev"
|
|
23
|
-
Requires-Dist: pre-commit
|
|
24
|
+
Requires-Dist: pre-commit>=4.5,<5.0 ; extra == "dev"
|
|
24
25
|
Requires-Dist: marshmallow-sqlalchemy>=0.19.0 ; extra == "docs"
|
|
25
|
-
Requires-Dist: Sphinx==
|
|
26
|
-
Requires-Dist: sphinx-issues==
|
|
26
|
+
Requires-Dist: Sphinx==9.1.0 ; extra == "docs"
|
|
27
|
+
Requires-Dist: sphinx-issues==5.0.1 ; extra == "docs"
|
|
27
28
|
Requires-Dist: flask-sqlalchemy>=3.0.0 ; extra == "sqlalchemy"
|
|
28
29
|
Requires-Dist: marshmallow-sqlalchemy>=0.29.0 ; extra == "sqlalchemy"
|
|
29
30
|
Requires-Dist: flask-marshmallow[sqlalchemy] ; extra == "tests"
|
|
@@ -39,7 +40,7 @@ Provides-Extra: tests
|
|
|
39
40
|
Flask-Marshmallow
|
|
40
41
|
*****************
|
|
41
42
|
|
|
42
|
-
|pypi-package| |build-status| |docs| |
|
|
43
|
+
|pypi-package| |build-status| |docs| |marshmallow-support|
|
|
43
44
|
|
|
44
45
|
Flask + marshmallow for beautiful APIs
|
|
45
46
|
======================================
|
|
@@ -82,9 +83,8 @@ Define your output format with marshmallow.
|
|
|
82
83
|
|
|
83
84
|
|
|
84
85
|
class UserSchema(ma.Schema):
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
fields = ("email", "date_created", "_links")
|
|
86
|
+
email = ma.Email()
|
|
87
|
+
date_created = ma.DateTime()
|
|
88
88
|
|
|
89
89
|
# Smart hyperlinking
|
|
90
90
|
_links = ma.Hyperlinks(
|
|
@@ -164,7 +164,7 @@ MIT licensed. See the bundled `LICENSE <https://github.com/marshmallow-code/flas
|
|
|
164
164
|
:target: https://flask-marshmallow.readthedocs.io/
|
|
165
165
|
:alt: Documentation
|
|
166
166
|
|
|
167
|
-
.. |
|
|
167
|
+
.. |marshmallow-support| image:: https://badgen.net/badge/marshmallow/3,4?list=1
|
|
168
168
|
:target: https://marshmallow.readthedocs.io/en/latest/upgrading.html
|
|
169
|
-
:alt: marshmallow 3 compatible
|
|
169
|
+
:alt: marshmallow 3|4 compatible
|
|
170
170
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
flask_marshmallow/__init__.py,sha256=z1T-yR1vgxKgU_QtdJmJgkJEFgKInIn1piaaOfb9ndw,4131
|
|
2
|
+
flask_marshmallow/fields.py,sha256=_aDs2dWM5CV2xigge_b4Qoz7LGam5gJoTLPlG0frD50,7865
|
|
3
|
+
flask_marshmallow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
flask_marshmallow/schema.py,sha256=qC6jF_peb8WvQAJpe14MQaLmqRahAReoP7GKcC4nNfI,1436
|
|
5
|
+
flask_marshmallow/sqla.py,sha256=RXiV5EZwg8g3XWN5ZsqOK3xrhmZ5FlgeVmzwDExC1LU,3984
|
|
6
|
+
flask_marshmallow/validate.py,sha256=cUsavS9Hsdb9yQ_WKvswbVjEMfD92GGDVm7yfmU-4W4,6813
|
|
7
|
+
flask_marshmallow-1.4.0.dist-info/licenses/LICENSE,sha256=kGtdkFHkJhRMsXOtkRZnuOvQWpxYTCwmwTWzKj7RIAE,1064
|
|
8
|
+
flask_marshmallow-1.4.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
9
|
+
flask_marshmallow-1.4.0.dist-info/METADATA,sha256=92zlOeitEYTujBPEvK1HxRMYXMsqEYDmsdOS1CDLdzE,5203
|
|
10
|
+
flask_marshmallow-1.4.0.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
flask_marshmallow/__init__.py,sha256=IsYMbL7JZL1yc1P0EKVfpxokIMlnKKVNMcSwhHfu29w,3678
|
|
2
|
-
flask_marshmallow/fields.py,sha256=Z-v60FhOe-HlupA_tGhZMtS4p4b9i4LFbTbCgDCQ5-4,7936
|
|
3
|
-
flask_marshmallow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
flask_marshmallow/schema.py,sha256=Z6uJVkqi-gq1QfdPbPuy5Fw3UnXGE9vKiD6IJkPOMR4,1412
|
|
5
|
-
flask_marshmallow/sqla.py,sha256=VN4aH5pm1HvyepeV6AHtipTAK_Mz_zLA-0IulsObhCk,3948
|
|
6
|
-
flask_marshmallow/validate.py,sha256=KRJus6GpPC7MZGFjDidhnNjI3tc6_y9PPQ-Pcmik18I,6816
|
|
7
|
-
flask_marshmallow-1.2.1.dist-info/LICENSE,sha256=kGtdkFHkJhRMsXOtkRZnuOvQWpxYTCwmwTWzKj7RIAE,1064
|
|
8
|
-
flask_marshmallow-1.2.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
9
|
-
flask_marshmallow-1.2.1.dist-info/METADATA,sha256=E5EDVQ1awnti6hs2oQPuBu1B5xAV19cfvW6kiUqbXH8,5190
|
|
10
|
-
flask_marshmallow-1.2.1.dist-info/RECORD,,
|
|
File without changes
|