Changeset 19
- Timestamp:
- 02/28/07 09:26:07 (2 years ago)
- Files:
-
- trunk/tgwebservices/controllers.py (modified) (4 diffs)
- trunk/tgwebservices/soap.py (modified) (3 diffs)
- trunk/tgwebservices/tests/test_controllers.py (added)
- trunk/tgwebservices/tests/test_soap.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/tgwebservices/controllers.py
r18 r19 22 22 from tgwebservices import soap 23 23 from tgwebservices.runtime import register, primitives, \ 24 FunctionInfo, register_complex_type 24 FunctionInfo, register_complex_type, \ 25 ctvalues 25 26 26 27 config.update({"tg.empty_flash" : False}) … … 117 118 value, None) 118 119 120 def _get_single_value(elem, itype): 121 """Converts a single XML element into the given type""" 122 if isinstance(itype, list): 123 itemtype = itype[0] 124 items = [] 125 for subelem in elem.getchildren(): 126 items.append(_get_single_value(subelem, itemtype)) 127 return items 128 if not isinstance(itype, type): 129 itype = type(itype) 130 if itype not in primitives: 131 return _xml_to_instance(elem, itype) 132 if itype == bool: 133 itype = boolean_converter 134 135 if elem.text is None: 136 text = "" 137 else: 138 text = elem.text 139 140 try: 141 return itype(text) 142 except ValueError: 143 raise validators.Invalid( 144 "%s value for the '%s' parameter is not a " 145 "valid %s" % (text, soap.namespace_expr.sub("", elem.tag), 146 itype.__name__), 147 text, None) 148 149 def _xml_to_instance(input, cls): 150 """Converts an input element into a new instance of cls.""" 151 instance = cls() 152 for elem in input.getchildren(): 153 tag = soap.namespace_expr.sub("", elem.tag) 154 try: 155 itype = getattr(cls, tag) 156 except AttributeError: 157 raise validators.Invalid("%s is an unknown tag for a %s" 158 % (tag, cls.__name__), 159 tag, None) 160 setattr(instance, tag, _get_single_value(elem, itype)) 161 return instance 162 163 class ComplexConverter(object): 164 pass_xml = True 165 166 def __init__(self, cls): 167 self.cls = cls 168 169 def __call__(self, val): 170 return _get_single_value(val, self.cls) 171 172 def _handle_xml_params(body, input_types): 173 kw = {} 174 for elem in body.getchildren(): 175 param = soap.namespace_expr.sub("", elem.tag) 176 try: 177 itype = input_types[param] 178 except KeyError: 179 raise validators.Invalid( 180 "%s is not a valid parameter (valid values are: %s)" 181 % (param, input_types.keys()), param, None 182 ) 183 kw[param] = _get_single_value(elem, itype) 184 return kw 185 186 def _handle_keyword_params(kw, input_types): 187 # convert the input parameters to appropriate types 188 for key in kw: 189 if key in input_types: 190 try: 191 converter = input_types[key] 192 if converter == bool: 193 converter = boolean_converter 194 kw[key] = converter(kw[key]) 195 except ValueError: 196 raise validators.Invalid( 197 "%s value for the '%s' parameter is not a " 198 "valid %s" % (kw[key], key, 199 input_types[key].__name__), 200 kw[key], None) 201 else: 202 raise validators.Invalid( 203 "%s is not a valid parameter (valid values are: %s)" 204 % (key, input_types.keys()), key, None 205 ) 206 119 207 def wsvalidate(*args, **kw): 120 208 """Validates and converts incoming parameters. Also registers the … … 132 220 for i in range(0, len(args)): 133 221 argtype = args[i] 134 if argtype is bool:135 argtype = boolean_converter136 222 input_types[fi.params[i]] = argtype 137 223 … … 140 226 141 227 def newfunc(self, **kw): 142 # convert the input parameters to appropriate types 143 for key in kw: 144 if key in input_types: 145 try: 146 kw[key] = input_types[key](kw[key]) 147 except ValueError: 148 raise validators.Invalid( 149 "%s value for the '%s' parameter is not a " 150 "valid %s" % (kw[key], key, 151 input_types[key].__name__), 152 kw[key], None) 153 else: 154 raise validators.Invalid( 155 "%s is not a valid parameter (valid values are: %s)" 156 % (key, input_types.keys()), key, None 157 ) 228 if "xml_body" in kw and len(kw) == 1: 229 body = kw.pop("xml_body") 230 kw = _handle_xml_params(body, input_types) 231 else: 232 _handle_keyword_params(kw, input_types) 233 158 234 return func(self, **kw) 159 235 newfunc.__name__ = func.__name__ trunk/tgwebservices/soap.py
r13 r19 190 190 request.soap_method = methodname 191 191 192 # pull out all of the parameters193 params = {}194 for paramelem in body.getchildren():195 paramname = namespace_expr.sub("", paramelem.tag)196 val = paramelem.text197 if val is None:198 val = ""199 params[paramname] = val200 201 192 try: 202 193 method = self.wscontroller._ws_funcs[methodname] … … 205 196 methodname, methodname, None) 206 197 198 fi = method._ws_func_info 199 input_types = fi.input_types 200 201 params = {"_tgws" : True} 202 if len(body.getchildren()): 203 params["xml_body"] = body 204 207 205 # ensure that the requested method has actually been exposed 208 206 assert hasattr(method, "exposed") and method.exposed == True … … 211 209 # in wsexpose. We want to manage the produced dictionary here, because 212 210 # we need to pass additional information on to the soap template. 213 params["_tgws"] = True214 211 output = method(**params) 215 212 data = dict(baseURL=self.wscontroller._ws_baseURL, trunk/tgwebservices/tests/test_soap.py
r13 r19 293 293 output = run_soap("times2", """<value>whaleblubber</value>""") 294 294 print cherrypy.response.status 295 print output 295 296 assert cherrypy.response.status == "500 Invalid Input" 296 print output297 297 assert output == """<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><Fault><faultcode>Client</faultcode><faultstring>whaleblubber value for the 'value' parameter is not a valid int</faultstring></Fault></Body></Envelope>""" 298 298 … … 432 432 print output 433 433 assert "fault" not in output 434 435 class Person(object): 436 name = str 437 age = int 438 439 class ComplexInput(WebServicesRoot): 440 @wsexpose() 441 @wsvalidate(Person) 442 def savePerson(self, p): 443 self.person = p 444 445 def test_complex_input_simple_object(): 446 ci = ComplexInput("http://foo.bar.baz/") 447 cherrypy.root = ci 448 output = run_soap("savePerson", """<p> 449 <name>George</name> 450 <age>280</age> 451 </p>""") 452 print output 453 assert isinstance(ci.person, Person)
