flask-restx icon indicating copy to clipboard operation
flask-restx copied to clipboard

marshal_with throws AttributeError: 'NoneType' object has no attribute 'pop'

Open cmdshepard opened this issue 3 years ago • 1 comments

Code

daily_streams_response = api.model(
    "Daily Streams Response",
    {
        "stream_count": fields.Integer,
        "date": fields.Date,
        "*": fields.Wildcard(fields.String),
    },
)

artists_streams_response = api.model(
    "Artists Streams Response",
    {
        "items": fields.List(fields.Nested(
            api.model(
                "artist_streams",
                {"artist_id": fields.String,
                 "streams": fields.List(fields.Nested(daily_streams_response))})
        )),
    },
)

@artists.route("/streams")
class ArtistsStreams(Streams):
    @origin_auth
    @user_auth
    @api.doc(
        responses={200: "Success", 401: "Unauthorized"},
        params={"API_KEY": {"in": "header"}},
    )
    @api.expect(artists_streams_request, validate=False)
    @api.marshal_with(artists_streams_response)
    @cache.cached(timeout=7200, query_string=True)
    def get(self) -> Dict:
        # some logic

Error Messages/Stack Trace

AttributeError: 'NoneType' object has no attribute 'pop'
  File "flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "flask_restx/api.py", line 403, in wrapper
    resp = resource(*args, **kwargs)
  File "flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "flask_restx/resource.py", line 49, in dispatch_request
    resp = meth(*args, **kwargs)
  File "app/api/__init__.py", line 35, in func_wrapper
    return func(*args, **kwargs)
  File "app/api/__init__.py", line 59, in func_wrapper
    return func(*args, **kwargs)
  File "flask_restx/marshalling.py", line 268, in wrapper
    return marshal(
  File "flask_restx/marshalling.py", line 58, in marshal
    out, has_wildcards = _marshal(data, fields, envelope, skip_none, mask, ordered)
  File "flask_restx/marshalling.py", line 189, in _marshal
    out = OrderedDict(items) if ordered else dict(items)
  File "flask_restx/marshalling.py", line 180, in <genexpr>
    else __format_field(k, v)
  File "flask_restx/marshalling.py", line 174, in __format_field
    value = field.output(key, data, ordered=ordered)
  File "flask_restx/fields.py", line 351, in output
    return self.format(value)
  File "flask_restx/fields.py", line 337, in format
    return [
  File "flask_restx/fields.py", line 338, in <listcomp>
    self.container.output(
  File "flask_restx/fields.py", line 275, in output
    return marshal(value, self.nested, skip_none=self.skip_none, ordered=ordered)
  File "flask_restx/marshalling.py", line 58, in marshal
    out, has_wildcards = _marshal(data, fields, envelope, skip_none, mask, ordered)
  File "flask_restx/marshalling.py", line 189, in _marshal
    out = OrderedDict(items) if ordered else dict(items)
  File "flask_restx/marshalling.py", line 180, in <genexpr>
    else __format_field(k, v)
  File "flask_restx/marshalling.py", line 174, in __format_field
    value = field.output(key, data, ordered=ordered)
  File "flask_restx/fields.py", line 351, in output
    return self.format(value)
  File "flask_restx/fields.py", line 337, in format
    return [
  File "flask_restx/fields.py", line 338, in <listcomp>
    self.container.output(
  File "flask_restx/fields.py", line 275, in output
    return marshal(value, self.nested, skip_none=self.skip_none, ordered=ordered)
  File "flask_restx/marshalling.py", line 90, in marshal
    value = field.output(dkey, data, ordered=ordered)
  File "flask_restx/fields.py", line 872, in output
    (objkey, val) = self._flat.pop()

Environment

  • Python version -> 3.8.11
  • Flask version -> 1.1.4
  • Flask-RESTX version -> 0.5.1
  • Other installed Flask extensions
    • flask-caching
    • flask-cors
    • flask-migrate
    • flask-script
    • flask-sqlalchemy

Additional Context

Trying to figure out what could be causing this error that's being triggered from the decorator. Thank you in advance! :)

cmdshepard avatar Dec 09 '22 16:12 cmdshepard

Can you move the wildcard definition outside of the model and see if that makes any difference?

From the docs:

It is important you define your Wildcard outside your model (ie. you cannot use it like this: res_fields = {'*': fields.Wildcard(fields.String)}) because it has to be stateful to keep a track of what fields it has already treated.

peter-doggart avatar Jan 05 '23 17:01 peter-doggart