flask-marshmallow 1.2.0__py3-none-any.whl → 1.2.1__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.
@@ -1,10 +1,11 @@
1
1
  """
2
- flask_marshmallow
3
- ~~~~~~~~~~~~~~~~~
2
+ flask_marshmallow
3
+ ~~~~~~~~~~~~~~~~~
4
4
 
5
- Integrates the marshmallow serialization/deserialization library
6
- with your Flask application.
5
+ Integrates the marshmallow serialization/deserialization library
6
+ with your Flask application.
7
7
  """
8
+
8
9
  import typing
9
10
  import warnings
10
11
 
@@ -75,14 +76,16 @@ class Marshmallow:
75
76
 
76
77
  class BookSchema(ma.Schema):
77
78
  class Meta:
78
- fields = ('id', 'title', 'author', 'links')
79
+ fields = ("id", "title", "author", "links")
79
80
 
80
81
  author = ma.Nested(AuthorSchema)
81
82
 
82
- links = ma.Hyperlinks({
83
- 'self': ma.URLFor('book_detail', values=dict(id='<id>')),
84
- 'collection': ma.URLFor('book_list')
85
- })
83
+ links = ma.Hyperlinks(
84
+ {
85
+ "self": ma.URLFor("book_detail", values=dict(id="<id>")),
86
+ "collection": ma.URLFor("book_list"),
87
+ }
88
+ )
86
89
 
87
90
 
88
91
  In order to integrate with Flask-SQLAlchemy, this extension must be initialized
@@ -1,14 +1,16 @@
1
1
  """
2
- flask_marshmallow.fields
3
- ~~~~~~~~~~~~~~~~~~~~~~~~
2
+ flask_marshmallow.fields
3
+ ~~~~~~~~~~~~~~~~~~~~~~~~
4
4
 
5
- Custom, Flask-specific fields.
5
+ Custom, Flask-specific fields.
6
6
 
7
- See the `marshmallow.fields` module for the list of all fields available from the
8
- marshmallow library.
7
+ See the `marshmallow.fields` module for the list of all fields available from the
8
+ marshmallow library.
9
9
  """
10
+
10
11
  import re
11
12
  import typing
13
+ from collections.abc import Sequence
12
14
 
13
15
  from flask import current_app, url_for
14
16
  from marshmallow import fields, missing
@@ -75,10 +77,10 @@ class URLFor(fields.Field):
75
77
 
76
78
  Usage: ::
77
79
 
78
- url = URLFor('author_get', values=dict(id='<id>'))
80
+ url = URLFor("author_get", values=dict(id="<id>"))
79
81
  https_url = URLFor(
80
- 'author_get',
81
- values=dict(id='<id>', _scheme='https', _external=True),
82
+ "author_get",
83
+ values=dict(id="<id>", _scheme="https", _external=True),
82
84
  )
83
85
 
84
86
  :param str endpoint: Flask endpoint name.
@@ -175,19 +177,23 @@ class Hyperlinks(fields.Field):
175
177
 
176
178
  Example: ::
177
179
 
178
- _links = Hyperlinks({
179
- 'self': URLFor('author', values=dict(id='<id>')),
180
- 'collection': URLFor('author_list'),
181
- })
180
+ _links = Hyperlinks(
181
+ {
182
+ "self": URLFor("author", values=dict(id="<id>")),
183
+ "collection": URLFor("author_list"),
184
+ }
185
+ )
182
186
 
183
187
  `URLFor` objects can be nested within the dictionary. ::
184
188
 
185
- _links = Hyperlinks({
186
- 'self': {
187
- 'href': URLFor('book', values=dict(id='<id>')),
188
- 'title': 'book detail'
189
+ _links = Hyperlinks(
190
+ {
191
+ "self": {
192
+ "href": URLFor("book", values=dict(id="<id>")),
193
+ "title": "book detail",
194
+ }
189
195
  }
190
- })
196
+ )
191
197
 
192
198
  :param dict schema: A dict that maps names to
193
199
  :class:`~flask_marshmallow.fields.URLFor` fields.
@@ -220,6 +226,17 @@ class File(fields.Field):
220
226
 
221
227
  default_error_messages = {"invalid": "Not a valid file."}
222
228
 
229
+ def deserialize(
230
+ self,
231
+ value: typing.Any,
232
+ attr: typing.Optional[str] = None,
233
+ data: typing.Optional[typing.Mapping[str, typing.Any]] = None,
234
+ **kwargs,
235
+ ):
236
+ if isinstance(value, Sequence) and len(value) == 0:
237
+ value = missing
238
+ return super().deserialize(value, attr, data, **kwargs)
239
+
223
240
  def _deserialize(self, value, attr, data, **kwargs):
224
241
  from werkzeug.datastructures import FileStorage
225
242
 
@@ -236,11 +253,12 @@ class Config(fields.Field):
236
253
  from flask import Flask
237
254
 
238
255
  app = Flask(__name__)
239
- app.config['API_TITLE'] = 'Pet API'
256
+ app.config["API_TITLE"] = "Pet API"
257
+
240
258
 
241
259
  class FooSchema(Schema):
242
260
  user = String()
243
- title = Config('API_TITLE')
261
+ title = Config("API_TITLE")
244
262
 
245
263
  This field should only be used in an output schema. A ``ValueError`` will
246
264
  be raised if the config key is not found in the app config.
flask_marshmallow/sqla.py CHANGED
@@ -1,12 +1,13 @@
1
1
  """
2
- flask_marshmallow.sqla
3
- ~~~~~~~~~~~~~~~~~~~~~~
2
+ flask_marshmallow.sqla
3
+ ~~~~~~~~~~~~~~~~~~~~~~
4
4
 
5
- Integration with Flask-SQLAlchemy and marshmallow-sqlalchemy. Provides
6
- `SQLAlchemySchema <marshmallow_sqlalchemy.SQLAlchemySchema>` and
7
- `SQLAlchemyAutoSchema <marshmallow_sqlalchemy.SQLAlchemyAutoSchema>` classes
8
- that use the scoped session from Flask-SQLAlchemy.
5
+ Integration with Flask-SQLAlchemy and marshmallow-sqlalchemy. Provides
6
+ `SQLAlchemySchema <marshmallow_sqlalchemy.SQLAlchemySchema>` and
7
+ `SQLAlchemyAutoSchema <marshmallow_sqlalchemy.SQLAlchemyAutoSchema>` classes
8
+ that use the scoped session from Flask-SQLAlchemy.
9
9
  """
10
+
10
11
  from urllib import parse
11
12
 
12
13
  import marshmallow_sqlalchemy as msqla
@@ -1,12 +1,15 @@
1
1
  """
2
- flask_marshmallow.validate
3
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
2
+ flask_marshmallow.validate
3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
4
4
 
5
- Custom validation classes for various types of data.
5
+ Custom validation classes for various types of data.
6
6
  """
7
+
8
+ import io
7
9
  import os
8
10
  import re
9
11
  import typing
12
+ from tempfile import SpooledTemporaryFile
10
13
 
11
14
  from marshmallow.exceptions import ValidationError
12
15
  from marshmallow.validate import Validator as Validator
@@ -15,7 +18,15 @@ from werkzeug.datastructures import FileStorage
15
18
 
16
19
  def _get_filestorage_size(file: FileStorage) -> int:
17
20
  """Return the size of the FileStorage object in bytes."""
18
- size: int = file.stream.getbuffer().nbytes # type: ignore
21
+ stream = file.stream
22
+ if isinstance(stream, io.BytesIO):
23
+ return stream.getbuffer().nbytes
24
+
25
+ if isinstance(stream, SpooledTemporaryFile):
26
+ return os.stat(stream.fileno()).st_size
27
+
28
+ size = len(file.read())
29
+ file.stream.seek(0)
19
30
  return size
20
31
 
21
32
 
@@ -57,7 +68,7 @@ class FileSize(Validator):
57
68
  Example: ::
58
69
 
59
70
  class ImageSchema(Schema):
60
- image = File(required=True, validate=FileSize(min='1 MiB', max='2 MiB'))
71
+ image = File(required=True, validate=FileSize(min="1 MiB", max="2 MiB"))
61
72
 
62
73
  :param min: The minimum size (lower bound). If not provided, minimum
63
74
  size will not be checked.
@@ -106,8 +117,10 @@ class FileSize(Validator):
106
117
  )
107
118
 
108
119
  def _repr_args(self):
109
- return "min={!r}, max={!r}, min_inclusive={!r}, max_inclusive={!r}".format(
110
- self.min, self.max, self.min_inclusive, self.max_inclusive
120
+ return (
121
+ f"min={self.min!r}, max={self.max!r}, "
122
+ f"min_inclusive={self.min_inclusive!r}, "
123
+ f"max_inclusive={self.max_inclusive!r}"
111
124
  )
112
125
 
113
126
  def _format_error(self, value, message):
@@ -141,11 +154,12 @@ class FileSize(Validator):
141
154
 
142
155
  class FileType(Validator):
143
156
  """Validator which succeeds if the uploaded file is allowed by a given list
144
- of extensions.
157
+ of extensions.
145
158
 
146
159
  Example: ::
160
+
147
161
  class ImageSchema(Schema):
148
- image = File(required=True, validate=FileType(['.png']))
162
+ image = File(required=True, validate=FileType([".png"]))
149
163
 
150
164
  :param accept: A sequence of allowed extensions.
151
165
  :param error: Error message to raise in case of a validation error.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flask-marshmallow
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: Flask + marshmallow for beautiful APIs
5
5
  Maintainer-email: Steven Loria <sloria1@gmail.com>, Stephen Rosen <sirosen0@gmail.com>
6
6
  Requires-Python: >=3.8
@@ -0,0 +1,10 @@
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,,
@@ -1,10 +0,0 @@
1
- flask_marshmallow/__init__.py,sha256=2s46vkrP0wX1wXBT0OF9oTUNIaoX5-uu_AogfhGXupg,3650
2
- flask_marshmallow/fields.py,sha256=0_mk3dKpyDKT66Tp4KoDZ0uNCxmvGVH3Rk4OAwjR8f4,7486
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=QKEpKDfrBJ5m1KpnRuEB5Txfxql-aN_pyHznYxzNd6Y,3971
6
- flask_marshmallow/validate.py,sha256=cJDooGyaEqhTmnIBEpOKAR8Y-WzPcNdvtDcAZUCI030,6565
7
- flask_marshmallow-1.2.0.dist-info/LICENSE,sha256=kGtdkFHkJhRMsXOtkRZnuOvQWpxYTCwmwTWzKj7RIAE,1064
8
- flask_marshmallow-1.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
9
- flask_marshmallow-1.2.0.dist-info/METADATA,sha256=SnUTf1VP6m6L83PHJK6QZ6tbsQwuCP4yAAvLwqPdMf0,5190
10
- flask_marshmallow-1.2.0.dist-info/RECORD,,