-
Notifications
You must be signed in to change notification settings - Fork 6
Description
The Python dependency flask-marshmallow released v0.15.0 on April 5, 2023, which includes a backwards-incompatible change from v0.14.0 (released September 27, 2020) that affects the sfa-api code: https://github.com/marshmallow-code/flask-marshmallow/blob/dev/CHANGELOG.rst
Backwards-incompatible:
URLForandAbsoluteURLFornow do not accept parameters forflask.url_foras top-level parameters. They must always be passed in the values dictionary, as explained in the v0.14.0 changelog.
Since our requirements.txt file didn't previously pin the version of flask-marshmallow, this lead to a (silent) upgrade which broke the sfa-api. The quick fix is to pin the version to v0.14.0, but we should also consider making the relevant changes in sfa-api to move to flask-marshmallow v0.15.0.
How the error showed up
If flask-marshmallow v0.15.0 is used, then GET /sites/ works fine but anything else that relates to Sites (e.g., GET /observations) will fail with this error in the logs:
[13/Apr/2023:22:42:54 +0000] - 200 "GET / HTTP/1.1" 548 "-" "-" 0.002208
[2023-04-13 22:43:13,250] ERROR in app: Exception on /observations/ [GET]
Traceback (most recent call last):
File "/opt/app-root/lib/python3.9/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.full_dispatch_request()
File "/opt/app-root/lib/python3.9/site-packages/flask/app.py", line 1825, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/opt/app-root/lib/python3.9/site-packages/flask/app.py", line 1823, in full_dispatch_request
rv = self.dispatch_request()
File "/opt/app-root/lib/python3.9/site-packages/flask/app.py", line 1799, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/opt/app-root/lib/python3.9/site-packages/flask/views.py", line 107, in view
return current_app.ensure_sync(self.dispatch_request)(**kwargs)
File "/opt/app-root/lib/python3.9/site-packages/flask/views.py", line 188, in dispatch_request
return current_app.ensure_sync(meth)(**kwargs)
File "/opt/app-root/src/sfa_api/observations.py", line 52, in get
return jsonify(ObservationSchema(many=True).dump(observations))
File "/opt/app-root/lib/python3.9/site-packages/marshmallow/schema.py", line 557, in dump
result = self._serialize(processed_obj, many=many)
File "/opt/app-root/lib/python3.9/site-packages/marshmallow/schema.py", line 519, in _serialize
return [
File "/opt/app-root/lib/python3.9/site-packages/marshmallow/schema.py", line 520, in <listcomp>
self._serialize(d, many=False)
File "/opt/app-root/lib/python3.9/site-packages/marshmallow/schema.py", line 525, in _serialize
value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)
File "/opt/app-root/lib/python3.9/site-packages/marshmallow/fields.py", line 344, in serialize
return self._serialize(value, attr, obj, **kwargs)
File "/opt/app-root/lib/python3.9/site-packages/flask_marshmallow/fields.py", line 180, in _serialize
return _rapply(self.schema, _url_val, key=attr, obj=obj)
File "/opt/app-root/lib/python3.9/site-packages/flask_marshmallow/fields.py", line 133, in _rapply
return {key: _rapply(value, func, *args, **kwargs) for key, value in d.items()}
File "/opt/app-root/lib/python3.9/site-packages/flask_marshmallow/fields.py", line 133, in <dictcomp>
return {key: _rapply(value, func, *args, **kwargs) for key, value in d.items()}
File "/opt/app-root/lib/python3.9/site-packages/flask_marshmallow/fields.py", line 135, in _rapply
return func(d, *args, **kwargs)
File "/opt/app-root/lib/python3.9/site-packages/flask_marshmallow/fields.py", line 143, in _url_val
return val.serialize(key, obj, **kwargs)
File "/opt/app-root/lib/python3.9/site-packages/marshmallow/fields.py", line 344, in serialize
return self._serialize(value, attr, obj, **kwargs)
File "/opt/app-root/lib/python3.9/site-packages/flask_marshmallow/fields.py", line 108, in _serialize
return url_for(self.endpoint, **param_values)
File "/opt/app-root/lib/python3.9/site-packages/flask/helpers.py", line 256, in url_for
return current_app.url_for(
File "/opt/app-root/lib/python3.9/site-packages/flask/app.py", line 2034, in url_for
return self.handle_url_build_error(error, endpoint, values)
File "/opt/app-root/lib/python3.9/site-packages/flask/app.py", line 2023, in url_for
rv = url_adapter.build( # type: ignore[union-attr]
File "/opt/app-root/lib/python3.9/site-packages/werkzeug/routing/map.py", line 917, in build
raise BuildError(endpoint, values, method, self)
werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'sites.single'. Did you forget to specify values ['site_id']?where the key lines are about the current_app.url_for() call and the werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'sites.single'. Did you forget to specify values ['site_id']? message.