"""Input Conversion Routines""" import re import simplejson from turbogears import validators from tgwebservices.runtime import primitives namespace_expr = re.compile(r'^\{.*\}') def boolean_converter(value): value = value.lower() if value in ["", "false", "0", "no", "off", "f", "n"]: return False if value in ["true", "1", "yes", "on", "y", "t"]: return True raise validators.Invalid("%s is not a legal boolean value" % (value), value, None) def _get_single_value(elem, itype): """Converts a single XML element into the given type""" if isinstance(itype, list): itemtype = itype[0] items = [] for subelem in elem.getchildren(): items.append(_get_single_value(subelem, itemtype)) return items if not isinstance(itype, type): itype = type(itype) if itype not in primitives: return _xml_to_instance(elem, itype) if itype == bool: itype = boolean_converter if elem.text is None: text = "" else: text = elem.text try: return itype(text) except ValueError: raise validators.Invalid( "%s value for the '%s' parameter is not a " "valid %s" % (text, namespace_expr.sub("", elem.tag), itype.__name__), text, None) def _xml_to_instance(input, cls): """Converts an input element into a new instance of cls.""" instance = cls() for elem in input.getchildren(): tag = namespace_expr.sub("", elem.tag) try: itype = getattr(cls, tag) except AttributeError: raise validators.Invalid("%s is an unknown tag for a %s" % (tag, cls.__name__), tag, None) setattr(instance, tag, _get_single_value(elem, itype)) return instance def handle_xml_params(body, input_types): kw = {} for elem in body.getchildren(): param = namespace_expr.sub("", elem.tag) try: itype = input_types[param] except KeyError: raise validators.Invalid( "%s is not a valid parameter (valid values are: %s)" % (param, input_types.keys()), param, None ) kw[param] = _get_single_value(elem, itype) return kw def handle_keyword_params(kw, input_types): # convert the input parameters to appropriate types for key in kw: if key in input_types: try: converter = input_types[key] if converter == bool: converter = boolean_converter kw[key] = converter(kw[key]) except ValueError: raise validators.Invalid( "%s value for the '%s' parameter is not a " "valid %s" % (kw[key], key, input_types[key].__name__), kw[key], None) else: raise validators.Invalid( "%s is not a valid parameter (valid values are: %s)" % (key, input_types.keys()), key, None ) def _get_json_value(value, itype): if isinstance(itype, list): itemtype = itype[0] return [_get_json_value(item, itemtype) for item in value] elif not isinstance(itype, type): return _get_json_value(value, type(itype)) elif itype not in primitives and isinstance(value, dict): return _create_instance_from_json(value, itype) return itype(value) def _create_instance_from_json(value, cls): instance = cls() for key in value: try: itype = getattr(cls, key) except AttributeError: raise validators.Invalid("%s is an unknown parameter for a %s" % (key, cls.__name__), key, None) setattr(instance, str(key), _get_json_value(value[key], itype)) return instance def handle_json_params(input, input_types): if isinstance(input, basestring): try: input = simplejson.loads(input) except ValueError: raise validators.Invalid("Invalid JSON input") kw = {} for key in input: if key in input_types: kw[str(key)] = _get_json_value(input[key], input_types[key]) else: raise validators.Invalid( "%s is not a valid parameter (valid values are: %s)" % (key, input_types.keys()), key, None ) return kw