66from marshmallow .exceptions import ValidationError
77from collections .abc import Mapping
88
9+ from marshmallow import Schema as _Schema
10+
911from .spec .utilities import update_spec
1012from .schema import TaskSchema , Schema , FieldSchema
1113from .fields import Field
1214from .view import View
1315from .find import current_labthing
16+ from .utilities import unpack
1417
1518from labthings .core .tasks .pool import TaskThread
1619
2023from marshmallow import pre_dump , pre_load
2124
2225
23- def unpack (value ):
24- """Return a three tuple of data, code, and headers"""
25- if not isinstance (value , tuple ):
26- return value , 200 , {}
27-
28- try :
29- data , code , headers = value
30- return data , code , headers
31- except ValueError :
32- pass
33-
34- try :
35- data , code = value
36- return data , code , {}
37- except ValueError :
38- pass
39-
40- return value , 200 , {}
41-
42-
4326class marshal_with :
4427 def __init__ (self , schema , code = 200 ):
45- """Decorator to format the response of a View with a Marshmallow schema
28+ """Decorator to format the return of a function with a Marshmallow schema
4629
4730 Args:
4831 schema: Marshmallow schema, field, or dict of Fields, describing
@@ -52,11 +35,11 @@ def __init__(self, schema, code=200):
5235 self .code = code
5336
5437 if isinstance (self .schema , Mapping ):
55- self .converter = Schema .from_dict (self .schema )().jsonify
38+ self .converter = Schema .from_dict (self .schema )().dump
5639 elif isinstance (self .schema , Field ):
57- self .converter = FieldSchema (self .schema ).jsonify
58- elif isinstance (self .schema , Schema ):
59- self .converter = self .schema .jsonify
40+ self .converter = FieldSchema (self .schema ).dump
41+ elif isinstance (self .schema , _Schema ):
42+ self .converter = self .schema .dump
6043 else :
6144 raise TypeError (
6245 f"Unsupported schema type { type (self .schema )} for marshal_with"
@@ -69,12 +52,15 @@ def __call__(self, f):
6952 @wraps (f )
7053 def wrapper (* args , ** kwargs ):
7154 resp = f (* args , ** kwargs )
72- if isinstance (resp , tuple ):
73- data , code , headers = unpack (resp )
55+ if isinstance (resp , ResponseBase ):
56+ resp .data = self .converter (resp .data )
57+ return resp
58+ elif isinstance (resp , tuple ):
59+ resp , code , headers = unpack (resp )
60+ return (self .converter (resp ), code , headers )
7461 else :
75- data , code , headers = resp , 200 , {}
76-
77- return make_response (self .converter (data ), code , headers )
62+ resp , code , headers = resp , 200 , {}
63+ return (self .converter (resp ), code , headers )
7864
7965 return wrapper
8066
@@ -90,15 +76,15 @@ def marshal_task(f):
9076 def wrapper (* args , ** kwargs ):
9177 resp = f (* args , ** kwargs )
9278 if isinstance (resp , tuple ):
93- data , code , headers = unpack (resp )
79+ resp , code , headers = unpack (resp )
9480 else :
95- data , code , headers = resp , 200 , {}
81+ resp , code , headers = resp , 201 , {}
9682
97- if not isinstance (data , TaskThread ):
83+ if not isinstance (resp , TaskThread ):
9884 raise TypeError (
99- f"Function { f .__name__ } expected to return a TaskThread object, but instead returned a { type (data ).__name__ } . If it does not return a task, remove the @marshall_task decorator from { f .__name__ } ."
85+ f"Function { f .__name__ } expected to return a TaskThread object, but instead returned a { type (resp ).__name__ } . If it does not return a task, remove the @marshall_task decorator from { f .__name__ } ."
10086 )
101- return make_response (TaskSchema ().jsonify ( data ), code , headers )
87+ return (TaskSchema ().dump ( resp ), code , headers )
10288
10389 return wrapper
10490
0 commit comments