22import logging
33import warnings
44
5+ from functools import lru_cache
56from six import iteritems
67
8+ from openapi_core .enums import ParameterLocation , ParameterStyle , SchemaType
79from openapi_core .exceptions import (
810 EmptyValue , InvalidValueType , InvalidParameterValue ,
911)
1012
1113log = logging .getLogger (__name__ )
1214
15+ PARAMETER_STYLE_DESERIALIZERS = {
16+ ParameterStyle .FORM : lambda x : x .split (',' ),
17+ ParameterStyle .SIMPLE : lambda x : x .split (',' ),
18+ ParameterStyle .SPACE_DELIMITED : lambda x : x .split (' ' ),
19+ ParameterStyle .PIPE_DELIMITED : lambda x : x .split ('|' ),
20+ }
21+
1322
1423class Parameter (object ):
1524 """Represents an OpenAPI operation Parameter."""
1625
1726 def __init__ (
1827 self , name , location , schema = None , required = False ,
1928 deprecated = False , allow_empty_value = False ,
20- items = None , collection_format = None ):
29+ items = None , style = None , explode = None ):
2130 self .name = name
22- self .location = location
31+ self .location = ParameterLocation ( location )
2332 self .schema = schema
24- self .required = True if self .location == "path" else required
33+ self .required = (
34+ True if self .location == ParameterLocation .PATH else required
35+ )
2536 self .deprecated = deprecated
2637 self .allow_empty_value = (
27- allow_empty_value if self .location == "query" else False
38+ allow_empty_value if self .location == ParameterLocation .QUERY
39+ else False
2840 )
2941 self .items = items
30- self .collection_format = collection_format
42+ self .style = ParameterStyle (style or self .default_style )
43+ self .explode = self .default_explode if explode is None else explode
44+
45+ @property
46+ def aslist (self ):
47+ return (
48+ self .schema and
49+ self .schema .type in [SchemaType .ARRAY , SchemaType .OBJECT ]
50+ )
51+
52+ @property
53+ def default_style (self ):
54+ simple_locations = [ParameterLocation .PATH , ParameterLocation .HEADER ]
55+ return (
56+ 'simple' if self .location in simple_locations else "form"
57+ )
58+
59+ @property
60+ def default_explode (self ):
61+ return self .style == ParameterStyle .FORM
62+
63+ def get_dererializer (self ):
64+ return PARAMETER_STYLE_DESERIALIZERS [self .style ]
65+
66+ def deserialize (self , value ):
67+ if not self .aslist or self .explode :
68+ return value
69+
70+ deserializer = self .get_dererializer ()
71+ return deserializer (value )
3172
3273 def unmarshal (self , value ):
3374 if self .deprecated :
@@ -36,69 +77,73 @@ def unmarshal(self, value):
3677 DeprecationWarning ,
3778 )
3879
39- if (self .location == "query" and value == "" and
80+ if (self .location == ParameterLocation . QUERY and value == "" and
4081 not self .allow_empty_value ):
4182 raise EmptyValue (
4283 "Value of {0} parameter cannot be empty" .format (self .name ))
4384
4485 if not self .schema :
4586 return value
4687
88+ deserialized = self .deserialize (value )
89+
4790 try :
48- return self .schema .unmarshal (value )
91+ return self .schema .unmarshal (deserialized )
4992 except InvalidValueType as exc :
5093 raise InvalidParameterValue (str (exc ))
5194
5295
96+ class ParameterFactory (object ):
97+
98+ def __init__ (self , dereferencer , schemas_registry ):
99+ self .dereferencer = dereferencer
100+ self .schemas_registry = schemas_registry
101+
102+ def create (self , parameter_spec , parameter_name = None ):
103+ parameter_deref = self .dereferencer .dereference (parameter_spec )
104+
105+ parameter_name = parameter_name or parameter_deref ['name' ]
106+ parameter_in = parameter_deref .get ('in' , 'header' )
107+
108+ allow_empty_value = parameter_deref .get ('allowEmptyValue' )
109+ required = parameter_deref .get ('required' , False )
110+
111+ style = parameter_deref .get ('style' )
112+ explode = parameter_deref .get ('explode' )
113+
114+ schema_spec = parameter_deref .get ('schema' , None )
115+ schema = None
116+ if schema_spec :
117+ schema , _ = self .schemas_registry .get_or_create (schema_spec )
118+
119+ return Parameter (
120+ parameter_name , parameter_in ,
121+ schema = schema , required = required ,
122+ allow_empty_value = allow_empty_value ,
123+ style = style , explode = explode ,
124+ )
125+
126+
53127class ParametersGenerator (object ):
54128
55129 def __init__ (self , dereferencer , schemas_registry ):
56130 self .dereferencer = dereferencer
57131 self .schemas_registry = schemas_registry
58132
59133 def generate (self , parameters ):
60- for parameter_name , parameter in iteritems (parameters ):
61- parameter_deref = self .dereferencer .dereference (parameter )
62-
63- parameter_in = parameter_deref .get ('in' , 'header' )
64-
65- allow_empty_value = parameter_deref .get ('allowEmptyValue' )
66- required = parameter_deref .get ('required' , False )
67-
68- schema_spec = parameter_deref .get ('schema' , None )
69- schema = None
70- if schema_spec :
71- schema , _ = self .schemas_registry .get_or_create (schema_spec )
72-
73- yield (
74- parameter_name ,
75- Parameter (
76- parameter_name , parameter_in ,
77- schema = schema , required = required ,
78- allow_empty_value = allow_empty_value ,
79- ),
80- )
134+ for parameter_name , parameter_spec in iteritems (parameters ):
135+ parameter = self .parameter_factory .create (
136+ parameter_spec , parameter_name = parameter_name )
137+
138+ yield (parameter_name , parameter )
81139
82140 def generate_from_list (self , parameters_list ):
83- for parameter in parameters_list :
84- parameter_deref = self .dereferencer .dereference (parameter )
85-
86- parameter_name = parameter_deref ['name' ]
87- parameter_in = parameter_deref .get ('in' , 'header' )
88-
89- allow_empty_value = parameter_deref .get ('allowEmptyValue' )
90- required = parameter_deref .get ('required' , False )
91-
92- schema_spec = parameter_deref .get ('schema' , None )
93- schema = None
94- if schema_spec :
95- schema , _ = self .schemas_registry .get_or_create (schema_spec )
96-
97- yield (
98- parameter_name ,
99- Parameter (
100- parameter_name , parameter_in ,
101- schema = schema , required = required ,
102- allow_empty_value = allow_empty_value ,
103- ),
104- )
141+ for parameter_spec in parameters_list :
142+ parameter = self .parameter_factory .create (parameter_spec )
143+
144+ yield (parameter .name , parameter )
145+
146+ @property
147+ @lru_cache ()
148+ def parameter_factory (self ):
149+ return ParameterFactory (self .dereferencer , self .schemas_registry )
0 commit comments